• Vue | 自定义组件双向绑定基础用法


    Vue | 自定义组件双向绑定基础用法

    vue 中,由于单向数据流,常规的父子组件属性更新,需要 在父组件绑定相应属性,再绑定相应事件,事件里去做更新的操作,利用语法糖 可以减少绑定事件的操作。

    这里就简单的梳理一下vue提供的双向更新的语法糖用法(水一篇,为了节省篇幅只给了关键部分的代码)。

    vue2

    v-model

    基础使用
    
    <template>
      <div class="vmodel-test">
      	V-model 测试
        <hr />
        v-model 默认基础类型值 | <span>{{ val }}span>
        <inner v-model="val">inner>
      div>
    template>
    
    export default {
      name: "VmodelTest",
      components: { inner },
      data() {
        return {
          val: 11111,
        }
      }
    }  
    
    
    <template>
      <div class="inner">
        <button @click="onUPdate">更改button>
      div>
    template>
    <script>
    export default {
      name: "Inner",
      props: {
        value: {
          type: [String, Number],
          default: "",
        },
      },
      data() {
        return {};
      },
      methods: {
        onUPdate() {
    	  // 更新
          this.$emit("input", new Date().toLocaleString());
        },
      },
    };
    script>
    

    在这里插入图片描述

    简单总结就是, 对于父组件 v-model 绑定的值,子组件 需要 定义一个 value 的props,然后更新时使用 input 事件 去更新值,适用于基础类型和对象类型,⚠️需要注意的是这种更新是全量更新(覆盖式)

    比如我 v-model 接受的是一个对象,我只想更新对象的 a 属性

    // 更新
    this.$emit("input", {
      ...this.value,
      a: new Date().toLocaleString(),
    });
    
    自定义更新事件名

    model: 允许一个自定义组件在使用 v-model 时定制 prop 和 event。默认情况下,一个组件上的 v-model 会把 value 用作 prop 且把 input 用作 event,但是一些输入类型比如单选框和复选框按钮可能想使用 value prop 来达到不同的目的。使用 model 选项可以回避这些情况产生的冲突。API — Vue.js

    input 是默认事件,可以自定义,需要 在子组件 写一个 model(2.2新增) 属性去更改

    model: {
      prop: "value", // 指定是更新value
      event: "custom-update-value", // 一般以 update:value 命名
    },
    props: {
      value: {
        type: [Array, Object],
        default: () => {},
      },
    },
    

    那么 更新时只需要用新的事件名,⚠️原来默认input事件已经失效

    // 更新
    this.$emit("custom-update-value", {
      ...this.value,
      a: new Date().toLocaleString(),
    });
    

    sync 修饰符

    基础使用

    sync 修饰符也双向更新的一个方法,更适用于多个属性需要双向更新的场景

    首先在父组件中绑定绑定的属性后面,跟上sync修饰符

    sync 修饰符 | <span>{{ modelValue3 }}</span>
    <inner3 :model-value.sync="modelValue3"></inner3>
    

    子组件更新时, 事件名 update: 拼上 属性名

    //...
    props: {
      modelValue: {
        type: [Array, Object],
        default: () => {},
      },
    },
    //...
    // 更新
    this.$emit("update:modelValue", {
      ...this.value,
      b: [1, new Date().toLocaleString()],
    });
    

    在这里插入图片描述

    也是全量更新, ⚠️注意这种方式不支持 model 方式自定义事件名

    一次性绑定多个(v-bind.sync)

    支持 v-bind 一次性绑定多个值的方式

    <!--  -->
    sync 修饰符 对象解构传入(vbind) | <span>{{ modelValue4 }}</span>
    <inner4 v-bind.sync="modelValue4"></inner4>
    
    //...(节省篇幅,只给出相应的data)
    modelValue4: {
      a: { val: 111 },
      b: [1, 2]
    },
    
    /** 子组件 **/
    props: {
      a: {
        type: [Array, Object],
        default: () => {},
      },
      b: {
        type: [Array, Object],
        default: () => {},
      },
    },
    //...
    // 更新
    this.$emit("update:a", {
       ...this.a,
       val: new Date().toLocaleString(),
    });
    this.$emit("update:b", [1, new Date().toLocaleString()]);
    

    在这里插入图片描述

    vue3

    v-model

    基础使用

    父组件传的v-model,子组件用 modelValue 接收

    
    v-model 默认-对象类型值 | <span>{{ modelValue1 }}span>
    <inner1 v-model="modelValue1">inner1>
    

    子组件 使用 update:modelValue 更新值

    <!-- 子组件 -->
    <script setup lang='ts'>
    const props = defineProps(['modelValue'])
    const emit = defineEmits(['update:modelValue'])
    
    const onUPdate = () => {
       // 更新
       emit("update:modelValue", {
        ...props.modelValue,
        a: new Date().toLocaleString(),
      });
    }
    </script>
    

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    均是全量更新

    绑定多个值
    <!-- 父组件 -->
    v-model 绑定多个值 | <span>{{ modelValue2 }} | {{ modelValue21 }}</span>
    <inner2 
        v-model:modelCusValue="modelValue2" 
        v-model:modelCusValue1="modelValue21"
    ></inner2>
    
    /** 子组件 **/
    <script setup lang='ts'>
      const props = defineProps(['modelCusValue', 'modelCusValue1'])
      const emit = defineEmits(['update:modelCusValue', 'update:modelCusValue1'])
    
      const onUPdate = () => {
          // 更新
    	  emit("update:modelCusValue", {
            ...props.modelCusValue,
            a: new Date().toLocaleString(),
          });
          emit("update:modelCusValue1", {
            ...props.modelCusValue1,
            a: new Date().toLocaleString(),
          });
      }
    </script>
    

    在这里插入图片描述

    也是全量更新

    defineModel

    基础使用

    此宏为 3.4 新增,使用起来比前面的方式稍微简洁一些。装个 vue-eslint-parser 且在 vite.config.ts 做如下配置 plugins, 避免编译器报错。

    export default defineConfig({
      plugins: [
        vue({
          // 开启 definModel
          script: { defineModel: true }
        }),
      ]
      //...
    })
    
    <!-- 父组件 -->
    defineModel() | <span>{{ modelData }} | {{ modelData1 }} | {{ modelData2 }}</span>
    <inner3
        v-model="modelData" 
        v-model:modelData1="modelData1"  
        v-model:modelData2="modelData2"
    ></inner3>
    //...
    const modelData1 = ref({
      a: 1,
      b: [1, 2],
    })
    const modelData2 = ref({
      a: 1,
      b: [1, 2],
    })
    

    此方法在子组件使用 直接使用 属性 value 赋值就行了

    <script setup lang='ts'>
    type modelValueType = {
      a: number | string,
      b: Array<number>
    }
    let model = defineModel<modelValueType>({ required: true })
    let model1 = defineModel<modelValueType>('modelData1', { required: true })
    let model2 = defineModel<modelValueType>('modelData2', { 
      required: true, 
      type: Object,
      default: { a: 0, b: [2,3] } 
    })
    
    const onUPdate = () => {
      // 更新
      model.value = {
        ...model.value,
        b: [2, 1],
        a: new Date().toLocaleString()
      }
      model1.value.a = new Date().toLocaleString();
      model2.value.a = new Date().toLocaleString();
      // 或者如下方式
      // Object.assign(model.value, { a: new Date().toLocaleString() });
    }
    </script>
    

    这种方式 支持单个属性更新,全量更新只需全部赋值,比较灵活
    在这里插入图片描述

    最后

    若行文有误,望评论区交流。

  • 相关阅读:
    【ArcGIS】重采样栅格像元匹配问题:不同空间分辨率栅格数据统一
    【leetcode】【2022/8/23】782. 变为棋盘
    MATLAB® 空间数学工具箱——旋转函数
    Spring Framework 学习笔记5:事务
    信泰如意享七金版养老年金保险怎么样,好不好?
    前端面试指南之React篇(二)
    SpringMvc+Spring+MyBatis+Maven+Ajax+Json注解开发 利用Maven的依赖导入不使用架包模式 (实操十)
    Spring Boot项目介绍(值得学习,超详细)
    内核态和用户态
    政务场景下-基于OAuth2.0 统一认证中心架构设计
  • 原文地址:https://blog.csdn.net/qq_39370934/article/details/139222599