学习笔记目录:
更新中…
目录
动态组件
1. 什么是动态组件
动态组件指的是动态切换组件的显示与隐藏。
2. 如何实现动态组件渲染
vue 提供了一个内置的 compoent 组件(我们也可以将该组件理解为我们要展示的组件的占位符),专门用来实现动态组件的渲染。通过该 component 组件的 is 属性来指定要显示的组件的名称。
示例代码如下;
<template>
<div class="app-container">
<!-- 渲染 Left 组件和 Right 组件 -->
<component :is="comName"></component>
</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>
我们来实现以下点击响应的按钮,实现展示组件的切换:
<button @click="comName='Left'">展示 Left</button>
<button @click="comName='Right'">展示 Right</button>
<div class="box">
<!-- 渲染 Left 组件和 Right 组件 -->
<component :is="comName"></component>
</div>
<script>
export default{
data(){
return{
// 表示要进行展示的组件的名字
comName:'Left'
}
},
}
</script>
3. 使用 keep-alive 保持状态
默认情况下,切换动态组件时无法保持组件的状态(就相当于每一次返回到对应的组件,组件中的内容就会被重置====销毁,重新创建)。此时可以使用 vue 内置的 keep-alive 组件保持动态组件的状态。可以使组件被切换为其他组件的之后,被切换的组件不会被销毁(被缓存,状态是 inactive )
示例代码如下:
<keep-alive>
<component :is="comName"></component>
</keep-alive>
4. keep-alive 对应的生命周期函数
当组件被缓存时,会自动触发组件的 deactivated 生命周期函数。
当组件被激活时,会自动触发组件的 activated 生命周期函数。
<script>
export default {
activated(){
console.log('组件被激活了!')
},
deactivated(){
console.log('组件被缓存了!')
}
}
</script>
5. keep-alive 的 include 属性
默认情况下,keep-alive 标签里面包含的内容都是会被缓存的;但是某些情况下我们并不需要相应的内容都被缓存,这就可以使用 include 属性来解决。
include 属性用来指定:只有名称匹配的组件会被缓存。多个组件名之间使用英文的逗号分隔;同时和他对应的还有一个属性就是 exclude ,这个属性的属性值包含的内容是指定其不被缓存,但是两者不能同时使用。
<keep-alive include="Left,Right">
<component :is="comName"></component>
</keep-alive>
叭叭小知识:
-
当我们不给我们调用的组件给 name 属性的话,默认的就是定义的时候的标签名;当我们提供了 name 属性之后,组件的名称就是 name 属性的值(include 和 exclude 属性里面对应的名称也要和我们定义的 name 的属性名一致)
-
组件的注册名称的主要应用场景是:以标签的形式,把注册好的组件,渲染和使用到页面结构之中
-
组件声明时候的 name 属性名称的主要应用场景:结合 keep-alive 标签实现组件的缓存功能(include 和 exclude 里面内容的指定),以及在调试工具中看到组件的 name 名称
下面是具体的示例代码:
APP.vue 中的代码
<template>
<div class="app-container">
<keep-alive include="Left">
<component is="MyLeft"></component>
</keep-alive>
</div>
</template>
<script>
import Left from './components/Left.vue'
export default {
components:{
Left
},
}
</script>
Left.vue 中的代码:
<script>
export default {
name:"MyLeft"
}
</script>
插槽
1. 什么是插槽
插槽(Slot)是 vue 为组件的封装者提供的能力。允许开发者在封装组件时,把不确定的、希望由用户指定的部分定义为插槽。
可以把插槽认为是组件封装期间,为用户预留的内容的占位符,然后在调用组件的时候在组件的标签里面使用的标签来占取之前定义标签组件的占位符的位置。
2. 体验插槽的基础用法
在封装组件时,可以通过 slot 元素定义插槽,从而为用户预留内容占位符。示例代码如下:
//Left 组件
<template>
<div class="left-container">
<h3>Left 组件</h3>
<!-- 声明一个插槽 -->
<!-- vue 官方规定:每一个 solt 插槽,都要有一个 name 名称,如果省略了该属性,则会有一个默认的名称 default -->
<slot name="default"></slot>
</div>
</template>
//App 组件
<template>
<div class="app-container">
<h1>App 根组件</h1>
<hr />
<div class="box">
<!-- 渲染 Left 组件和 Right 组件 -->
<Left>
<!-- 默认情况下:在使用组件的时候,提供的内容都会被填充到名字为 default 的插槽中 -->
<p>插槽体验</p>
<!-- 指定要显示相应内容的插槽的做法--使用 v-slot 指令(简写为 # )指定插槽名(要注意的是:该属性只能用在组件 component 标签和 template 标签上面,不能直接使用在其他元素上上面) -->
<!-- template 标签只是起到一个包裹器的作用,并不会渲染成真正的元素(或者说是 其他实质性的 html 元素) -->
<template v-slot:default>
<p>指定要显示相应内容的插槽 </p>
</template>
</Left>
</div>
</div>
</template>
<script>
import Left from './components/Left.vue'
export default {
components:{
Left
}
}
</script>
2.1 没有预留插槽的内容会被丢弃
如果在封装组件时没有预留任何 slot 插槽,则用户提供的任何自定义内容都会被丢弃。即在封装的组件里面没有使用 slot 的话,在使用该组件的时候,该组件的标签中间的内容会直接被系统默认丢弃(删除)
当然,如果在组件中定义了插槽,但是在使用的时候,在这个组件标签里面,并没有填放内容,那么会默认什么也不显示。
2.2 后备内容
封装组件时,可以为预留的 slot 插槽提供后备内容(默认内容)。如果组件的使用者没有为插槽提供任何内容,则后备内容会生效。示例代码如下:
<template>
<div class="left-container">
<h3>Left 组件</h3>
<!-- 声明一个插槽 -->
<slot>
<p> 后备内容--默认内容 </p>
</slot>
</div>
</template>
3. 具名插槽
如果在封装组件时需要预留多个插槽节点,则需要为每个 slot 插槽指定具体的 name 名称。这种带有具体名称的插槽叫做“具名插槽”。
注意:
-
一个组件里面可以有多个具有相同的 name 属性的插槽,在调用组件的时候,指定 name 的插槽里面显示的内容,会在具有该 name 名称的所有插槽的位置显示该指定的内容。
-
没有指定 name 名称的插槽,会有隐含的名称叫做 “default”。
-
在向具名插槽提供内容的时候,我们可以在一个 template 元素上使用 v-slot 指令,并以 v-slot 的参数的形式提供其名称。
-
跟 v-on 和 v-bind 一样,v-slot 也有缩写,即把参数之前的所有内容 (v-slot:) 替换为字符 #。例如 v-slot:header
可以被重写为 #header
//组件代码 Artilce.vue
<template>
<div class="article-container">
<h3 v-color="'red'">Article 组件</h3>
<!-- 文章的标题 -->
<div class="header-box">
<slot name="title"></slot>
</div>
<!-- 文章的内容 -->
<div class="content-box">
<!-- 在封装组件时,为预留的 <slot> 提供属性对应的值,这种用法,叫做 “作用域插槽” -->
<!-- 在定义插槽的时候使用一些自定义属性,可以对象的形式传递给调用该组件的组件 -->
<slot name="content" msg="hello vue.js" :user="userinfo"></slot>
</div>
<!-- 文章的作者 -->
<div class="footer-box">
<slot name="author"></slot>
</div>
</div>
</template>
<script>
export default {
// 首字母要大写
name: 'Article',
data() {
return {
// 用户的信息对象
userinfo: {
name: 'zs',
age: 20
}
}
}
}
</script>
//组件调用
<Article>
<template #title>
<h3>一首诗</h3>
</template>
<!-- 我们接收作用于插槽的自定义属性对象的时候,接收对象的名称,我们一般使用 scope -->
<!-- <template #content="scope"> -->
<!-- 这样我们后面使用的时候就可以直接使用该对象得到其属性===比如:scope.msg -->
<!-- 下面的这种写法是对对象进行结构接收(可以用几个接收几个)--格式为 { 要接收对象的属性名(中间使用 ',' 分隔) } -->
<template #content="{ msg, user }">
<div>
<p>啊,大海,全是水。</p>
<p>{{ msg }}</p>
<p>{{ user.name }}</p>
</div>
</template>
<template #author>
<div>作者:彬果锅</div>
</template>
</Article>
小练手:
把之前的那个购物车案例进行一下重构(优化):对其计数器( Counter )部分进行优化
自定义指令
1. 什么是自定义指令
vue 官方提供了 v-text、v-for、v-model、v-if 等常用的指令。除此之外 vue 还允许开发者自定义指令。
注意:自定义局部指令中内部不能出现大写字母(第一个字母可以大写,如:Obgcolors,中间大写不行,如:obgColors就不可以);
2. 自定义指令的分类
vue 中的自定义指令分为两类,分别是:
-
私有自定义指令
-
全局自定义指令
3. 私有自定义指令
在每个 vue 组件中,可以在 directives 节点下声明私有自定义指令。示例代码如下:
<!-- 我们使用自定义指令的时候,在指令的前面需要加上一个 v- ,也就是说:比如 v-color 他的指令实际上是 color -->
<p v-color>自定义指令</p>
<script>
export default {
// 私有自定义指令的节点
directives:{
// 定义名为 color 的指令,指向一个配置对象
color:{
// 当指令第一次被绑定到元素上的时候,会立即触发 bind 函数
// 形参中的 el 表示当前指令所绑定到的那个 DOM 对象
bind(el){
el.style.color='blue'
}
}
}
}
</script>
4. 为自定义指令动态绑定参数值
-
当指令第一次被绑定到元素上的时候,会立即触发 bind 函数
-
bind 函数里面的这两个参数虽然都是形参,名字可以任意命名,但是我们最好是按照官方的标准来,元素使用 el , 第二参数(接收指令的参数值对象)使用 binding
-
形参中的 el 表示当前指令所绑定到的那个 DOM 对象
-
通过 binding 获取指令的参数值,需要注意的是这个后面的这个 binding 参数,代表的是一个对象,
-
binding.exxpression 是表达式,其内容是我们在指令后面所写的全部内容(包括最外层的双引号)
-
binding.value 是我们真正能够使用的值,是指令后面双引号里面的内容(不包括最外层的双引号)
<p v-color>自定义指令1</p>
<!-- 默认黑色-该指令没有起作用 -->
<p v-color="color">自定义指令2</p>
<!-- 蓝色--我们定义的 data 里面的 coloe 的值 -->
<p v-color="'red'">自定义指令3</p>
<!-- 红色--相当于直接赋值;尤其要注意直接给值的时候,值要加上双引号,否则会被认为是 data 里面的属性,然后去data 里面找,找不到就会报错 -->
====================分割线==========================
<script>
export default {
data(){
return{
//单引号
color:'blue'
}
},
directives:{
// 定义名为 color 的指令,指向一个配置对象
color:{
bind(el,binding){
el.style.color=binding.value
}
}
}
}
</script>
5. update 函数
bind 函数只调用 1 次:当指令第一次绑定到元素时调用,当 DOM 更新时 bind 函数不会被触发。 update 函数会在每次 DOM 更新时被调用,但是在指令对一次绑定到元素上面的时候并不会被调用。所以 bind 函数和 update 函数我们都是配套使用的。(^ω^)
就比如说我们用下面的这种方式来改变颜色值的话,就是不会生效的,虽然我们在调试工具里面看到的 color 的值确实已经被更改,但是并没有被渲染到其他元素的上面,也就是因为 bind 这个渲染改颜色值的函数只是在第一次绑定到元素时调用,其他时候不会调用!!!
<button @click="color='green'">改变 color 的颜色值</button>
所以我们就是需要使用这个 update 函数(该函数的用法和 bind 函数基本一致)了
// 私有自定义指令的节点
directives: {
// 定义名为 color 的指令,指向一个配置对象
color: {
bind(el, binding) {
console.log("触发了 v-color 的 bind 函数");
el.style.color = binding.value;
},
update(el, binding) {
console.log("触发了 v-color 的 bind 函数");
el.style.color = binding.value;
},
},
},
6. 函数简写
如果 bind 和update 函数中的逻辑完全相同,则对象格式的自定义指令可以简写成函数格式:
// 私有自定义指令的节点
directives: {
// 在bind 和 update 的时候,会触发相同的业务逻辑
color(el, binding) {
console.log("触发了 v-color 的 bind 函数");
el.style.color = binding.value;
}
},
7. 全局自定义指令
全局共享的自定义指令需要通过 “Vue.directive()” 在 main.js 中进行声明(和声明全局的过滤器的写法差不多)
import Vue from 'vue'
import App from './App.vue'
Vue.config.productionTip = false
// 全局自定义指令
//完整写法:
// Vue.directive('color', {
// bind(el, binding) {
// el.style.color = binding.value
// },
// update(el, binding) {
// el.style.color = binding.value
// }
// })
// 可简写为
Vue.directive('color', function(el, binding) {
el.style.color = binding.value
})
new Vue({
render: h => h(App),
}).$mount('#app')
叭叭小知识:
-
我们一般在开发中使用 过滤器 和 自定义指令 的时候,一般都是使用全局注册的方式,以实现代码的复用。
-
main.js 里面的一个小知识:
main.js 里面有一行语句 Vue.config.productionTip = false ;该行语句的作用是:
我们在 web 端调试的时候,Vue的窗口会不会看到一个提示信息—我们现在是开发模式 development,发布的时候,需要将其改为生产模式 production ;
Vue.config.productionTip 的默认值是 TRUE 即我们可以看到提示信息(也就是说这一行语句是可以删除掉的,没有太大影响)
对上面的三个知识的学习小结:
① 能够掌握 keep-alive 元素的基本使用
- keep-alive 标签、include 属性
② 能够掌握插槽的基本用
- slot 标签、具名插槽、作用域插槽、后备内容
③ 能够知道如何自定义指令
-
私有自定义指令 directives: { }
-
全局自定义指令 Vue.directive()
学习笔记目录:
更新中…