Vue3复习:组件的v-model

1,272 阅读1分钟

官方文档v-model:v3.cn.vuejs.org/guide/migra…

(1). 父组件A调用子组件B,父组件通过 v-model ="msg" 来绑定值,子组件需要通过内置的默认值 modelValue 来接收。

(2). 对于父组件而言,v-model="msg",相当于 :modelValue="msg" @update:modelValue="msg=$event" (赋值的同时,监听到子组件的变化,收到最新值$event,并且赋值给 msg)

(3). 对于子组件而言,也可以通过 v-model="modelValue"来赋值(前提是input、select等标签),此时将自动监听modelVaule的变化,拿到变化值需要通过 emit对外传递。 通过中转自动监听modelValue的变化有两种方式:

A. 通过computed属性处理一下modelValue值,然后再给v-model绑定

B. 通过watch监听modelValue值,变化的时候emit对外传递。

(4). 对于子组件而言,v-model="modelValue" 也等价于 :modelValue="modelValue[xx]"    @update:modelValue="handleValueChange($event, x)"然后在handelValueChange方法中实现对外emit 

(5). 父组件中也可以通过v-model绑定其它值,不用默认的modelValue传递,比如: v-model:title="msg",等价于  :title="msg", @update:title="msg=$event" ,子组件在props中通过title接收到父组件传递的值。

父组件 App.vue

<template>
  <div class="app">
    {{ msg }}
    <hr />
    <!-- 这里故意给modelValue改名字为msg 子组件需要通过 msg来接收 -->
    <home v-model:msg="msg"></home>
    <hr />
    <!-- 这里没有改名字 那么子组件 要通过默认的props接收 -->
    <about v-model="msg"></about>
  </div>
</template>

<script>
import Home from "@/components/Home.vue";
import About from "@/components/About.vue";

import { ref } from "vue";
export default {
  name: "App",
  components: {
    Home,
    About,
  },
  setup() {
    const msg = ref("App");
    return {
      msg,
    };
  },
};
</script>

<style></style>

子组件 Home.vue

<template>
  <div>
    {{ msg }}
    <!-- 注意这里,是通过value绑定值,修改值通过发射事件去修改 -->
    <input type="text" :value="msg" @input="inputChange" />
  </div>
</template>

<script>
export default {
  props: {
    // 因为父组件重新命名了, 这里我们要通过msg来接收
    msg: {
      type: String,
      default: "",
    },
  },
  emits: ["update:msg"],
  setup(props, { emit }) {
    // 通过发射事件去修改值
    const inputChange = (event) => {
      // 因为改了名字 所以是update:msg 默认的 update:modelValue
      emit("update:msg", event.target.value);
    };
    return {
      inputChange,
    };
  },
};
</script>

<style lang="scss" scoped></style>

子组件About.vue

<template>
  <!-- 这里为了保证单项数据流,我们重新copy了一份数据 -->
  <div>{{ modelValue }} <input type="text" v-model="modelValueCopy" /></div>
</template>

<script>
import { ref, watch } from "vue";
export default {
  props: ["modelValue"],
  emits: ["update:modelValue"],
  setup(props, { emit }) {
    // 如果是对象 那么需要 ref( {...props.modelValue});
    // 如果是对象 并且是多层次的 需要深拷贝
    const modelValueCopy = ref(props.modelValue);

    // 如果是对象,那么要deep:true 深度监听
    // 如果我们拷贝的数据发生变化,我们就发射事件,并且把值带过去,这种方法很巧妙
    watch(modelValueCopy, (newValue) => {
      emit("update:modelValue", newValue);
    });

    return {
      modelValueCopy,
    };
  },
};
</script>

<style lang="scss" scoped></style>

最终效果:

gif.gif