Vue的一些高级特性
- 兄弟组件之间的传值
- 自定义v-model
- $nextTick
- slot
- 动态,异步组件
- keep-alive
- mixin
兄弟组件传值
- 使用自定义事件
- 子组件A
- 绑定自定义事件
event.$on('onAddTitle', this.addTitleHandler)
- 子组件B
- 调用自定义事件
event.$emit('onAddTitle', this.title)
- event获取
// event.js
import Vue from 'vue'
export default new Vue()
// 子组件B
import event from 'event'
- 使用自定义事件时,必须及时销毁,否则会造成内存泄漏
beforeDestory() {
// 及时销毁,否则可能造成内存泄漏
event.$off('onAddTitle', this.addTitleHandler)
}
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>
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的场景
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'
}
}
}
// 然后直接使用即可
网友评论