vue 的高级特性
1, 自定义v-model
父组件
<template>
<div>
<customVModel v-model="text" />
</div>
</tempalte>
<script>
import CustomVModel from './customVModel'
export default{
components: { CustomVModel },
data() {
return {
text: ''
}
}
}
</script>
子组件 model.prop 和props.text对应 model.event 对应 this.$emit('change',value)
<tempalte>
<div>
<input type="text" :value="text" @input="changeInput">
</div>
</tempalte>
<script>
export default{
model: {
prop: 'text',
event: 'change'
},
props: {
text: { type: String, default: '' }
},
methods: {
changeInput(e) {
this.$emit('change', e.target.value)
}
}
}
</script>
2,$nextTick 异步渲染
$nextTick待DOM渲染完成后在回调 页面渲染时会将data的修改整合,多次data修改只会渲染一次
<tempalte>
<div>
<ul>
<li v-for="item in list" key="item">{{ item }}</li>
</ul>
<button @click="add">add</button>
</div>
</tempalte>
<script>
export default{
data () {
return {
list: ['a,b,c']
}
},
methods: {
add () {
this.list.push('d')
this.list.push('e')
this.list.push('f')
console.log(this.list) // 输出 ['a,b,c']
this.$nextTick(() => {
// 异步渲染
console.log(this.list) // 输出 ['a,b,c,d,e,f']
})
}
}
}
</script>
3,slot 插槽
slot 插槽内可以包含任何模板代码,包括 HTML 或其它的组件
父组件实例:
<template>
<div class="">
<vueComponent :data="data" >
<!-- vue 2.6以上的写法 具名插槽简写 -->
<!-- 具名插槽简写 v-slot(指令):dataval(子组件定义slot的name)="自己定义的一个名称"-->
<template v-slot:dataval="slotProps">
<h1>作用域插槽 {{slotProps.item.value}}</h1>
</template>
<!-- <div>覆盖子组件的span标签</div> -->
<template>
<div>覆盖子组件的span标签</div>
</template>
<template v-slot:test>
<div>使用具名插槽</div>
</template>
</vueComponent>
</div>
</template>
<script>
import VueComponent from './vueConponent'
export default{
components: { VueComponent },
data() {
return {
data:{
text: '父组件数据',
value: '123'
}
}
}
}
</script>
子组件实例:
<template>
<div>
<h2>{{ data.text }}</h2>
<!-- 作用域插槽 -->
<slot name="dataval" :item="data">
<p>作用域插槽slot </p>
</slot>
<!-- 插槽 -->
<slot>
<span>默认slot</span>
</slot>
<!-- 具名插槽 -->
<slot name="test">
<i>默认的具名插槽</i>
</slot>
</div>
</template>
<script>
export default{
props: {
data: { type: Object, default: null }
},
data() {
return {}
}
}
</script>
4,动态组件,异步组件
动态组件component 参数is为组件名称 异步组件加载方法:在component中使用 组件名: () => import(“组件路径”)
动态组件实例:(工作中一个项目中的动态组件例子)
组件在main.js中引入了
<template>
<div id="app">
<div v-for="(item,index) in data" :key="index">
<component :is="item.sItemName" :list-data="item.tData" :data="item"></component>
</div>
</div>
</template>
<script>
import Carousel_L1 from "./components/Carousel/carousel_L1"
import ButtonGroup_L1 from "./components/ButtonGroup/buttonGroup_L1"
import CMS_L1 from "./components/Cms/cms_L1"
import Fission_L1 from "./components/Fission/fission_L1"
import Network_L1 from "./components/Network/network_L1"
import IGet from '@/api'
const info = ['Carousel_L1','ButtonGroup_L1','CMS_L1','Fission_L1','Network_L1']
export default {
name: 'App',
components: {
Carousel_L1,
ButtonGroup_L1,
CMS_L1,
Fission_L1,
Network_L1
},
data () {
return {
data: null
}
},
created () {
this.getListData()
},
methods: {
getListData () {
const url = '接口地址'
IGet(url,{
AuthorToken: 1,
appid: "",
key: 1,
secret: 1
}).then(res => {
let list = JSON.parse(res.data.data);
this.data = list.items.filter((item) => {
if (info.includes(item.sItemName)) {
return item
}
})
})
}
}
}
</script>
异步组件的实例:
<template>
<div id="app">
<div v-for="(item,index) in data" :key="index">
<component :is="item.sItemName" :list-data="item.tData" :data="item"></component>
</div>
</div>
</template>
<script>
import { IGet } from "./utils/api"
export default {
name: 'App',
components: {
Carousel_L1: () => import('./components/Carousel/carousel_L1'),
ButtonGroup_L1: () => import('./components/Carousel/carousel_L1'),
CMS_L1: () => import('./components/Carousel/carousel_L1'),
Fission_L1: () => import('./components/Carousel/carousel_L1'),
Network_L1: () => import('./components/Carousel/carousel_L1')
},
data() {
return {
data: [
{ id: 213,sItemName: 'Carousel_L1', tData: [] },
{ id: 214,sItemName: 'ButtonGroup_L1', tData: [] },
{ id: 215,sItemName: 'CMS_L1', tData: [] },
{ id: 216,sItemName: 'Fission_L1', tData: [] },
{ id: 217,sItemName: 'Network_L1', tData: [] }
]
}
}
}
</script>
5,keep-alive
缓存组件 频繁切换,不需要重复渲染
<keep-alive>
<!--- 组件 -->
</keep-alive>
6,Mixin 全局混合
多个组件有相同的逻辑, 抽离出来
export default{
data() {
return {
text: 'Mixin test'
}
},
mounted () {
console.log("Mixin mounted")
},
methods: {
getDataList() {
console.log('Mixin methods')
}
}
}
<template>
<div class="">
Mixins = {{ text }}
</div>
</template>
<script>
import mixinTest from './index.js'
export default{
mixins: [mixinTest],
data() {
return {
data:{
text: '父组件数据',
value: '123'
}
}
}
}
</script>
7,filter 过滤器
<template>
<div>
<input type="text" v-model="text">
<p>{{ text | format }}</p>
</div>
</template>
<script>export default{
data() {
return {
text: 'text'
}
},
filters: {
format (value) {
if (!value) return
return value.charAt(0).toUpperCase() + value.slice(1)
}
}
}
</script>
8,watch 深度监听
当修改数组的值时 不使用深度监听 是不会监听到数组的变化
<template>
<div>
<ul>
<li v-for="item in listData" :key="item.id">
<div>{{ item.label }}</div>
</li>
</ul>
<button @click="updateArr">更新数组</button>
</div>
</template>
<script>export default{
data() {
return {
listData: [
{ id:11,label: '栏目分类', key: 'cclassID', type: 'select' }
]
}
},
watch: {
listData(data){
console.log(data) // 点击按钮时这里不会输出
},
listData: {
deep: true, // 开启深度监听
handler(data){
// 输出 [{ id:11,label: '测试一下', key: 'cclassID', type: 'select' }]
console.log(data)
}
}
},
methods: {
updateArr () {
this.listData[0].label = "测试一下"
}
}
}
</script>
9,transition css3过渡动画
在页面切换的时候可以加上css3的过渡动画效果
<template>
<transition name="testTransition">
<!-- 这里可以是组件 也可以是router-view -->
</transition>
</template>
<style>
// 可以设置不同的进入和离开动画
// 设置持续时间和动画函数
.testTransition-enter-active,
.testTransition-leave-active {
transition: all 0.3s;
}
.testTransition-enter,
.testTransition-leave-to {
transform: translate3d(100%, 0, 0);
}
</style>