美文网首页
vue(2/3)中在组件上使用v-model

vue(2/3)中在组件上使用v-model

作者: 踏莎行 | 来源:发表于2021-11-26 21:28 被阅读0次

v-model一般用于表单数据的双向绑定,使用起来也很方便,但是本质上他还是一个语法糖,先拿input输入框举个例子

自定义一个MyInput组件

<template>
  <div>
    <input
      type="text"
      :value="value"
      @input="$emit('input', $event.target.value)"
    />
  </div>
</template>

<script>
export default {
  props: {
    value: String,
  },

  methods: {
    change() {
      this.$emit("input", "hahah");
    },
  },
};
</script>

创建一个父组件,导入并注册MyInput组件

<template>
  <div>
    <MyInput :value="value" @input="value = $event"></MyInput>
    父组件的value:{{ value }}
  </div>
</template>

<script>
import MyInput from "../components/MyInput.vue";
export default {
  components: {
    MyInput,
  },
  data() {
    return {
      value: "",
    };
  },
};
</script>

看结果


Snipaste_2021-11-27_19-53-19.png

这样我们就实现了一个v-model,本质上就是为input元素的value属性进行数据绑定,然后通过一个input事件将当前文本框的内容发送给父组件,父组件监听一个input事件,将传递过来的值赋值给value,像这样的我们就可以简写成

<MyInput v-model="value"></MyInput>

而在组件上,一个组件上的 v-model 默认会利用名为 value 的 prop 和名为 input 的事件。

我觉得这句话很重要,以往没有仔细看文档这句话,就形成了一种定向思维,要在组件上使用v-model,组件里面必须含有input等这些表单元素才行,其实是大错特错

当我们要使用v-model的时候,只需要在组件中定义一个value的prop,当组件内部需要修改value的值时,自定义input事件传递给父组件,让父组件修改,这样就不违背单向数据流的思想了,因为数据一般都是响应式的嘛

下面举个五星评分组件的例子,就不写的那么完整了,星星用方块代替,点击方块进行评分,并且设置v-model绑定的值是当前评分(就是几颗星),类型是number

  • rate.vue
<template>
  <div>
    <!-- 
      五颗基本星星,循环5的话,那么item就是1,2,3,4,5
      通过比较当前item和传进来的value比较,如果当前item小于等于value,
      说明当前星星应该是黄色的,绑定一个on的类名,它的css就是背景色为黄色
     -->
    <span
      class="rate"
      v-for="(item, index) in 5"
      :key="index"
      :class="{ on: item <= value }"
    ></span>
  </div>
</template>

<script>
export default {
  props: {
    value: Number,
  },
};
</script>

<style scoped>
.rate {
  display: inline-block;
  width: 20px;
  height: 20px;
  margin: 0 10px;
  background-color: #666;
}

.on {
  background-color: yellow;
}
</style>
  • 使用组件
<template>
  <div>
    <!-- 通过v-model绑定初始评分是2颗星 -->
    <Rate v-model="rate"></Rate>
  </div>
</template>

<script>
import Rate from "../components/Rate.vue";
export default {
  components: {
    Rate,
  },
  data() {
    return {
      rate: 2,
    };
  },
};
</script>

效果,目前应该是两颗星是黄色


init.png

下面来写点击逻辑,其实就一行

    <span
      class="rate"
      ....
      @click="$emit('input', item)"
    ></span>

点击之后,定义一个input事件,参数就是item,父组件就会监听子组件的input事件,将你绑定的值(rate)变成input事件的参数(item),然后数据是响应式的,对应的之就会被修改(变成黄色的星星的数量对应发生变化)

大家也可以看对应的官网

vue3在组件上使用v-model

vue3在组件上的用法发生了变化

value -> modelValue
input -> update:modeVale

那么上面的例子中

<Rate v-model="rate"></Rate>

就等价于

<Rate :model-value="rate" @update:model-value="$event = rate"></Rate>

那么Rate.vue内部就该是

<span
  ...
  @click="$emit('update:modelValue', item)"
></span>
...
props: {
  modelValue: Number,
}
...

那么input那些表单元素的绑定本质就是

<input
  :value="modelValue"
  @input="$emit('update:modelValue', $event.target.value)"
>
  • 多值双向绑定
    一般来说v-model绑定的就是modelValue,如果你想绑定多个或者绑定其他属性,那就可以给v-model添加参数
v-model:(属性)="(为该属性绑定的值)"
// 当然这个属性应该是子组件的一个prop,且触发方法同v-model,
$emit('update:属性', (参数))

这个是可以和v-model同时存在的

- 子组件

<template>
  <div style="marign: 20px">
    <h1>子组件</h1>
    <div @click="$emit('update:modelValue', '修改了')">{{ modelValue }}</div>
    <div @click="$emit('update:message', 'message修改了')">
      {{ message }}
    </div>
  </div>
</template>

<script lang="ts">
import { defineComponent } from "vue";

export default defineComponent({
  emits: ["update:modelValue", "update:message"],
  props: {
    modelValue: String,
    message: String,
  },
  setup() {},
});
</script>

- 使用

<template>
  <div>
    <Children v-model="value" v-model:message="otherModel"></Children>

    <h1>父组件数据</h1>
    <div>{{ value }}</div>
    <div>{{ otherModel }}</div>
  </div>
</template>

<script lang="ts">
import { defineComponent, reactive, toRefs } from "vue";
import Children from "./components/Children.vue";

export default defineComponent({
  components: { Children },

  setup() {
    const state = reactive({
      value: "哈哈",
      otherModel: "message1",
    });
    return { ...toRefs(state) };
  },
});
</script>

效果就是,点击子组件的文字,两边的文字内容同时修改


Snipaste_2021-11-27_21-20-21.png

|
|


1.png

3.x官网链接:

相关文章

网友评论

      本文标题:vue(2/3)中在组件上使用v-model

      本文链接:https://www.haomeiwen.com/subject/bbnfxrtx.html