vue 自定义组件 v-model

官方的介绍讲得比较全,这里就省去复制粘贴的步骤了。此处模拟一种非表单元素的 v-model 组件:

类似复选框,在组件里点选不同的选项,然后能跟父组件双向绑定。

1. 首先做好基础的排版及样式

复制代码
<template>
  <div style="padding:10px">
    <span>1</span>
    <span>2</span>
    <span>3</span>
    <span>4</span>
  </div>
</template>

<style scoped>
  span{
    display: inline-block;
    width: 80px;
    height: 30px;
    line-height: 30px;
    border-radius: 4px;
    border: 1px solid #333;
    color: #333;
    text-align: center;
  }
  span.active{
    border-color: #f45619;
    color: #f45619;
  }
</style>
复制代码

2. 添加 model 属性

根据文档内容,v-model 需要两个属性:value、event,一个用来传值(父传子),一个用来接收并赋值(子传父)。

<input
  v-bind:value="searchText"
  v-on:input="searchText = $event.target.value"
>

我们定为 val、change 以示区分

复制代码
<script>

export default {
  model:{
    prop:'val',
    event:'change'
  },
  // val 这个值本身是不存在的,所以需要通过 props 定义
  props:{
    val: Array,
  },
  
};
</script>
复制代码

3. 接下来,我们把数据进一步处理,通过 computed 计算属性操作父组件传过来的值。val 为 0,1,2,3 中的值组成的数组,如:[ 1,3 ]。通过 computed 转换为 list : [ 0,1,0,1]

复制代码
<template>
  <div style="padding:10px">
    <span :class="{'active':list[0]}" >1</span>
    <span :class="{'active':list[1]}" >2</span>
    <span :class="{'active':list[2]}" >3</span>
    <span :class="{'active':list[3]}" >4</span>
  </div>
</template>

<script>

export default {
  model:{
    prop:'val',
    event:'change'
  },
  // val 这个值本身是不存在的,所以需要通过 props 定义
  props:{
    val: Array,
  },
  computed:{
    list(){
      let arr = []
      this.val.forEach(i=>{
        let n = parseInt(i)
        arr[n] = 1
      })
      return arr
    }
  },
};
</script>

<style scoped>
  span{
    display: inline-block;
    width: 80px;
    height: 30px;
    line-height: 30px;
    border-radius: 4px;
    border: 1px solid #333;
    color: #333;
    text-align: center;
  }
  span.active{
    border-color: #f45619;
    color: #f45619;
  }
</style>
复制代码

4. 到这里实现了单向的绑定,然后根据子组件的事件操作给父组件传值。通过子组件的点击事件触发父组件的事件提交,并把新值带给父组件

复制代码
<template>
  <div style="padding:10px">
    <span :class="{'active':list[0]}" @click="onTap(0)">1</span>
    <span :class="{'active':list[1]}" @click="onTap(1)">2</span>
    <span :class="{'active':list[2]}" @click="onTap(2)">3</span>
    <span :class="{'active':list[3]}" @click="onTap(3)">4</span>
  </div>
</template>

<script>

export default {
  model:{
    prop:'val',
    event:'change'
  },
  // val 这个值本身是不存在的,所以需要通过 props 定义
  props:{
    val: Array,
  },
  computed:{
    list(){
      let arr = []
      this.val.forEach(i=>{
        let n = parseInt(i)
        arr[n] = 1
      })
      return arr
    }
  },
  methods:{
    onTap(n){
      console.log(n)
      let list = this.list
      list[n] = !list[n]
      let res = []
      list.map((i, idx)=>{
        if(i) res.push(idx)
      })
      // 注意
      // 此处的 change ,来自一开始定义在 model 属性里的event
    // 父组件在接收到传过来的新值后,会用这个新值更新 val 属性,这样就会更新了自组件的值,完成双向绑定的过程
this.$emit('change',res)
}
}
};
</script>

<style scoped>
  span{
    display: inline-block;
    width: 80px;
    height: 30px;
    line-height: 30px;
    border-radius: 4px;
    border: 1px solid #333;
    color: #333;
    text-align: center;
  }
  span.active{
    border-color: #f45619;
    color: #f45619;
  }
</style>
复制代码

5. 父组件引用:

复制代码
// 父组件
<template>
  <div class="hello">
    <hello v-model="value"></hello>
  </div>
</template>

<script>
import hello from '@/components/model'
export default {
  components:{ hello },
  data () {
    return {
      value:[1,3],
    }
  },
}
</script>
复制代码

 

 

 

参考官方文档 :

在组件上使用 v-model 、 自定义组件的 v-model

posted @   晨の风  阅读(1458)  评论(0编辑  收藏  举报
编辑推荐:
· 对象命名为何需要避免'-er'和'-or'后缀
· SQL Server如何跟踪自动统计信息更新?
· AI与.NET技术实操系列:使用Catalyst进行自然语言处理
· 分享一个我遇到过的“量子力学”级别的BUG。
· Linux系列:如何调试 malloc 的底层源码
阅读排行:
· C# 中比较实用的关键字,基础高频面试题!
· .NET 10 Preview 2 增强了 Blazor 和.NET MAUI
· Ollama系列05:Ollama API 使用指南
· 为什么AI教师难以实现
· 如何让低于1B参数的小型语言模型实现 100% 的准确率
点击右上角即可分享
微信分享提示