Vue组件进阶与自定义指令
- 一、Vue组件进阶
- 1.1 动态组件
- 1.2 组件缓存
- 1.3 组件激活和非激活
- 1.4 组件插槽
- 1.5 具名插槽
- 1.6 作用域插槽
- 1.7 作用域插槽使用场景
- 二、自定义指令
- 2.1 自定义指令--注册
- 2.2 自定义指令-传参
一、Vue组件进阶
1.1 动态组件
多个组件使用同一个挂载点,并动态切换
实现流程
代码
<template>
<div>
<button @click="comName = 'UserName'">账号密码填写</button>
<button @click="comName = 'UserInfo'">个人信息填写</button>
<p>下面显示注册组件的动态切换</p>
<div style="border: 1px solid red;">
<component :is="comName"></component>
</div>
</div>
</template>
<script>
// 目标:动态组件-切换组件显示
//1.创建要被切换的组件 - 标签+样式
//2.引入到要展示的vue文件内
//3.准备一个变量承载要显示的组件名
//4.设置挂载点<component :is="变量"></component>
import UserName from '../components/01/UserName.vue'
import UserInfo from '../components/01/UserInfo.vue'
export default {
components: {
UserInfo,
UserName
},
data() {
return {
comName: 'UserName' ,//准备一个变量
}
}
}
</script>
1.2 组件缓存
原因:频繁的切换会导致组件频繁创建和销毁,性能不高
语法: Vue内置的keep-alive组件 包起来要频繁切换的组件
<div style="border: 1px solid red;">
<keep-alive>
<!-- Vue内置组件 包起来进行缓存 -->
<component :is="comName"></component>
</keep-alive>
</div>
//dom更改后
created() {
console.log('username组件创建了');
},
//实例销毁
destroyed() {
console.log('username组件销毁了');
},
1.3 组件激活和非激活
扩展2个新的生命周期方法
activated -- 激活时触发
deactivated -- 失去激活状态触发
//组件缓存后 多了两个钩子函数
activated() {
console.log('username组件激活了');
},
deactivated() {
console.log('username组件失去激活状态');
}
1.4 组件插槽
通过 slot 标签, 让组件内可以接收不同的标签结构显示
语法
1.组件内使用<slot></slot>进行占位
2.使用组件时<Pannel></Pannel>夹着的地方,传入标签替换slot
插槽默认内容
<slot>内放置内容, 作为默认显示内容
不给组件传标签. slot内容原地显示
给组件内传标签, 则slot整体被换掉
父组件代码
<Pannel>
<img src="../../src/assets/logo.png" alt="">
<span>我是图片</span>
</Pannel>
<Pannel>
<p>寒雨连江夜入吴,</p>
<p>平明送客楚山孤。</p>
<p>洛阳亲友如相问,</p>
<p>一片冰心在玉壶。</p>
</Pannel>
<Pannel></Pannel>
子组件代码
<div>
<!-- 按钮标题 -->
<div class="title">
<h4>芙蓉楼送辛渐</h4>
<span class="btn" @click="isShow = !isShow">
{{ isShow ? "收起" : "展开" }}
</span>
</div>
<!-- 下拉内容 -->
<div class="container" v-show="isShow">
<slot>
<!-- 没有传则显示默认内容 -->
我是默认的显示内容
</slot>
</div>
</div>
1.5 具名插槽
一个组件内有2处以上需要外部传入标签的地方
语法
1.slot使用name属性区分名字
2.template配合v-slot:名字来分发对应标签
v-slot; 可以简写为#
父组件代码
<Pannel>
<template v-slot:title>
<h4>
芙蓉楼送辛渐
</h4>
</template>
<template v-slot:content>
<img src="../../src/assets/logo.png" alt="">
<span>我是图片111</span>
</template>
</Pannel>
<Pannel>
<template #title>
<h4>
v-slot:可简写成#号
</h4>
</template>
<template #content>
<img src="../../src/assets/logo.png" alt="">
<span>我是图片222</span>
</template>
</Pannel>
子组件代码
<div>
<!-- 按钮标题 -->
<div class="title">
<slot name="title"></slot>
<span class="btn" @click="isShow = !isShow">
{{ isShow ? "收起" : "展开" }}
</span>
</div>
<!-- 下拉内容 -->
<div class="container" v-show="isShow">
<slot name="content">
我是默认的显示内容
</slot>
</div>
</div>
1.6 作用域插槽
在使用子组件时,父组件需要使用子组件里的变量
步骤
1.子组件, 在slot上绑定属性和子组件内的值
2. 父组件, 传入自定义标签, 用template和v-slot="自定义变量名"
3. scope变量名自动绑定slot上所有属性和值
scope = {row: defaultObj}
父组件代码
<Pannel>
<template v-slot="scope">
<!-- scope变量{row:defaultObj} -->
{{ scope.row.defaultTwo }}
</template>
</Pannel>
子组件代码
<template>
<div>
<!-- 按钮标题 -->
<div class="title">
<h4>作用域插槽</h4>
<span class="btn" @click="isShow = !isShow">
{{ isShow ? "收起" : "展开" }}
</span>
</div>
<!-- 下拉内容 -->
<div class="container" v-show="isShow">
<slot :row="defaultObj">
{{ defaultObj.defaultOne }}
</slot>
</div>
</div>
</template>
<script>
//目标:作用域 插槽
//场景:使用插槽 使用组件内的变量
//1.slot标签,自定义属性和内变量关联
//2.使用组件 template配合v-slot="变量名"
//变量名会收集slot身上的属性和值形成对象
export default {
data() {
return {
isShow: false,
defaultObj: {
defaultOne: '无名氏',
defaultTwo: '木子'
}
};
},
};
1.7 作用域插槽使用场景
父组件代码
<template>
<div>
<Mytable :arr="list">
</Mytable>
<Mytable :arr="list">
<!-- scope:{row:obj} -->
<template v-slot="scope">
<a :href="scope.row.headImgUrl">{{ scope.row.headImgUrl }}</a>
</template>
</Mytable>
<Mytable :arr="list">
<template v-slot="scope">
<img :src="scope.row.headImgUrl" alt="">
</template>
</Mytable>
</div>
</template>
<script>
import Mytable from '../components/06/MyTable.vue'
export default {
components: {
Mytable
},
data() {
return {
list: [
{
name: "小传同学",
age: 18,
headImgUrl:
"http://yun.itheima.com/Upload/./Images/20210303/603f2d2153241.jpg",
},
{
name: "小黑同学",
age: 25,
headImgUrl:
"http://yun.itheima.com/Upload/./Images/20210304/6040b101a18ef.jpg",
},
{
name: "智慧同学",
age: 21,
headImgUrl:
"http://yun.itheima.com/Upload/./Images/20210302/603e0142e535f.jpg",
},
],
}
}
}
</script>
子组件代码
<template>
<div>
<table border="1">
<thead>
<tr>
<th>序号</th>
<th>姓名</th>
<th>年龄</th>
<th>头像</th>
</tr>
</thead>
<tbody>
<tr v-for="(obj, index) in arr">
<td>{{ index + 1 }}</td>
<td>{{ obj.name }}</td>
<td>{{ obj.age }}</td>
<td>
<!-- 标签不确定 slot插槽占位 -->
<!-- 默认显示文字 -->
<slot :row="obj">{{ obj.headImgUrl }}</slot>
</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
export default {
props: {
arr: Array
}
}
</script>
二、自定义指令
2.1 自定义指令–注册
获取标签, 扩展额外的功能
全局注册 main.js
//全局指令 到处直接使用
Vue.directive("gfocus", {
inserted(el) {
console.log('el', el);
el.focus(); //触发标签的事件方法
}
})
局部注册
directives: {
focus: {
inserted(el) {
el.focus()
}
}
},
使用 v-指令名
<input v-focus type="text">
2.2 自定义指令-传参
语法
//注意:inserted方法 指令所在标签,被插入到网页上才会触发(一次)
//update方法 指令对应数据/标签更新时,此方法执行
//目标:自定义指令全局 传值
Vue.directive('color', {
inserted(el, binding) {
console.log('binding', binding);
el.style.color = binding.value
},
update(el, binding) {
el.style.color = binding.value
}
})