Vue高级特性总结

267 阅读2分钟

自定义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>
输出结果: 369//这里因为是异步渲染,获取不到最新的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和组件可能出现多对多的关系,复杂度较高