动态组件 什么是动态组件 动态组件指的是动态切换组件的显示与隐藏
动态组件的渲染 vue 提供了一个内置的 <component>
组件,专门用来实现动态组件的渲染,它就相当于组件的占位符,提供一个 is
属性用来指定该位置实际需要渲染的组件,通过控制 is
属性的值可以实现组件的切换
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 <template > <div class ="app-container" > <h1 > App 根组件</h1 > <button @click ="comName = 'Left'" > 展示 Left</button > <button @click ="comName = 'Right'" > 展示 Right</button > <div class ="box" > <component :is ="comName" > </component > </div > </div > </template > <script > import Left from '@/components/Left.vue' import Right from '@/components/Right.vue' export default { data ( ) { return { comName : 'Left' } }, components : { Left , Right } } </script >
使用 keep-alive 保持动态组件状态 在上面使用<component>
标签来切换组件时,默认情况下,被切换的组件时无法保持组件的状态。此时可以使用 vue 内置的 <keep-alive>
组件保持动态组 件的状态,在使用时,我们只需要使用<keep-alive>
将<component>
组件包裹起来就好了
1 2 3 4 <keep-alive > <component :is ="comName" > </component > </keep-alive >
keep-alive 的生命周期 当组件被keep-alive包裹时,会多两个生命周期函数 deactivated
和 activated
当组件被缓存时,会自动触发组件的 deactivated 生命周期函数。 当组件被激活时,会自动触发组件的 activated 生命周期函数。
我们只需要给被包含的组件 定义这两个函数就可以进行使用了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 export default { data ( ) { return { count : 0 } }, created ( ) { console .log ('Left 组件被创建了!' ) }, destroyed ( ) { console .log ('Left 组件被销毁了~~~' ) }, activated ( ) { console .log ('组件被激活了,activated' ) }, deactivated ( ) { console .log ('组件被缓存了,deactivated' ) } } </script>
keep-alive 的include和exclude属性 include
属性用来指定:只有名称匹配的组件 会被缓存。多个组件名之间使用英文的逗号
分隔exclude
属性用来指定:名称匹配的组件 不会被缓存。多个组件名之间使用英文的逗号
分隔
不要同时使用 include 和 exclude 这两个属性
1 2 3 4 5 <keep-alive exclude ="MyRight" > <component :is ="comName" > </component > </keep-alive >
组件的声明和注册名称 注册名称:就是我们在使用该组件 时,父组件的 components
节点中写的名称
声明名称:我们可以在组件声明(即编写封装组件的.vue
文件时)通过 name
节点来给组件指定的名称,我们建议每个封装的组件都有自己的声明的名称
如果在声明组件 的时候,没有为组件指定 name 名称,则组件的名称 默认就是注册时候的名称
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <script> import Left from '@/components/Left.vue' import Right from '@/components/Right.vue' export default { data ( ) { return { comName : 'Left' } }, components : { Left , Right } } </script>
1 2 3 4 5 6 7 8 9 10 <script> export default { name : 'MyRight' } </script>
插槽 插槽(Slot)是 vue 为组件的封装者提供的能力。允许开发者在封装组件时,把不确定的、希望由用户指定的部分定义为插槽。
可以把插槽认为是组件封装期间,为用户预留的内容的占位符。
插槽快速使用 在封装组件时,可以通过 元素定义插槽,从而为用户预留内容占位符
在声明left.vue
组件时,通过 <slot>
来定义插槽
1 2 3 4 5 6 7 <template > <div class ="left-container" > <h3 > Left 组件</h3 > <slot > </slot > </div > </template >
在app.vue
组件中使用
1 2 3 <left> <p>这是在left组件的内容区域生命的p标签</p> </left>
v-slot 指令 我们定义插槽时,官方规定每个插槽都要有一个 name
名称,如果省略了 slot 的 name
属性,则有一个默认名称叫做 default
,默认情况下,在使用组件的时候,提供的内容都会被填充到名字为 default
的插槽之中,当我们有很多插槽时,我们应该给每个插槽一个不同的 name
,这样有自己名字的插槽叫做 具名插槽
在定义插槽时,可以通过在slot
标签内部写入信息,指定该插槽的后备内容,当使用了该插槽但没有指定插入内容时,会显示后备内容
比如在声明left.vue
组件时,通过 name
来定义插槽名称
1 2 3 4 5 6 7 8 9 10 11 12 <template > <div class ="left-container" > <h3 > Left 组件</h3 > <hr /> <slot name ="default" > <h6 > 这是 default 插槽的后备内容</h6 > </slot > </div > </template >
当我们有很多插槽时,我们可以通过v-slot指令来指定需要进行操作的插槽
v-slot: 指令不能直接用在元素身上,必须用在 template 标签上
v-slot: 指令的简写形式是 #
在app.vue
组件中使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 <template > <div class ="app-container" > <div class ="box" style ="display: none;" > <Left > <template #default > <p > 这是在 Left 组件的内容区域,声明的 p 标签</p > </template > </Left > </div > </div > </template >
作用域插槽 在封装组件时,为预留的slot
提供属性对应的值,这种用法叫做作用域插槽
在下方实例中,给slot
提供了msg这个属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <div class ="content-box" > <slot name ="content" msg ="hello vue.js" :user ="userinfo" > </slot > </div > <script > export default { name : 'Article' , data ( ) { return { userinfo : { name : 'zs' , age : 20 } } } } </script >
当我们使用时,可以通过 =
来接收该属性值和其数据,scope
就是个形参变量,想写什么都好,习惯使用 scope
1 2 3 4 5 <template #content ="scope" > <div > <p > {{ scope.msg }}</p > </div > </template >
同样,也可以使用解构赋值的方法来使用该数据
1 2 3 4 5 6 <template #content="{ msg, user }"> <div> <p>{{ msg }}</p> <p>{{ user.name }}</p> </div> </template>
自定义指令 什么是自定义指令 vue 官方提供了 v-text、v-for、v-model、v-if 等常用的指令。除此之外 vue 还允许开发者自定义指令。
自定义指令的分类 vue 中的自定义指令分为两类,分别是:
私有 自定义指令
全局 自定义指令
私有自定义指令 在每个vue组件之中,可以在 directives
节点下声明私有自定义指令
在下面代码中,自定义一个 v-color
指令来改变标签颜色
当指令第一次被绑定到元素上的时候,会立即触发 bind
函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <template > <div class ="app-container" > <h1 v-color > App 根组件</h1 > </div > </template > <script > export default { directives : { color : { bind (el ) { console .log ('触发了 v-color 的 bind 函数' ) el.style .color = 'red' } } } } </script >
为自定义指令动态绑定参数值 在 template 结构中使用自定义指令时,可以通过等号(=)的方式,为当前指令动态绑定参数值
并且在声明自定义指令时,可以通过形参中的第二个参数,来接收指令的参数值,习惯性的第二个参数我们叫做 binding
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 <template > <div class ="app-container" > <h1 v-color ="color" > App 根组件</h1 > <p v-color ="'red'" > 测试</p > </div > </template > <script > export default { data ( ) { return { color : 'blue' } }, directives : { color : { bind (el, binding ) { console .log (binding) console .log ('触发了 v-color 的 bind 函数' ) el.style .color = binding.value } } } } </script >
指令的update函数 bind 函数只调用 1 次:当指令第一次绑定到元素时调用,当 DOM 更新时 bind
函数不会被触发。 update
函数会在每次 DOM 更新时被调用。
下面实现点击按钮后,颜色数据改变,同时页面标签颜色渲染改变,指令的 update
函数,当元素变化时,所有使用该指令的组件都会触发update函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 <template > <div class ="app-container" > <h1 v-color ="color" > App 根组件</h1 > <p v-color ="'red'" > 测试</p > <button @click ="color = 'green'" > 改变 color 的颜色值</button > </div > </template > <script > export default { data ( ) { return { color : 'blue' } }, directives : { color : { bind (el, binding ) { console .log (binding) console .log ('触发了 v-color 的 bind 函数' ) el.style .color = binding.value }, update (el, binding ) { console .log ('触发了 v-color 的 update 函数' ) el.style .color = binding.value } } } } </script >
自定义指令的简写 我们会发现 bind
和 update
这两个函数,除了函数名不同,其他都相同,写两遍比较麻烦,所以vue提供了自定义指令的简写方式
如果 bind
和 update
函数中的逻辑完全相同,则对象格式的自定义指令可以简写成函数格式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 <template > <div class ="app-container" > <h1 v-color ="color" > App 根组件</h1 > <p v-color ="'red'" > 测试</p > <button @click ="color = 'green'" > 改变 color 的颜色值</button > </div > </template > <script > export default { data ( ) { return { color : 'blue' } }, directives : { color (el, binding ) { console .log (binding) el.style .color = binding.value } } } </script >
全局自定义指令 上面在组件的.vue
文件中定义的指令只能在自己的组件中使用,我们可以像定义全局过滤器一样在main.js
中定义全局自定义指令
1 2 3 4 5 6 7 8 9 10 11 12 Vue .directive ('color' , function (el, binding ) { el.style .color = binding.value })