Vue组件进阶: 语法糖 - ref - $nextTick - dynamic

193 阅读2分钟

Vue组件进阶

v-model 语法糖

语法糖:v-model本质上是 value属性和input事件的一层包装

v-model的作用:提供数据的双向绑定

  • 数据发生了改变,页面会自动变 v-bind:value
  • 页面输入改变 , 数据会自动变化 v-on:input

v-model是语法糖, v-model等价于 给一个input框提供了 :value属性以及 @input事件

很显然如果每次使用input框,都需要提供value和input事件,比较麻烦,所以使用v-model

<template>
  <div>
    <input type="text" v-model="msg">
    <input type="text" :value="msg" @input="msg = $event.target.value">
​
    <input type="text" :value="car" @input="car = $event.target.value">
    <input type="text" v-model="car">
  </div>
</template>

v-model给组件使用

经常遇到一种场景:

  1. 父组件提供一个数据给子组件使用(父传子)
  2. 子组件又需要修改父组件传过来的这个数据,所以需要子传父把值传给父组件。

这种场景可以使用v-model进行简写。

  • 定义组件的时候,注意接收的值叫value, 子传父触发的事件叫 input

image.png

  • 父传子给子组件传递value属性和input事件

image.png

ref 和 $refs

利用 ref 和 $refs 可以用于获取 dom 元素, 或者组件实例

每个 vue 的组件实例上,都包含一个$refs 对象,里面存储着对应的DOM 元素或组件的引用。

1 给需要获取的 dom 元素或者组件, 添加 ref 属性

<div>
  <div ref="box">我是div盒子</div>
  <jack ref="jack"></jack>
  <button @click="fn">按钮</button>
</div>

2 通过 this.$refs.xxx 获取, 拿到组件可以调用组件的方法

import Jack from './jack.vue'
export default {
  methods: {
    fn () {
      console.log(this.$refs.box)
      console.log(this.$refs.jack)
      this.$refs.jack.sayHi()
    }
  },
  components: {
    Jack
  }
}

$nextTick

点击按钮, 切换显示输入框

<template>
  <div>
    <!-- 点击按钮, 切换显示输入框 -->
    <input type="text" v-if="isShowInput">
    <button @click="fn" v-else>点此搜索</button>
  </div>
</template><script>
export default {
  data () {
    return {
      isShowInput: false
    }
  },
  methods: {
    fn () {
      this.isShowInput = true
    }
  }
}
</script>

显示输入框的同时, 要获取焦点

当文本框展示出来之后,如果希望它立即获得焦点,则可以为其添加 ref 引用,并调用原生 DOM 对象的.focus() 方法即可。

直接调用会报错, 因为 vue 是 异步dom更新的 (提升渲染效率), this.isShowInput = true 执行完时, 实际的 dom 还没渲染出来

<input ref="inp" type="text" v-if="isShowInput">
​
fn () {
  this.isShowInput = true
  this.$refs.inp.focus()
}

组件的 $nextTick(callback) 方法,会把 callback 回调推迟到下一个 DOM 更新周期之后执行。

通俗的理解是:等组件的DOM 刷新之后,再执行 callback 回调函数。从而能保证 callback 函数可以操作到最新的 DOM 元素。

<template>
  <div>
    <!-- 需求: 点击按钮, 切换显示输入框 -->
    <input ref="inp" type="text" v-if="isShowInput">
    <button @click="fn" v-else>点此搜索</button>
  </div>
</template><script>
export default {
  data () {
    return {
      isShowInput: false
    }
  },
  methods: {
    fn () {
      this.isShowInput = true
      this.$nextTick(() => {
        this.$refs.inp.focus()
      })
    }
  }
}
</script>

dynamic 动态组件

动态组件的基本使用

什么是动态组件: 让多个组件使用同一个挂载点,并动态切换,这就是动态组件

<template>
  <div>
    <h3>动态组件的演示</h3>
    <!-- 动态组件 => 多个组件使用同一个挂载点, 并可以动态的切换展示 -->
    <button @click="comName = 'my-swiper'">swiper</button>
    <button @click="comName = 'my-nav'">nav</button>
    
    <!-- 
      <my-nav></my-nav>
      <my-swiper></my-swiper> 
    -->
    <component :is="comName"></component>
  </div>
</template><script>
import MyNav from './my-nav.vue'
import MySwiper from './my-swiper.vue'
export default {
  data () {
    return {
      comName: 'my-nav'
    }
  },
  components: {
    MyNav,
    MySwiper
  }
}
</script>