vue2的高级特性

408 阅读3分钟

自定义v-model

一般情况下的话,我们使用input要对变量name进行绑定,会用到vue组件的input的v-model来对变量name进行绑定

<template>
    <div>
			<p>{{name}}</p>
      <input type="text" v-model="name">
    </div>
</template>

这样子就可以对数据进行绑定,而当自定义组件的时候需要使用到数据绑定的时候

<template>
    <div>
			<p>{{name}}</p>
      <CustomVModel v-model="name">
    </div>
</template>

上面中的CustomVModel表示自定义组件。

下面是自定义组件的代码

<template>
    <!-- 例如:vue 颜色选择 -->

    <input type="text"
        :value="content"
        @input="$emit('change1', Number($event.target.value) )"
    >
	

    <!--
        1. 上面的 input 使用了 :value 而不是 v-model
        2. 上面的 change1 和 model.event1 要对应起来
        3. text1 属性对应起来
    -->
</template>

<script>
export default {
    model: {
        prop: 'content', // 对应 props text1
        event: 'change1'
    },
    // 定义一个属性,用来传递值
    props:{
        content:String  , //数字
        default(){
            return ""
        }
    }
}
</script>

在上面的组件CustomVModelinput使用的不是v-bind而是:value 绑定值的属性+ @input事件来实现 来实现

:value用来绑定变量content、以及限制变量的属性,用来记录外部组件传入的参数

@input则是用来改变变量,当输入的文本变化的时候,触发变量,

props用来接收属性,定义类型和默认值

model用来定义一个prop和一个事件event

Vue组件如何使用

props和$emit

props几种写法

可以结合v-model起来一起向下传递数据流

props: ['postTitle']

加上验证

Vue.component('my-component', {
  props: {
    // 基础的类型检查 (`null` 和 `undefined` 会通过任何类型验证)
    propA: Number,
    // 多个可能的类型
    propB: [String, Number],
    // 必填的字符串
    propC: {
      type: String,
      required: true
    },
    // 带有默认值的数字
    propD: {
      type: Number,
      default: 100
    },
    // 带有默认值的对象
    propE: {
      type: Object,
      // 对象或数组默认值必须从一个工厂函数获取
      default: function () {
        return { message: 'hello' }
      }
    },
    // 自定义验证函数
    propF: {
      validator: function (value) {
        // 这个值必须匹配下列字符串中的一个
        return ['success', 'warning', 'danger'].indexOf(value) !== -1
      }
    }
  }
})

$emit

name表示函数的名字,比如changeName,data可能是this.title或者其他

父子组件进行通信

this.$emit(name,data)表示子组件向父组件触发一个事件(这个事件在父组件中),这样子就可以把子组件的数据传入,然后在父组件进行处理,然后进行通信

event.$emit 表示自定义的事件

组件间的通信——自定义事件

兄弟组件进行通信

进行事件的触发

event.$emit(name,data)

进行事件的绑定

mounted中 event.$on(name,name) 后面的那个name是函数的名字,比如event.$on('onAddTitle',this.addTitleHandler)

之后需要在beforeDestory中进行解绑,

event.$off(name,name),event.$on('onAddTitle',this.addTitleHandler)

event是从哪里来的呢?

event是在一个new实例中

//event.js
import Vue from 'vue'

export default new Vue()

vue中具有自定义事件

组件生命周期

挂载阶段

beforeCreate

Created

beforeMount

mounted

\

\

created和mounted的区别

created只是把实例给初始化了,还没有开始渲染

mounted是在网页上真正渲染完成了

更新阶段

beforeupdate

Updated

销毁阶段

beforeDestroy

destroyed

$nextTick

$nextTick会在DOM渲染之后被触发,以获取最新的DOM节点

使用nextTick后会让数据进行异步渲染,就是让之前的变量渲染完成后,再来渲染想要的变量。

回调函数渲染

  methods: {
    addItem() {
        this.list.push(`${Date.now()}`)
        this.list.push(`${Date.now()}`)
        this.list.push(`${Date.now()}`)
        // 1. 异步渲染,$nextTick 待 DOM 渲染完再回调
        // 3. 页面渲染时会将 data 的修改做整合,多次 data 修改只会渲染一次
        this.$nextTick(() => {
          // 获取 DOM 元素
          const ulElem = this.$refs.ul1
          // eslint-disable-next-line
          console.log( ulElem.childNodes.length )
        })
    }
  }

当数据进行变化后,等待渲染之后再进行显示

refs

const ulElem = this.$refs.ul1

slot

<template>
    <a :href="url">
        <slot>
            默认内容,即父组件没设置内容时,这里显示
        </slot>
    </a>
</template>

<script>
export default {
    props: ['url'],
    data() {
        return {}
    }
}
</script>

让子组件插入父组件的内容

父组件通过:url向子组件传递链接,然后通过SlotDemotitle传递给子组件

子组件通过props接收来自父组件的链接url,然后通过slot标签将父组件的title给渲染出来。

作用域插槽

父组件能够获取到子组件的内容,然后进行显示

\

动态组件

对组件通过名字进行动态显示,

<component :is="NextTickName" />

这里的等号后面接的内容是一个data中的变量

异步组件

  • import()函数
  • 按需加载,异步加载最大组件

使用动态的方式来进行组件的引入

再components中使用

FormDemo:()=>import('../BaseUse/FormDemo')

将组件进行异步引入

一开始不加载,点击按钮后再对组件进行加载

什么使用到的话,什么时候再进行加载

异步加载,等都加载后再进行加载

keep-alive

缓存组件,频繁切换tab

  • 缓存组件
  • 频繁切换,不要重新渲染
  • Vue常见性能优化

正常的情况下,点击组件的切换,会不断进行渲染和销毁

v-if是原生的

keep-alive是通过vue来对子组件进行缓存后,进行切换的时候,组件不会频繁进行切换和销毁

通过keep-alive对三个子组件进行缓存,这样子组件进行切换的时候,就不用进行重新渲染和销毁

mixin

  • 多个组件有相同的逻辑,抽离出来
  • mixin并不是完美的解决方案,会有一些问题
  • Vue3的compostion用来解决这种问题

抽离出来,然后通过mixin进行混合,父组件使用import引入js文件,然后通过prop进行引入

存在覆盖的现象

\