• vue3.4的更新,保证你看的明明白白


    defineModel 同学已经转正

    defineModel 在vue3.3中还是一个实验性功能,
    但是经过一个学期的努力,该同学已经转正。
    

    defineModel的简单介绍

    defineModel() 返回的值是一个 ref。
    它可以像其他 ref 一样被访问以及修改。
    它能起到在父组件和当前变量之间的双向绑定的作用。
    它的 .value 和父组件的 v-model 的值同步。
    当它被子组件改变时,会触发父组件绑定的值一起更新。
    
    我们都知道 props 的设计原则是单项数据流。
    子组件默认情况下是无法更改父组件传递过来的数据。
    如果要更改vue3.3以前是通过 $emit 来实现的。
    下面我们来对比一下使用 $emit 和 defineModel 来更新数据
    

    使用 $emit更新父组件传递过来的数据(vue3.2)

    // 父页面
    <template>
      <div>
        <div class="father-box">
          <p>我是父页面-此时:son组件的值{{ flag }}p>
          <button @click="openHandler"> 显示子组件button>
        div>
        
        <son v-model:flag="flag">son>
      div>
    template>
    <script setup lang="ts">
    // vue3.2开始组件引入后,就不需要注册啦。变量也不需要暴露出去啦
    import son from '@/components/son.vue'
    import { ref } from 'vue';
    let flag = ref(false)
    // 点击事件,更改值,让组件显示出来
    const openHandler = ()=>{
      flag.value = true;
    }
    script>
    <style>
    .father-box{
      background: palegreen;
    }
    style>
    
    // son组件
    <template>
      <div class="son-box" v-if="flag">
        <h1 >我是son组件h1>
        <button @click="hideHandler"> 关闭组件:更改父组件传递过来的值button>
      div>
    template>
    <script setup lang="ts">
    import { defineProps, defineEmits } from "vue";
    // 接收传递过来的值
    defineProps({
      flag: {
        type: Boolean,
        default: false,
      }
    });
    // 注册事件
    const emits = defineEmits(["update:flag"]);
    // 去更新父组件中的flag值,更改为false
    const hideHandler = () => {
      emits("update:flag", false)
    }
    script>
    <style>
    .son-box{
       background: pink;
    }
    style>
    

    使用 defineModel 更新父组件传递过来的数据(vue3.4)

    // 父页面代码
    <template>
      <div>
        <div class="father-box">
          <p>我是父页面-此时:son1组件的值{{ flag }}p>
          <button @click="openHandler"> 显示子组件button>
        div>
        
        <son1 v-model:flag="flag">son1>
      div>
    template>
    <script setup lang="ts">
    // vue3.2开始组件引入后,就不需要注册啦。变量也不需要暴露出去啦
    import son1 from '@/components/son1.vue'
    import { ref } from 'vue';
    let flag = ref(false)
    // 点击事件,更改值,让组件显示出来
    const openHandler = ()=>{
      flag.value = true;
    }
    script>
    <style>
    .father-box{
      background: palegreen;
    }
    style>
    
    // son1组件
    <template>
      <div class="son-box" v-if="flagBool">
        <h1 >我是son1组件h1>
        <button @click="hideHandler"> 关闭组件:更改父组件传递过来的值button>
      div>
    template>
    
    <script setup lang="ts">
    import { defineModel } from "vue";
    // defineModel('flag')中的flag必须与传递过来的属性保持一致
    // flagBool 是接受的控制变量,可以是任意的
    const flagBool = defineModel('flag')
    const hideHandler = () => {
      flagBool.value = false
    }
    script>
    <style>
    .son-box{
       background: pink;
    }
    style>
    

    采访一下:使用 defineModel 后的感觉

    现在使用 defineModel 进行数据的双向绑定更加友好。
    比原来更加方便了。爽歪歪!
    原来需要再一个合适的时机(事件触发)写上:
    emits("update:flag", false)
    而现在直接写上 const 变量名 = defineModel('双向绑定的值')
    不需要考虑时机
    

    defineModel 传递多个v-model

    // 父页面
    <template>
      <div>
        <div class="father-box">
          <p>我是父页面-此时:son3组件的值{{ titleName }} {{ address }}p>
        div>
        
        <son3 v-model:titleName="titleName" v-model:address="address">son3>
      div>
    template>
    <script setup lang="ts">
    // vue3.2开始组件引入后,就不需要注册啦。变量也不需要暴露出去啦
    import son3 from '@/components/son3.vue'
    import { ref } from 'vue'
    let titleName = ref('少玩手机多看报')
    let address = ref('我在这个红绿灯旁边')
    script>
    <style>
    .father-box{
      background: palegreen;
    }
    style>
    
    // 组件son3