001_自定义组件使用v-model

本文介绍了如何在Vue中创建并使用自定义组件,包括MyInput、MyRadio和MyCheckbox。通过v-model实现数据双向绑定,详细展示了组件内部的数据处理和事件监听,为前端开发提供了组件复用的示例。
摘要由CSDN通过智能技术生成

一、APP组件

<template>
  <div>
    <div>
      <h3>自定义MyInput组件</h3>
      <my-input v-model="mValue" />
      {{ mValue }}
    </div>
    <hr />

    <div>
      <h3>自定义MyRadio组件</h3>
      <my-radio v-model="sex" label="male" name="sex"></my-radio>
      <my-radio v-model="sex" label="female" name="sex"></my-radio>
      {{ sex }}
    </div>
    <hr />

    <div>
      <h3>自定义MyCheckbox组件</h3>
      <my-checkbox v-model="hobbies" label="yy" name="hobbies">游泳</my-checkbox>
      <my-checkbox v-model="hobbies" label="ts" name="hobbies">跳水</my-checkbox>
      <my-checkbox v-model="hobbies" label="dq" name="hobbies">打球</my-checkbox>
      {{ hobbies }}
    </div>
  </div>
</template>

<script>
import MyInput from "./MyInput.vue";
import MyRadio from "./MyRadio.vue";
import MyCheckbox from "./MyCheckbox.vue";
export default {
  name: "App",
  components: { MyInput, MyRadio, MyCheckbox },
  data() {
    return {
      mValue: 50,
      sex: "",
      hobbies: [],
    };
  },
};
</script>

二、MyInput组件

<template>
  <div>
    <label>输入内容</label>
    <!-- 第一种: -->
    <!-- 用vueComponent实例自带的$attrs来接收父组件传递过来的value属性 -->
    <!-- <input :value="$attrs.value" @input="handleInput"/> -->

    <!-- 第二种: -->
    <!-- <input :value="value" @input="handleInput"/> -->

    <!-- 第三种: -->
    <input :value="mValue" @input="handleInput" />
  </div>
</template>

<script>
export default {
  name: "MyInput",
  //第二种:
  //属性值用'value'字符串接收得时候
  //可以不使用model这个配置项,因为父组件一旦给子组件使用了v-model,
  //那么相应的子组件的$listener属性上面就会含有input方法,而且也会向
  //对应子组件传递名为'value'字符串的属性
  // props:['value'],
  // 此处可以不使用用model,因为父组件一旦给子组件使用了v-model,
  // 那么响应的子组件的$listener属性上面就会含有input方法
  // model:{
  //   prop:'value',
  //   event:'input'
  // },


  //第三种情况:props必须和model配合使用。model的prop属性和props中的"mValue"形成映射,将
  //父控件中传入的value属性修改为"mValue"
  props: ["mValue"],
  model: {
    prop: "mValue",
    //因为子组件的$listener属性上面就会含有input方法, 下面的event:'input'属性可以不写
    event: "input",
  },

  data() {
    console.log("MyInput", this);
    return {};
  },
  methods: {
    handleInput(event) {
      this.$emit("input", event.target.value);
    },
  },
};
</script>
<style>
</style>
2.1 第一种
2.2 第二种
2.3 第三种(标准的使用方式)

三、MyRadio组件

<!--  -->
<template>
  <div>
    <input
      type="radio"
      :checked="checked"
      @change="handleChange"
      :value="label"
      :name="name"
    />
    <slot />
  </div>
</template>

<script>
export default {
  name: "MyRadio",
  props: ["sex", "label", "name"],
  //此处没有model,那么props中的mRadio是无法获取属性值得
  model: {
    prop: "sex",
    //A 如果event的值是change的话,$listener就只会有一个change函数,否则会包含change和input函数
    event: "change",
  },
  computed: {
    checked() {
      return this.sex === this.label;
    },
  },
  data(){
    console.log('MyRadio',this);
    return{}
  },
  methods: {
    handleChange(event) {
      //当sex有值之后,再次点击时就不要一直触发事件了
      if (!this.sex||this.sex!==this.label) {
        console.log("event", event, event.target.checked, this.label);
        //B A与B处的事件名称必须保持一致,否则无法生效
        this.$emit("change", event.target.checked ? this.label : "");
      }
    },
  },
};
</script>
<style>
</style>


四、MyCheckbox组件

<!-- MyCheckbox需要借助外层再次包裹,否则无法获取数组。参考element-ui实现 -->
<template>
  <div>
    <input
      type="checkbox"
      :checked="checked"
      @change="handleChange"
      :value="label"
      :name="name"
    />
    <slot />
  </div>
</template>

<script>
export default {
  name: "MyCheckbox",
  props: ["hobbies", "label", "name"],
  //此处没有model,那么props中的mRadio是无法获取属性值得
  //model起到一个映射的作用,把组件中$attr的value属性值给映射成所需要的属性
  model: {
    prop: "hobbies",
    event: "change",
  },
  data() {
    console.log("MyCheckbox", this);
    return {};
  },
  computed: {
    checked() {
      return this.hobbies.includes(this.label);
    },
  },
  methods: {
    handleChange(event) {
      console.log("event", event);
      //当前是否选中
      const checked = event.target.checked;
      let tempHobbies = [...this.hobbies];
      //查找当前标签在hobbies的位置
      let currentIndex = tempHobbies.indexOf(this.label);
      //选中并且之前未添加
      if (checked && currentIndex == -1) {
        tempHobbies.push(this.label);
      //没选中并且之前已添加
      } else if (!checked && currentIndex != -1) {
        tempHobbies.splice(currentIndex, 1);
      }
      //B A与B处的事件名称必须保持一致,否则无法生效
      this.$emit("change", tempHobbies);
    },
  },
};
</script>
<style>
</style>

五、效果图

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值