VUE的高级特性

  • 自定义 v-model
  • $nextTick
  • slot使用
  • 动态、异步加载组件
  • keep-alive缓存组件
  • mixin混入

自定义 v-model

在 vue 中,v-model 是用来进行数据双向绑定的一个语法糖,比如说用在 input 上,输入框数据变化,v-model 绑定的对应的值也会跟着变化,无需单独获取。
其实 v-model 还可以在自定义组件中使用,可以被拆解为 props:value 和 event:input,也就是说组件必须接收一个 value 值以及名为 input 的自定义事件,就可以在自定义组件上使用 v-model 了。

  • 新建一个组件UseVModel.vue
<template>
  <input
    type="text"
    :value="textVal"
    @input="$emit('changeMethod', $event.target.value)"
  />
  
template>

<script>
export default {
  props: {
    textVal: {
      type: String,
      default: () => '',
    },
  },
  model: {
    props: 'textVal',
    event: 'changeMethod',
  },
}
script>
  • 引用组件
<template>
  <p>{{ name }}p>
  <UseVModel v-model="name" />
template>

<script>
import UseVModel from '@/components/UseVModel.vue'
export default {
  components: {
    UseVModel,
  },
  data() {
    return {
      name: 'rmq',
    }
  },
}
script>

VUE的高级特性_第1张图片

我个人觉得有点类似于父子组件传值,父组件通过v-model传值,子组件props接收,通过 :value,绑定值,然后通过 $emit() 触发事件又传值给父组件,实现双向绑定。

  • 可以不写model,但是需要改 $emit('input',$event.target.value)
    VUE的高级特性_第2张图片
    VUE的高级特性_第3张图片

$nextTick

$nextTick() 是在下次DOM更新循环结束之后执行延迟回调,在修改数据之后使用 $nextTick,则可以在回调中获取更新后的DOM(DOM的改变是发生在 $nextTick()之后),这个方法作用是当数据被修改后使用这个方法,会回调获取更新后的DOM再render出来。
$nextTick()作用:在下次DOM更新循环结束之后,执行延迟回调。在修改数据之后立即使用这个方法,获得更新后的DOM。

  • 创建一个组件NextTick
<template>
  <div>
    <ul ref="ul1">
      <li v-for="(item, index) in list" :key="index">{{ item }}li>
    ul>
    <button @click="change">添加button>
  div>
template>

<script>
export default {
  data() {
    return {
      list: ['a', 'b', 'c'],
    }
  },
  methods: {
    change() {
      this.list.push(`${Date.now()}`)
      this.list.push(`${Date.now()}`)
      this.list.push(`${Date.now()}`)
      // 直接这样写,获取到的是渲染之前的3个
      // const ul = this.$refs.ul1
      // console.log(ul.childNodes.length)

      //this.$nextTick()
      // vue 是 异步渲染,this.$nextTick()待 DOM 渲染完成后再回调
      // 页面渲染时会将 data 修改整合, 多次的 data 修改 只会渲染一次
      this.$nextTick(() => {
        const ul = this.$refs.ul1
        console.log(ul.childNodes.length)
      })
    },
  },
}
script>
  • 引用组件
<template>
  <div class="home">
    
    <NextTick />
  div>
template>
  • 我们不用$nextTick时,是拿不到push之后的DOM节点
    VUE的高级特性_第4张图片
  • 但是用$nextTick,就可以拿到渲染之后的DOM节点
    VUE的高级特性_第5张图片

slot使用

  • 创建子组件SlotDemo
<template>
  <div>
    <a :href="url">
      <slot :slotData1="slotData1"
            name="rmq">父组件没有东西时显示默认内容slot>
    a>
  div>
template>

<script>
export default {
  data () {
    return {
      slotData1: {
        url: 'www.baidu.com1',
        title: 'slot1',
        subTitle: 'hello slot1',
      },
    }
  },
  props: {
    url: {
      type: String,
      default: '',
    },
  },
}
script>
  • 引用
<template>
  <div class="home">
    
    
    <SlotDemo :url="slotData.url"
              #rmq>SlotDemo>
    
    <SlotDemo :url="slotData.url"
              #rmq>
      <template>{{ slotData.title }}template>
    SlotDemo>
    
    <SlotDemo :url="slotData.url">
      <template #rmq="SlotProps">
        {{ SlotProps.slotData1.subTitle }}
      template>
    SlotDemo>
  div>
template>
<script>
import SlotDemo from '@/components/SlotDemo.vue'
export default {
  components: {
    SlotDemo,
  },
  data() {
    return {
      slotData: {
        url: 'www.baidu.com',
        title: 'slot',
        subTitle: 'hello slot',
      },
    }
  },
}
script>

VUE的高级特性_第6张图片

propsv-slot配合也可以用来父子组件之间传值

动态、异步加载组件

  • 动态组件

一个页面的构成可以动态控制

<template>
  <div>
    
    <div v-for="(val, key) in comList" :key="key">
      <component :is="val.componentName">component>
    div>
  div>
template>
<script>
export default {
  data() {
    return {
      comList: {
        1: { componentName: 'text' },
        2: { componentName: 'text' },
        3: { componentName: 'image' },
      },
    }
  },
}
script>

通过,来动态加载组件

VUE的高级特性_第7张图片

  • 异步加载组件

对于大的组件或者有异步加载组件需求的时候可以用

<template>
  <div class="home">
    
    <WatchEventCom v-if="showCom">WatchEventCom>
    <button @click="showCom = true">异步加载组件button>
    <hr />
  div>
template>
<script>
export default {
  components: {
    WatchEventCom: () => import('@/components/WatchEvent'), //如果同时引入2个相同组件,则不会异步加载,没有效果 
    Mixin,
  },
    data() {
    return {
      showCom: false,
    }
  },
}
script>
  • 异步加载之前
    VUE的高级特性_第8张图片
  • 异步加载之后
    VUE的高级特性_第9张图片

keep-alive缓存组件

  • Props:

include - 字符串或正则表达式。只有名称匹配的组件会被缓存。
exclude - 字符串或正则表达式。任何名称匹配的组件都不会被缓存。
max - 数字。最多可以缓存多少组件实例。

  • 用法:

包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。和 相似, 是一个抽象组件:它自身不会渲染一个 DOM 元素,也不会出现在组件的父组件链中。
当组件在 内被切换,它的 activateddeactivated 这两个生命周期钩子函数将会被对应执行。


<keep-alive>
  <component :is="view">component>
keep-alive>


<keep-alive>
  <comp-a v-if="a > 1">comp-a>
  <comp-b v-else>comp-b>
keep-alive>


<transition>
  <keep-alive>
    <component :is="view">component>
  keep-alive>
transition>


<keep-alive include="a,b">
  <component :is="view">component>
keep-alive>


<keep-alive :include="/a|b/">
  <component :is="view">component>
keep-alive>


<keep-alive :include="['a', 'b']">
  <component :is="view">component>
keep-alive>

<keep-alive :max="10">
  <component :is="view">component>
keep-alive>

注意, 是用在其一个直属的子组件被开关的情形。如果你在其中有 v-for 则不会工作。如果有上述的多个条件性的子元素, 要求同时只有一个子元素被渲染。

mixin混入

  • 写一个mixin.js
export default {
  data() {
    return {
      name: 'rmq'
    }
  },
  mounted() {
    console.log('mixin');
  },
  methods: {
    mixinMethod() {
      console.log('点击了mixin');
    }
  },
}
  • 引入组件中
<template>
  <div>
    <p>name:{{name}}p>
    <p>age:{{age}}p>
    <button @click="mixinMethod">clickbutton>
  div>
template>

<script>
import mixin from '../assets/mixin';
export default {
  mixins: [mixin],
  data () {
    return {
      age: '18'
    };
  },
}
script>

VUE的高级特性_第10张图片

可以看到组件中能够使用mixin,js中的data/methods等的数据方法。相当于把2个合并了。
这样可以抽离一些相同的逻辑,但是会有数据冲突

  • 全局混入
// 为自定义的选项 'myOption' 注入一个处理器。
Vue.mixin({
  created: function () {
    var myOption = this.$options.myOption
    if (myOption) {
      console.log(myOption)
    }
  }
})

new Vue({
  myOption: 'hello!'
})
// => "hello!"

你可能感兴趣的:(vue)