Vue的一些高级特性
2021-11-14 本文已影响0人
JX灬君
Vue的一些高级特性
- 兄弟组件之间的传值
- 自定义v-model
- $nextTick
- slot
- 动态,异步组件
- keep-alive
- mixin
兄弟组件传值
- 使用自定义事件
- 子组件A
- 绑定自定义事件
event.$on('onAddTitle', this.addTitleHandler)
- 绑定自定义事件
- 子组件B
- 调用自定义事件
event.$emit('onAddTitle', this.title)
- 调用自定义事件
- event获取
- new 一个Vue的实例,然后在子组件B里导入
// event.js import Vue from 'vue' export default new Vue() // 子组件B import event from 'event' - 使用自定义事件时,必须及时销毁,否则会造成内存泄漏
beforeDestory() { // 及时销毁,否则可能造成内存泄漏 event.$off('onAddTitle', this.addTitleHandler) }
- 子组件A
vue如何自己实现v-model
- 自定义v-model
- 使用场景,给子组件使用v-model(正常场景是给标签使用v-model)
- 使用说明
- 子组件里的input使用:value 而不是 v-model
- 子组件里的change和model.event要对应起来
- text属性要对应起来
// app.vue
<div>{{ names }}</div>
<TestModel v-model="names" />
// TestModel.vue
<input
type="text"
:value="text"
@input="$emit('change', $event.target.value)"
name=""
id=""
/>
export default {
model: {
prop: 'name1', // 对应props text
event: 'change'
},
props: {
name1: String,
default () {
return ''
}
}
}
Vue组件更新之后如何获取最新DOM- $nextTick
- Vue是异步渲染的框架
- data改变之后,DOM不会立刻渲染
- $nextTick会在DOM渲染之后触发,以获取最新DOM
- 原理
- 异步渲染,$nextTick 待DOM渲染完再回调
- 页面渲染时,会将data的修改做整合,多次data修改只会渲染一次
- Vue操作dom后不会立即获取到,异步渲染
- 比如动态添加子元素,如果子元素数量为3
- 动态添加完3个子元素,此时如果查询子元素数量,依然为3,但是页面已经有了6个子元素
- 如果想要添加完3个子元素后立即获取6个子元素,那就使用$nextTick()
// 3个子元素添加子元素之后打印 = 3个
addItem () {
this.list.push(Date.now())
this.list.push(Date.now())
this.list.push(Date.now())
// 获取DOM元素
const ulElem = this.$refs.ul1
// eslint-disable-next-line
console.log(ulElem.childNodes)
// eslint-disable-next-line
console.log(ulElem.childNodes.length)
}
// 3个子元素添加子元素之后打印 = 6ge
addItem () {
this.list.push(Date.now())
this.list.push(Date.now())
this.list.push(Date.now())
this.$nextTick(() => {
// 获取DOM元素
const ulElem = this.$refs.ul1
// eslint-disable-next-line
console.log(ulElem.childNodes)
// eslint-disable-next-line
console.log(ulElem.childNodes.length)
})
}
Vue通过ref获取DOM元素的技巧
- 通过设置ref获取DOM元素
- 通过childNodes获取子元素
<ul ref="ul1">
// 获取DOM元素
const ulElem = this.$refs.ul1
slot插槽
- 基本使用
- slot主要用来接受在父组件引入子组件里的子节点
- 存在的意义就是让父组件可以往子组件内插入一段数据
// 父组件 website: { url: 'http://www.baidu.com', title: 'baidu', subTitle: 'search best' } <SlotDemo :url="website.url"> website.title </SlotDemo> // 子组件 <a :href="url"> <slot> 默认内容,即父组件没设置内容时,这里显示 </slot> </a> export default { props: ['url'], data () { return {} }, mounted () { // eslint-disable-next-line console.log(this.url) } } - 作用域插槽
- 将子组件里的数据通过插槽暴露给父组件
- 子组件通过:slotData传值
- 父组件通过template + v-slot获取
// 子组件 <a :href="url"> <slot :slotData="website"> {{website.subTitle}} <!-- 默认值显示 subTitle ,即父组件不传内容时 --> </slot> </a> // 父组件 <ScopedSlotDemo :url="website.url"> <template v-slot="slotProps"> {{ slotProps.slotData.title }} </template> </ScopedSlotDemo> - 具名插槽
- 当子组件有多个插槽时,通过name表明要查到哪个插槽里
// 子组件 <div class="container"> <header> <slot name="header"></alot> </header> <main> <slot></alot> </main> <footer> <slot name="footer"></alot> </footer> </div> // 父组件 <NamedSlot> <template v-slot:header> <h1>将插入header slot中</h1> </template> <p>将插入到main slot中,即未命名的slot</p> <template v-slot:footer> <p>将插入到footer slot中</p> </template> </NameSlot>
动态组件
- 用法
:is = "component-name"- 需要根据数据,动态渲染的场景。即组件类型不确定
- 应用场景例子
- 新闻详情页(有文本,图片,视频且位置不确定)
- 应用1
import TplDemo from './TplDemo'
components: {
TplDemo
}
data () {
return {
TplDemoName: TplDemo
}
},
<component :is="TplDemoName"></component>
- 应用2(根据后台返回内容渲染不同组件)
import Text from './Text'
import Image from './Image'
components: {
Text, Image
}
data () {
return {
newsData:{
1:{
type: 'text'
},
2:{
type: 'text'
},
3:{
type: 'image'
}
}
}
},
<div v-for="(name,index) in newsData" :key="index">
<component :is="name:type"></component>
</div>
异步组件
- 什么时候用,什么时候加载,一直不用永远不会加载
- 用来加载大型组件(比如echarts或者第三方图表)
- 如果不会将会根据大型组件的大小影响系统的流畅程度,组件越大,影响越大
- import() 函数
- 按需加载,异步加载大组件
// 同步加载组件
import Text from './Text'
components: {
Text
}
// 异步加载组件
components: {
Text: () => import('../Text')
}
// 相当于
components: {
Text: () =>{
return import('../Text')
}
}
keep-alive 组件缓存
- 缓存组件
- 频繁切换,不需要重复渲染
- Vue常见性能优化
- 将代码放入keep-alive中包裹
<keep-alive>需要缓存的组件</keep-alive> - v-show和keep-alive都可以实现缓存效果,有什么区别
- v-show靠css的display:none; 来控制(低级,简单粗暴)
- keep-alive靠框架来控制
- 需要使用keep-alive的场景
- 需要频繁切换的tab页面
Vue组件抽离公共逻辑 mixin
- 多个组件有相同的逻辑,抽离出来
- mixin并不是完美的解决方案,会有一些问题
- Vue3提出的Composition API旨在解决这些问题
- 缺点
- 变量来源不明确,不利于阅读
- 多mixin可能会造成命名冲突
- mixin和组件可能出现多对多的关系,复杂度较高
- 用法
- 抽离相同的组件逻辑然后写入js中
- 在使用的页面上import导入
- 通过mixins属性导入
// same.js相同组件
export default {
data() {
return {
name: 'mixin混入'
}
},
methods: {
showName() {
// eslint-disable-next-line
console.log(this.name)
}
},
mounted() {
// eslint-disable-next-line
console.log('mixin mounted', this.name)
}
}
// vue页面使用
import Same from './same.js'
export default {
mixins: [Same],
name: 'app',
data () {
return {
names: 'zach'
}
}
}
// 然后直接使用即可