自定义v-model
父组件
<template>
<div class="about">
<p>{{name}}</p>
<MyInput v-model="name"/>
</div>
</template>
<script>
import MyInput from '../components/MyInput.vue'
export default {
data() {
return {
name: ''
}
},
components:{
MyInput
}
}
</script>
子组件
<template>
<input type="text" :value="text" @input="$emit('change',$event.target.value)">
</template>
<script>
export default {
model:{
prop:'text',
event:'change'
},
props:{
text:String
}
}
</script>
总结:
1.上面的input使用了 :value而不是v-model
2.上面的change和model.event要对应起来
3.text属性对应起来
$nextTick
1.Vue是异步渲染
2.data改变之后,DOM不会立刻渲染
3.$nextTick会在DOM渲染之后被触发,以获取最新的DOM节点
父组件
<template>
<next-tick />
</template>
<script>
import NextTick from "../components/NextTick.vue";
export default {
components: {
NextTick,
},
};
</script>
子组件
<template>
<div>
<ul ref="uls">
<li v-for="(item, index) in list" :key="index">{{ item }}</li>
</ul>
<button @click="addItem">添加</button>
</div>
</template>
<script>
export default {
data(){
return {
list:[1,2,3]
}
},
methods:{
addItem(){
this.list.push(`${Date.now()}`)
this.list.push(`${Date.now()}`)
this.list.push(`${Date.now()}`)
//获取节点
let ulEl = this.$refs.uls
console.log(ulEl.childNodes.length)
}
}
};
</script>
输出结果: 3、 6、 9、 //这里因为是异步渲染,获取不到最新的DOM情况
异步渲染,这里我们可以通过$nextTick渲染完再回调
页面渲染时会将data的修改做整合,多次data修改只会渲染一次
this.$nextTick(() => {
let ulEl = this.$refs.uls;
console.log(ulEl.childNodes.length);
});
输出结果: 6、 9、12 //我们需要的结果
slot(插槽)
基本使用
父组件
<template>
<my-slot :url="website.url">
{{website.title}}
</my-slot>
</template>
<script>
import MySlot from "../components/MySlot.vue";
export default {
components: {
MySlot,
},
data(){
return {
website:{
title:'百度',
url:'https://www.baidu.com'
}
}
}
};
</script>
子组件
<template>
<a :href="url">
<slot>默认值</slot>
</a>
</template>
<script>
export default {
props: ['url']
}
</script>
作用域插槽
父组件
<template>
<my-slot :url="website.url">
<template v-slot="slotProps">
{{slotProps.slotData}}
</template>
</my-slot>
</template>
子组件
<template>
<a :href="url">
<slot :slotData="data">
默认值
</slot>
</a>
</template>
具名插槽
父组件
<template>
<my-slot>
<template v-slot:header>
<h1>Header</h1>
</template>
<h1>Main</h1>
<template v-slot:footer>
<h1>footer</h1>
</template>
</my-slot>
</template>
子组件
<template>
<div class="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
</template>
动态组件
1.:is= "component-name"
2.需要根据数据,动态渲染的场景.即组件类型不确定
//基本用法
<component :is="componentName" />
//这里可以用一个组件数组,传我们想要的组件名称
<div v-for="(name,index) in names" :key="index">
<component :is="name" />
</div>
这样就是动态组件数组
异步组件
import()函数
按需加载,异步加载大组件
//这是我们经常用的同步加载组件方式
import MySlot from '../components/MySlot.vue
export default {
components: {
MySlot
}
}
//但是如果加载的组件很大,这时我们就需要使用异步加载组件
export default {
components: {
MySlot:() => import('../components/MySlot.vue')
}
}
keep-alive
1.缓存组件
2.频繁切换,不需要重复渲染 比如tab切换
3.Vue常见的性能优化方式
mixin
1.多个组件有相同的逻辑,抽离出来
2.mixin并不是完美的解决方案,会有一些问题
3.Vue3提出的Composition API旨在解决这些问题
<template>
<div>
<p>{{name}} {{job}} {{city}}</p>
<button @click="showName">显示姓名</button>
</div>
</template>
<script>
import myMixin from './mixin'
export default {
mixins: [myMixin], //可以添加多个,会自动合并起来
data() {
return {
name:'一支鱼',
job: 'web 前端'
};
},
methods:{},
mounted(){
console.log('mounted',this.name)
}
};
</script>
//抽离出来myMixin.js 抽离出多个组件公用的
export default {
data() {
return {
city: '北京'
}
},
methods: {
showName() {
console.log(this.name)
}
},
mounted() {
console.log('mounted', this.name)
}
}
mixin存在的问题
1.变量来源不明确,不利于阅读
2.多mixin可能会造成命名冲突
3.mixin和组件可能出现多对多的关系,复杂度较高