Vue.js 2.0 学习笔记(四)动态组件&插槽&自定义指令
一、动态组件
动态组件指动态切换组件的显示与隐藏
1.1 实现动态组件的渲染
vue 提供了一个内置的 <component>
组件,专门用来实现动态组件的渲染,可以认为<component>
就是专门用来给组件占位的占位符
代码如下:
<!-- APP.vue -->
data() {
//1.当前要渲染的组件名称
return {
comName: 'Left'
}
}
<!-- 2.通过 is 属性,动态指定要渲染的组件的名称 -->
<component :is="comName"></component>
<!-- 3.点击按钮,动态切换组件的名称 -->
<button @click="comName = 'Left'">展示 Left</button>
<button @click="comName = 'Right'">展示 Right</button>
重点:
- is 属性的值,表示要渲染的组件的名字,是组件在 components 节点下的注册名称
- component 标签是 vue 内置的,作用:组件的占位符
1.2 keep-alive的使用
默认情况下,切换动态组件时无法保持组件的状态。此时可以使用 vue 内置的 <keep-alive>
组件保持动态组件的状态:
<!-- APP.vue -->
<keep-alive>
<component :is="comName"></component>
</keep-alive>
重点:
- keep-alive 会把内部的组件进行缓存,而不是销毁组件
1.2.1 keep-alive 对应的生命周期函数
当使用了标签keep-alive时:
- 当组件被缓存时,会自动触发组件的 deactivated 生命周期函数。
- 当组件被激活时,会自动触发组件的 activated 生命周期函数。
<!-- APP.vue -->
export default {
created() {
console.log('Left 组件被创建了!');
},
destroyed() {
console.log('Left 组件被销毁了~~~');
},
activated() {
console.log('组件被激活了,activated');
},
deactivated() {
console.log('组件被缓存了,deactivated');
}
}
重点:
- 当组件第一次被创建的时候,既会执行 created 生命周期,也会执行 activated 生命周期,切换展示其他组件时,会执行 deactivated 生命周期
- 但是,当组件被激活的时候,只会触发 activated 生命周期,不再触发 created。因为组件没有被重新创建
1.2.2 keep-alive的 include 和 exclude 属性
<!-- APP.vue -->
<keep-alive include="Right,Left">
<component :is="comName"></component>
</keep-alive>
<!-- APP.vue -->
<keep-alive exclude="Right">
<component :is="comName"></component>
</keep-alive>
重点:
- 在使用 keep-alive 的时候,可以通过 include 指定哪些组件需要被缓存;
- 或者通过 exclude 属性指定哪些组件不需要被缓存;但是:不要同时使用 include 和 exclude 这两个属性
1.3 组件注册名称和组件声明时name的区别
<!-- APP.vue -->
export default {
components: {
// 如果在“声明组件”的时候,没有为组件指定 name 名称,则组件的名称默认就是“注册时候的名称”
Left, //注册名称
Right
}
}
<!-- Left.vue -->
export default {
name: 'MyLeft' // 当提供了 name 属性之后,组件的名称,就是 name 属性的值
}
重点:
- 组件的 “注册名称” 的主要应用场景是:以标签的形式,把注册好的组件,渲染和使用到页面结构之中
- 组件声明时候的 “name” 名称的主要应用场景:结合
<keep-alive>
标签实现组件缓存功能;以及在调试工具中看到组件的 name 名称
二、插槽slot
1.1 slot 的概念
插槽(Slot)是 vue 为组件的封装者提供的能力。允许开发者在封装组件时,把不确定的、希望由用户指定的部分定义为插槽。 让封装的组件更加具有扩展性。可以把插槽认为是组件封装期间,为用户预留的内容的占位符
1.2 插槽使用的例子——移动网站中的导航栏
移动开发中几乎每个页面都有导航栏,我们会将导航栏封装成一个插件,如:nav-bar组件,一旦有了这个组件,我们就可以在多个页面中复用了,但是每个页面的导航栏不是一样的,以京东M站为例:
1.3 插槽的基本使用
在封装组件时,可以通过 <slot>
元素定义插槽,从而为用户预留内容占位符。示例代码如下:
<!-- Left.vue -->
<template>
<h3>Left 组件</h3>
<!-- 通过slot标签,为用户预留内容占位符-->
<!-- 若省略了 slot 的 name 属性,有一个默认名称叫做 default -->
<slot name='default'></slot>
</div>
</template>
<!-- APP.vue -->
<Left>
<!--在使用 Left 组件时,为插槽指定具体的内容-->
<!-- 默认情况下,在使用组件的时候,提供的内容都会被填充到名字为 default 的插槽之中 -->
<p>这是在 Left 组件的内容区域,声明的 p 标签</p>
</Left>
要点:vue 官方规定:每一个 slot 插槽,都要有一个 name 名称,如果省略了 slot 的 name 属性,则有一个默认名称叫做 default
1.3.1 v-slot 指令
作用:若想显式的告诉 vue 要把组件中的内容放到哪个插槽,就可以使用 v-slot:插槽的名字
来完成。
<!-- APP.vue -->
<Left>
<!--在使用 Left 组件时,为插槽指定具体的内容-->
<template v-slot='default'>
<!--或者<template #default>-->
<p>这是在 Left 组件的内容区域,声明的 p 标签</p>
</template>
</Left>
要点:
- 如果要把内容填充到指定名称的插槽中,需要使用 v-slot: 这个指令,v-slot: 后面要跟上插槽的名字
- v-slot: 指令不能直接用在元素身上,必须用在 template 标签上或一个组件上
- template 这个标签是一个虚拟的标签,只起到包裹性质的作用,不会被渲染为任何实质性的 html 元素
- v-slot: 指令的简写形式是 #
1.3.2 插槽的后备内容
如果渲染的组件中没有提供插槽的内容,那么可以在声明插槽时给插槽指定默认显示的内容(后备内容)
<!-- Left.vue -->
<template>
<h3>Left 组件</h3>
<!-- 通过slot标签,为用户预留内容占位符-->
<slot name='default'>这是 default 插槽的默认内容</slot>
</div>
</template>
1.3.3 具名插槽
如果在封装组件时需要预留多个插槽节点,则需要为每个 <slot>
插槽指定具体的 name 名称。这种带有具体名称的插槽叫做“具名插槽”。在向具名插槽提供内容的时候,我们可以在一个 <template>
元素上使用 v-slot 指令,并以 v-slot 的参数的形式提供其名称。
示例1:
示例2:
<!-- APP.vue -->
<Article>
<template #title>
<h3>一首诗</h3>
</template>
<template #content>
<div>
<p>啊,大海,全是水。</p>
<p>啊,蜈蚣,全是腿。</p>
<p>啊,辣椒,净辣嘴。</p>
</div>
</template>
<template #author>
<div>作者:彬果锅</div>
</template>
</Article>
<!--Artical.vue-->
<template>
<div class="article-container">
<!-- 文章的标题 -->
<div class="header-box">
<slot name="title"></slot>
</div>
<!-- 文章的内容 -->
<div class="content-box">
<slot name="content"></slot>
</div>
<!-- 文章的作者 -->
<div class="footer-box">
<slot name="author"></slot>
</div>
</div>
</template>
1.3.4 作用域插槽
1. 编译作用域
考虑个问题,my-cpn 组件是否可以渲染出来呢?
要点:
- 属性是去 vue 实例的模板里面找,而不是去组件 cpn 里面的data找
- 父组件模板的所有东西都会在父级作用域内编译;子组件模板的所有东西都会在子子级作用域里编译。
- 在使用 my-cpn 组件时,整个组件的使用过程相当于在父组件中出现的,即它的作用域就是父组件,使用的也是父组件的属性
2. 作用域插槽的基本使用
在封装组件的过程中,可以为预留的 <slot>
插槽绑定 props 数据(自定义属性),这种带有 props 数据的 <slot>
叫做“作用域插槽”
<!-- Article.vue -->
<template>
<!-- 文章的内容 -->
<div class="content-box">
<!-- 作用域插槽 -->
<slot name="content" msg="hello vue.js" :user="userinfo"></slot>
</div>
</template>
<!-- App.vue -->
<Article>
<template #title>
<h3>一首诗</h3>
</template>
<template #content="scope"> //scope 是个形参,取什么名字都可以
<div>
<p>啊,大海,全是水。</p>
<p>啊,蜈蚣,全是腿。</p>
<p>啊,辣椒,净辣嘴。</p>
<p>{{ scope.msg }}</p>
</div>
</template>
<template #author>
<div>作者:彬果锅</div>
</template>
</Article>
3. 作用域插槽的解构赋值
<!-- Article.vue -->
<template>
<!-- 文章的内容 -->
<div class="content-box">
<!-- 作用域插槽 -->
<slot name="content" msg="hello vue.js" :user="userinfo"></slot>
</div>
</template>
<script>
export default {
// 首字母要大写
name: 'Article',
data() {
return {
// 用户的信息对象
userinfo: {
name: 'zs',
age: 20
}
}
}
}
</script>
<!-- App.vue -->
<Article>
<template #title>
<h3>一首诗</h3>
</template>
<template #content="{msg, user}"> //{}作用是结构对象,若只需要解构出msg,可以用{msg}
<div>
<p>啊,大海,全是水。</p>
<p>啊,蜈蚣,全是腿。</p>
<p>啊,辣椒,净辣嘴。</p>
<p>{{ msg }}</p>
<p>{{ user.name }}</p>
</div>
</template>
<template #author>
<div>作者:彬果锅</div>
</template>
</Article>
三、自定义指令
3.1 自定义指令的分类
vue 中的自定义指令分为两类,分别是:
-
私有自定义指令
-
全局自定义指令
3.2 私有自定义指令
在每个 vue 组件中,可以在 directives 节点下声明私有自定义指令。示例代码如下:
<h1 v-color>hhhhh</h1>
<script>
directives: {
color: {
// 当指令第一次被绑定到元素上时,会立即触发 bind 函数
//为绑定到的HTML元素设置红色的文字
bind(el) { //固定写法
// 形参中的 el 表示当前绑定了此指令的、原生DOM对象
el.style.color = 'red';
}
}
}
</script>
要点:
- 在directives 节点下声明私有自定义指令
- 属性定义时名字前不用加 v
- 使用自定义属性时前面要加 v ,即 v + 自定义属性名
3.3 为自定义指令动态绑定参数值
在 template 结构中使用自定义指令时,可以通过等号(=)的方式,为当前指令动态绑定参数值:
3.4 使用binding.value 获取指令绑定的值
在声明自定义指令时,可以通过形参中的第二个参数,来接收指令的参数值:
<!--App.vue-->
<template>
<!-- color 是一个变量 -->
<h1 v-color="color">App 根组件</h1>
<!-- red加了单引号,是一个字面量值 -->
<p v-color="'red'">测试</p>
</template>
<script>
export default {
data() {
return {
color: 'blue'
}
},
directives: {
// 当指令第一次被绑定到元素上的时候,会立即触发 bind 函数
color: {
// 通过 binding 对象的 .value 属性,获取动态的参数值
bind(el, binding) {
el.style.color = binding.value;
}
}
}
}
</script>
3.5 update 函数
bind 函数只调用 1 次:当指令第一次绑定到元素时调用,当 DOM 更新时 bind 函数不会被触发。 update 函数会在每次 DOM 更新时被调用。示例代码如下:
directives: {
// 当指令第一次被绑定到元素上的时候,会立即触发 bind 函数
color: {
// 通过 binding 对象的 .value 属性,获取动态的参数值
bind(el, binding) {
el.style.color = binding.value;
},
// 每次 DOM 更新时被调用
update(el, binding) {
el.style.color = binding.value;
}
}
}
3.6 bind 和 update 函数的简写形式
如果 bind 和 update 函数中的逻辑完全相同,则对象格式的自定义指令可以简写成函数格式:
directives: {
color(el, binding) {
el.style.color = binding.value;
}
}
3.7 全局自定义指令
全局共享的自定义指令需要通过 “ Vue.directive() ” 进行声明,示例代码如下:
//main.js
// 参数1:字符串,表示全局自定义指令的名字
// 参数2:对象,用来接收指令的参数值
Vue.directive('color', function(el, binding) {
el.style.color = binding.value;
})
注意:全局声明的自定义指令和过滤器等命令都要放在main.js中
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/150422.html