vue高级特性
1、自定义 v-model
<template>
<div>
<p>vue 高级特性p>
<hr>
<p>{{name}}p>
<CustomVModel v-model="name"/>
//也可以这样写,value对应$emit第二个参数
div>
template>
<script>import CustomVModel from './CustomVModel'export default {components: {
CustomVModel
},
data() {return {name: '自定义model',
}
}
}script>
<template>
<input type="text":value="text"
@input="$emit('change1', $event.target.value)"
>
template>
<script>export default {model: {prop: 'text', // 对应 props text
event: 'change1' //对应$emit第一个参数
},props: {text: String,default() {return ''
}
}
}script>
提示
一个组件上的v-mode1默认会利用名为value的prop和名为input的事件,但是像单选框、复选框等类型的输入控件可能会将value attribute用于不同的目的。model选项可以用来避免这样的冲突
拓展
vue2.3.0+ 新增 .sync
修饰符一样可以达到同样的效果
子组件:this.$emit('update:visible', visible)
, 使用update:my-prop-name
的模式触发事件
上面列子可以改为:
父组件:
"name" @update:text="val=>name=val">components> //简写<CustomVModel :text.sync="name"/>
子组件:
"text" :value="text" @input="syncChang" />
methods: {
syncChang(event) {
this.$emit("update:text", event.target.value);
}
}
官方案例
2、$nextTick
说明
Vue是异步渲染,data改变之,DOM不会立刻渲染,$nextTick 会在DOM渲染之后被触发,以获取最新的DMO节点
<template>
<div id="app">
<ul ref="ul1">
<li v-for="(item, index) in list" :key="index">
{{item}}
li>
ul>
<button @click="addItem">添加一项button>
div>
template>
<script>export default {name: 'app',
data() {return {list: ['a', 'b', 'c']
}
},methods: {
addItem() {this.list.push(`${Date.now()}`)this.list.push(`${Date.now()}`)this.list.push(`${Date.now()}`)const ulElem = this.$refs.ul1console.log( ulElem.childNodes.length )
}
}
}script>
如上展示,会获取不到正确的数组长度length,这个时候就的用$nextTick
addItem() {
this.list.push(`${Date.now()}`)
this.list.push(`${Date.now()}`)
this.list.push(`${Date.now()}`)
this.$nextTick(() => {
// 获取 DOM 元素
const ulElem = this.$refs.ul1
console.log( ulElem.childNodes.length )
})
}
说明
异步渲染,$nextTick 待 DOM 渲染完再回调
页面渲染时会将 data 的修改做整合,多次 data 修改只会渲染一次(也就是只会调用一个$nextTick)
3、solt插槽
作用
让父组件可以往子组件中插入一段内容(不一定是字符串,可以是其它的组件,只要是符合Vue标准的组件或者标签都可以)
3.1 默认插槽
<div><SlotDemo :url="website.url">
{{website.title}}SlotDemo>div>template><script>import SlotDemo from './CustomVModel'export default {components: {
SlotDemo
},
data() {return {website: {url: 'http://imooc.com/',title: 'imooc',subTitle: '程序员的梦工厂'
},
}
}
}script>
<a :href="url"><slot>
默认内容,即父组件没设置内容时,这里显示slot>a>template><script>export default {props: ['url'],
data() {return {}
}
}script>
3.2 作用域插槽
作用
让父组件可以访问到子组件的数据(算是一种组件通讯的方式)
<div><ScopedSlotDemo :url="website.url"><template v-slot="slotProps">
{{slotProps.slotData.title}}template>ScopedSlotDemo>div>template><script>import ScopedSlotDemo from './CustomVModel'export default {components: {
ScopedSlotDemo
},
data() {return {website: {url: 'http://imooc.com/',title: 'imooc',subTitle: '程序员的梦工厂'
},
}
}
}script>
<a :href="url"><slot :slotData="website">
{{website.subTitle}} slot>a>template><script>export default {props: ['url'],
data() {return {website: {url: 'http://wangEditor.com/',title: 'wangEditor',subTitle: '轻量级富文本编辑器'
}
}
}
}script>
讲解
子组件内部的slot
标签上绑定动态数据 soltData='website'
(website是 data中的数据)
在父组件调用子组件ScopedSlotDemo中 插入template ,v-slot='slotProps'
(slotProps可以自定义名字)
最后就可以通过slotProps.slotData
获取到子组件中的website
3.3 具名插槽
4、动态、异步组件
4.1 动态组件
说明
需要根据数据,动态渲染场景(组件类型不确定),使用
![5910b421c699dd78ee2ec997bf9f2b6f.png](https://i-blog.csdnimg.cn/blog_migrate/1cd2f2e592eada9e764263eae92fc565.png)
<div><div v-for="(val, index) in newsData": key="val.id"><component :is="val. compnent"/>div>div>template><script>import Text from './Text'import Image from './Image'import Video from './Video'export default {components: {
Text,
Image,
Video
},
data() {return {newsData:[
{id:1,compnent:'Text'
},
{id:1,compnent:'Image'
},
{id:1,compnent:'Video'
}
]
}
}
}script>
注意
即使一个组件也不能写成 (会报错)
4.2 异步组件
>作用
只有用到的时候才加载
import Text from './Text'
import Image from './Image'
import Video from './Video'
export default {
components: {
Text,
Image,
Video
},
//这些都是同步加载组件,意思就是进入这个页面不管有没有用到都会加载进来
如上图所示,还没有点击按钮显示Form组件 ,就能在文件中搜索到Form组件中的内容
接下来让我们看看异步组件
components: {
FormDemo: () => import('../BaseUse/FormDemo'),
},
//异步引入
如上图 ,一开始加载页面是搜不到Form组件内容的,只有当我没点击了按钮才加载组件文件进来
5、keep-alive
说明
频繁切换,不需要重复渲染的时候就需要使用keep-alive
缓存组件,下次使用直接拿缓存,页面不需要重新加载组件,这是Vue常见性能优化之一。
<template>
<div>
<button @click="changeState('A')">Abutton>
<button @click="changeState('B')">Bbutton>
<button @click="changeState('C')">Cbutton>
<keep-alive>
<KeepAliveStageA v-if="state === 'A'"/>
<KeepAliveStageB v-if="state === 'B'"/>
<KeepAliveStageC v-if="state === 'C'"/>
keep-alive>
div>
template>
<script>import KeepAliveStageA from './KeepAliveStateA'import KeepAliveStageB from './KeepAliveStateB'import KeepAliveStageC from './KeepAliveStateC'export default {components: {
KeepAliveStageA,
KeepAliveStageB,
KeepAliveStageC
},
data() {return {state: 'A'
}
},methods: {
changeState(state) {this.state = state
}
}
}script>
A、b、c只是三个简单的组件
state A
6、mixin
作用
多个组件有相同逻辑,就会抽离出来,使用mixn混入
例如:
index.vue
<template>
<div>
<p>{{name}} {{major}} {{city}}p>
<button @click="showName">显示姓名button>
div>
template>
<script>import myMixin from './mixin'export default {mixins: [myMixin],
data() {return {name: '张三',major: 'web 前端'
}
},methods: {
},
mounted() {console.log('component mounted', this.name)
}
}script>
mixin.js
export default {
data() {
return {
city: '北京'
}
},
methods: {
showName() {
console.log(this.name)
}
},
mounted() {
console.log('mixin mounted', this.name)
}
}
说明
- 上面代码运,会执行mixin.js
中的钩子函数,然后在执行
index.vue`中的钩子函数 mixin.js
文件中能获取index.vue
中的name属性index.vue
文件点击能触发mixin.js
中的showName
事件
注意
- 同个文件可以混入多个
mixin
,有多个混入的时候,按混入顺序依次执行mixin
中的钩子函数,最后在执行文件的钩子函数 - 多个混入还会造成属性覆盖
以上内容纯属个人理解,若有不对,请回复纠正
关注【前端知识小册】,第一时间获取前端优质文章!