irpas技术客

Vue 3.0 组件高级(下)_一只淡水鱼

网络 1324

一、ref 引用 1. 什么是 ref 引用

ref 用来辅助开发者在不依赖于 jQuery 的情况下,获取 DOM 元素或组件的引用。

每个 vue 的组件实例上,都包含一个 $refs 对象,里面存储着对应的 DOM 元素或组件的引用。默认情况下,组件的 $refs 指向一个空对象。

2. 使用 ref 引用 DOM 元素 <!--使用ref属性,为对应dom添加引用名称--> <h3 ref="myh3">myref</h3> <button @click="getRef">获取对ref的引用</button> methods:{ getRef(){ //通过this.$refs.引用的名称,可获取dom元素的引用 console.log(this.$refs.myh3) //操作dom元素,把文本颜色改为红色 this.$refs.myh3.style.color='red' }, } 3. 使用 ref 引用组件实例 <!--使用ref属性,为对应dom添加引用名称--> <my-counter ref="counterRef"></my-counter> <button @click="getRef">获取对ref的引用</button> methods:{ getRef(){ //引用到组件的实例之后,就可以调用组件上的methods方法 this.$refs.counterRef.add() } } 4. 控制文本框和按钮的按需切换

通过布尔值 inputVisible

<template> <input type="text" v-if="inputVisible"> <button v-else @click='showInput"></button> </template> export default{ data(){ return{ inputVisible: false, } }, methods:{ showInput(){ this.inputVisible = true }, }, } 5. 让文本框自动获得焦点

当文本框展示出来之后,如果希望它立即获得焦点,则可以为其添加 ref 引用,并调用原生 DOM 对象的.focus()

<template> <input type="text" v-if="inputVisible ref="ipt"> <button v-else @click='showInput"></button> </template> methods:{ showInput(){ this.inputVisible=true //获取文本框的dom引用,并调用.focus()获得焦点 this.$refs.ipt.focus() } }

以上代码会报错,是因为组件dom的渲染是异步的。this.$refs.ipt.focus()执行时dom还没渲染。

6. this.$nextTick(cb) 方法

$nextTick(cb) 会把 cb 回调推迟到下一个 DOM 更新周期之后执行。通俗的理解是:等组件的DOM 异步地重新渲染完成后,再执行 cb 回调函数。从而能保证 cb 回调函数可以操作到最新的 DOM 元素。

<template> <input type="text" v-if="inputVisible ref="ipt"> <button v-else @click='showInput"></button> </template> methods:{ showInput(){ this.inputVisible=true //把对input文本框的操作,推迟到下一次dom更新之后,否则页面上根本不存在文本框元素 this.$nextTick(()=>{ this.$refs.ipt.focus() }) } } 二、动态组件 1. 什么是

动态切换组件的显示与隐藏。vue 提供了一个内置的 <component> 组件,专门用来实现组件

的动态渲染。

① <component> 是组件的占位符

② 通过 is 属性动态指定要渲染的组件名称

③ <component is="要渲染的组件的名称"></component>

data(){ return{ //1.当前要渲染的组件名称 comName: 'myhome' } } <template> //3. 点击按钮,动态切换组件名称 <button @click="comName='myhome'"></button> <button @click="comName='mymovie'"></button> //2. 通过is属性,动态指定要渲染的组件名称 <component :is="comName"></component> </template> 2.?使用 keep-alive 保持状态

默认情况下,切换动态组件时无法保持组件的状态。可以使用 vue 内置的?<keep-alive>?组件保持动态组件的状态。

<keep-alive> <component :is="comName"></component> </keep-alive> 三、插槽 1. 什么是插槽

在封装组件时,把不确定的、希望由用户指定的部分定义为插槽。

2. 插槽的基础用法

在封装组件时,可以通过?<slot>?元素定义插槽,从而为用户预留内容占位符。

如果在封装组件时没有预留任何 <slot> 插槽,则用户提供的任何自定义内容都会被丢弃。

<template> <p>aaa</p> <slot></slot> <p>aaa</p> </template> <my-com-1> <p>自定义内容</p> </my-com-1>

后备内容:

可以为预留的 <slot> 插槽提供后备内容(默认内容)。如果组件的使用者没有为插槽提供任何

内容,则后备内容会生效。

<template> <p>aaa</p> <slot>默认内容</slot> <p>aaa</p> </template> 3. 具名插槽

如果在封装组件时需要预留多个插槽节点,则需要为每个 <slot> 插槽指定具体的 name 名称。

<div class="container"> <header> <slot name="header"></slot> </header> <main> <slot></slot> </main> <footer> <slot name="footer"></slot> </footer> </div>

注意:没有指定 name 名称的插槽,会有隐含的名称叫做 “default”。

<my-com-2> <template v-slot:header> <h1>头部</h1> </template> <template v-slot:default> <p>内容</p> </template> <template v-slot:footer> <p>尾部</p> </template> </my-com-2>

向具名插槽提供内容的时候,在?<template>?元素上使用?v-slot?指令,并以 v-slot 的参数的形式提供其名称。

简写形式:v-slot:?替换为字符?#

<my-com-2> <template #header> <h1>头部</h1> </template> <template #default> <p>内容</p> </template> <template #footer> <p>尾部</p> </template> </my-com-2> 4. 作用域插槽

在封装组件的过程中,可以为预留的 <slot> 插槽绑定 props 数据。

<div> <slot :info="information"></slot> </div> <my-test> <template v-slot:default="scope"> {{ scope }} </template> </my-test>

解构作用域插槽的 Prop

<my-table> <template #default="{ user }"> <td>{{ user.id }}</td> <td>{{ user.name }}</td> <td>{{ user.state }}</td> </template> </my-table>

在封装 MyTable 组件的过程中,可以通过作用域插槽把表格每一行的数据传递给组件的使用者。

<tbody> <tr v-for="item in list" :key="item.id"> <slot :user="item"></slot> </tr> </tbody>

在使用 MyTable 组件时,自定义单元格的渲染方式,并接收作用域插槽对外提供的数据。

<my-table> <template #default="{ user }"> <td>{{ user.id }}</td> <td>{{ user.name }}</td> <td> <input type="checkbox" :checked="user.state"> </td> </template> </my-table> 四、自定义指令 1.?私有自定义指令

在每个 vue 组件中,可以在?directives?节点下声明私有自定义指令。

export default{ name: 'Myhome', directives: { //自定义一个私有指令 focus: { //当被绑定的元素插入到dom中时,自动触发mounted函数 mounted(el){ el.focus() //让被绑定的元素自动获得焦点 } } } }

使用自定义指令:需要加上?v-?前缀。

<!-- 声明自定义指令时,指令的名字时focus--> <!--使用自定义指令时,需要加上v-指令前缀--> <input v-focus /> 2. 全局自定义指令

全局共享的自定义指令需要通过“单页面应用程序的实例对象”进行声明。

const app = Vue.createApp({}) //注册一个全局自定义指令 'v-focus' app.directive('focus',{ //当被绑定的元素插入到dom中时,自动触发mounted函数 mounted(el){ el.focus() } }) 3.?updated 函数

mounted 函数只在元素第一次插入 DOM 时被调用,当 DOM 更新时 mounted 函数不会被触发。?updated?函数会在每次 DOM 更新完成后被调用。

app.directive('focus',{ mounted(el){//第一次插入dom时触发这个函数 el.focus() }, updated(el){ //每次dom更新时都会触发updated函数 el.focus() } })

如果 mounted 和updated 函数中的逻辑完全相同,则可以简写:

app.directive('focus',(el) => { //在mounted和updated时都会触发相同的业务逻辑 el.focus() }) 4. 指令的参数值

在绑定指令时,可以通过“等号”的形式为指令绑定具体的参数值.

<input type="text" v-model.number="count" v-focus v-color="'red'"> <p v-color="cyan>{{count}}</p> <button @click="count++">+1</button> app.directive('color', (el,binding) => { el.style.color = binding.value })


1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,会注明原创字样,如未注明都非原创,如有侵权请联系删除!;3.作者投稿可能会经我们编辑修改或补充;4.本站不提供任何储存功能只提供收集或者投稿人的网盘链接。

标签: #Vue #30 #组件高级下 #一ref #引用1 #什么是 #ref #引用ref