VUE的高级特性

自定义 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)"
  />
  <!-- 
    1. 上面的 input 使用了 :value 而不是 v-model
    2. 上面的 changeMethod 和 model.event 要对应起来
    3. textVal 属性对应起来
   -->
</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>

在这里插入图片描述

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

  • 可以不写model,但是需要改 $emit('input',$event.target.value)
    在这里插入图片描述
    在这里插入图片描述

$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 -->
    <NextTick />
  </div>
</template>
  • 我们不用$nextTick时,是拿不到push之后的DOM节点
    在这里插入图片描述
  • 但是用$nextTick,就可以拿到渲染之后的DOM节点
    在这里插入图片描述

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">
    <!-- slot -->
    <!-- 父组件没有内容 -->
    <SlotDemo :url="slotData.url"
              #rmq></SlotDemo>
    <!-- 父组件有内容 -->
    <SlotDemo :url="slotData.url"
              #rmq>
      <template>{{ slotData.title }}</template>
    </SlotDemo>
    <!-- 父组件接收子组件传过来的slotData1的值,用 SlotProps 接收-->
    <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>

在这里插入图片描述

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>

通过<component :is="componentName"></component>,来动态加载组件

在这里插入图片描述

  • 异步加载组件

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

<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>
  • 异步加载之前
    在这里插入图片描述
  • 异步加载之后
    在这里插入图片描述

keep-alive缓存组件

  • Props:

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

  • 用法:

<keep-alive> 包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。和 <transition> 相似,<keep-alive> 是一个抽象组件:它自身不会渲染一个 DOM 元素,也不会出现在组件的父组件链中。
当组件在 <keep-alive> 内被切换,它的 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>` 一起使用 -->
<transition>
  <keep-alive>
    <component :is="view"></component>
  </keep-alive>
</transition>

<!-- 逗号分隔字符串 -->
<keep-alive include="a,b">
  <component :is="view"></component>
</keep-alive>

<!-- 正则表达式 (使用 `v-bind`) -->
<keep-alive :include="/a|b/">
  <component :is="view"></component>
</keep-alive>

<!-- 数组 (使用 `v-bind`) -->
<keep-alive :include="['a', 'b']">
  <component :is="view"></component>
</keep-alive>

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

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

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">click</button>
  </div>
</template>

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

在这里插入图片描述

可以看到组件中能够使用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!"
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值