动态组件
动态组件指的是动态切换组件的显示与隐藏。vue提供了一个内置的<component>组件,专门用来实现动态组件的渲染。
is
is属性的值,表示要渲染组件的名字,可以通过修改data里的值来进行动态渲染。
在App组件中使用的例子:
<component :is="flag"></component> ... data(){ return{ //动态渲染left组件 flag:'left' } },
隐藏(切换)的组件会被销毁,而显示的组件会被重新创建一个新的组件。
插槽
它是vue为组件的封装者提供的能力,允许开发者在封装组件时,把不确定、希望由使用者自己指定的部分定义为插槽(slot)。
基本用法
使用组件者自定义内容并用v-slot指定填充到的插槽名称
在App中的例子
<template> <div> <left> <!-- template和上面的标签不一样,它不会被渲染成任何结构,只起包裹作用。v-slot只能用在template标签上,它可以简写成#,即#leftChaCao--> <template v-slot:leftChaCao> <p>目前我显示不了,因为我是使用组件者自定义的内容</p> </template> </left> <div> <template>
在left组件某个地方中使用slot声明一个插槽区域,就会自动填充上面自定义的内容了。
<!-- 声明一个插槽区域 --> <slot name="leftChaCao"> 标签里可以放leftChaCao插槽的后备内容(默认内容)(没有被自定义,内容就会被显示) </slot>
接着在App自定义的内容就会被填充到left中声明的这个插槽区域,就可以显示了。
具名插槽
<!-- 声明一个插槽区域 --> <slot name="leftChaCao"> 标签里可以放leftChaCao插槽的后备内容(默认内容)(没有被自定义内容就会被显示) </slot>
作用域插槽
在封装组件时,为预留的<slot>提供属性对应的数据,也可以理解成子传父,即把数据传给了外面使用它的组件。也就是通过插槽可以接收到插槽身上给我们传过来的数据。
<!-- 声明一个同时兼有具名和作用域的插槽区域 --> <slot name="leftChaCao" mes="zzl"> 标签里可以放leftChaCao插槽的后备内容(默认内容)(没有被自定义内容就会被显示) </slot>
使用组件者自定义内容时可以接收到这个对象。
<template> <div> <left> <!-- 指定插槽的名称,它和上面的标签不一样,它不会被渲染成任何结构,只起包裹作用,它只能用在template标签上,它可以简写成#,即#leftChaCao--> <template #leftChaCao="obj"> <p>目前我显示不了,因为我是使用组件者自定义的内容</p> <p>{{obj.mes}}</p> <!-- 上面会显示zzl --> </template> </left> <div> <template>
作用域插槽的解构赋值
在子组件中
<!-- 声明一个同时兼有具名和作用域的插槽区域 --> <slot name="leftChaCao" mes="zzl" :user="info"> 标签里可以放leftChaCao插槽的后备内容(默认内容)(没有被自定义内容就会被显示) </slot> ... <script> export default{ data(){ return{ info:{ name:'wxl', age:18 } } } } </script>
在父组件中
<template> <div> <left> <template #leftChaCao="{mes,info}"> <p>目前我显示不了,因为我是使用组件者自定义的内容</p> <p>{{mes}}</p> <p>{{info.name}}</p> </template> </left> <div> <template>
自定义指令
当需要对dom进行底层操作时,可以使用自定义指令。
私有自定义指令
在每一个vue组件中,可以在directives节点下声明私有自定义指令。
<template> <div class="rootbox"> <h1 v-color>App根组件</h1> </div> </template> ... directives:{ //定义名为color的指令,指向一个配置对象,使用的时候是v-color,同下。 color:{ //vue3方法,当指令第一次被挂载到元素上的时候,会立即触发mounted函数 mounted(el){ console.log("v-color被这个页面挂载了") el.style.color='red' }, //vue2方法,当指令第一次被绑定到元素上的时候,会立即触发bind函数 //形参中的el表示当前指令所绑定的那个dom对象 bind(el){ console.log('触发了v-color的bind函数') el.style.color='red' } } }, data(){ }
vue2与vue3自定义指令还是有很大的差别的,具体可以参考vue官网,里面包含自定义指令的所有生命周期函数
binding.value获取指令绑定的值
<template> <div class="rootbox"> <h1 v-color="blue">App根组件</h1> <h1 v-color="'red'">App根组件2</h1> </div> </template> ... directives:{ //定义名为color的指令,指向一个配置对象 color:{ //当指令 【第一次】 被绑定到元素上的时候,会立即触发bind函数 //形参中的el表示当前指令所绑定的那个dom对象 bind(el,binding){ console.log('触发了v-color的bind函数',binging) el.style.color=binging.value } } }, data(){ return{ blue : 'blue' } }
update函数
bind函数的缺点是只调用1次:当指令第一次绑定到元素时会立即触发bind函数,但当dom更新时,bind函数不会再被触发了。
此时用update函数就可以在每次dom更新时都触发。
<template> <div class="rootbox"> <button @click="color='green'">变App根组件1的颜色</button> <h1 v-color="color">App根组件1</h1> <h1 v-color="'red'">App根组件2</h1> </div> </template> ... directives:{ //定义名为color的指令,指向一个配置对象 color:{ //当指令 【第一次】 被绑定到元素上的时候,会立即触发bind函数 //形参中的el表示当前指令所绑定的那个dom对象 bind(el,binding){ console.log('触发了v-color的bind函数',binging) el.style.color=binging.value }, //当dom更新时,会触发update函数,此时就又可以实现上面的需求了 update(el,binding){ console.log('触发了v-color的update函数',binging) el.style.color=binding.value } } }, data(){ return{ color : 'blue' } }
自定义指令简写形式
当bind和update函数中的逻辑完全相同,则对象格式的自定义指令可以简写成函数格式,所以上面代码可以简写为下面部分:
<template> <div class="rootbox"> <button @click="color='green'">变App根组件1的颜色</button> <h1 v-color="color">App根组件1</h1> <h1 v-color="'red'">App根组件2</h1> </div> </template> ... directives:{ color(el,binding){ el.style.color=binding.value } }, data(){ return{ color : 'blue' } }
全局自定义指令
全局共享的自定义指令需要在main.js里通过Vue.directive()进行声明。
参数1:字符串,表示全局自定义指令的名字 参数2:对象,用来接收指令的参数值 //参数2简写形式 Vue.directive('color',function(el,binding){ el.style.color=binding.value }) //vue3写法 //const app = createApp(App) //app.directive() //不简写形式 Vue.directive('color',{ bing(el,binding){ el.style.color=binding.value }, update(el,binding){ el.style.color=binding.value } })