首页 > 其他分享 >vue 2 实现自定义组件一到多个v-model双向数据绑定的方法(转)

vue 2 实现自定义组件一到多个v-model双向数据绑定的方法(转)

时间:2024-07-25 09:56:07浏览次数:8  
标签:vue return 自定义 绑定 value export 组件 model

原文链接:https://blog.csdn.net/Dobility/article/details/110147985

前言
有时候我们需要对一个组件绑定自定义 v-model,以更方便地实现双向数据,例如自定义表单输入控件。

甚至有时候,我们想要实现绑定多个 “v-model”,也就是多个“双向绑定”,例如带表单输入的模块框,想同时控制模态框的显示状态与表单的输入状态。好在 vue 3 已经实现了多 v-model,那么在 vue 2 上我们可以如下实现。

1.单个“双向绑定”的实现
使用 model 实现

其实 v-model 只是 value + change 的语法糖,监听输入并触发改变,因此只要实现 “监听” + “触发” 就可以自定义 v-model 啦。

复制代码
<!-- 父组件 -->
<template>
    <Child v-model="value" />
</template>
<script>
export default {
  data() {
    return {
      value: ''
    }
  }
}
</script>

<!-- 子组件 -->
<template>
    <input v-model="input" />
</template>
<script>
export default {
  props: {
    value: String,
  },
  model: {
    prop: 'value',        // 指定 v-model 要绑定的参数叫什么名字,来自于 props 中定义的参数
    event: 'change',    // 指定要触发的事件名字,将被用于 $emit
  },
  computed: {
    input: {
      // 这里的计算属性使用了 getter、setter,可以简化代码
      // 可参见链接 https://cn.vuejs.org/v2/guide/computed.html#%E8%AE%A1%E7%AE%97%E5%B1%9E%E6%80%A7%E7%9A%84-setter
      get() {
        return this.value;
      },
      set(val) {
        this.$emit('change', val);    // 触发
      }
    }
  }
}
</script>
复制代码

这样一来,就实现了自定义组件的 v-model 实现,重点在于子组件中 model 的声明和 emit 事件。

2.使用 .sync 实现

除了上面 model 的方法,其实还可以通过 sync 来实现。同样也是处理“监听”和“触发”就行。

在官方文档中有写,https://cn.vuejs.org/v2/guide/components-custom-events.html#sync-修饰符

用上面相似的例子,可以这样来实现:

复制代码
<!-- 父组件 -->
<template>
    <Child :value.sync="value" />
</template>
<script>
export default {
  data() {
    return {
      value: ''
    }
  }
}
</script>

<!-- 子组件 Child -->
<template>
    <input v-model="input" />
</template>
<script>
export default {
  props: {
    value: String,
  },
  computed: {
    input: {
      get() {
        return this.value;
      },
      set(val) {
        this.$emit('update:value', val);    // 这里的事件名字一定是 'update:' + prop的名字
      }
    }
  }
}
</script>
复制代码

很显然,使用这种方法的代码量比第1种要少,因为不用写 model 属性。只是比起 v-model,v-bind:value.sync 的写法还是不那么“引人注目”

多个“双向绑定”的实现
在 vue 3 出来之前,我们知道在一个标签里面最多只能有一个 v-model。但这并不意味着一个组件只能一次双向数据绑定。

根据上面 .sync 的方法,我们可以举一反三,多几个 update:xxxx 就可以了。

1.分开绑定

下面以一个带输入框的模态框为例子,需求是父组件能够打开模态框,子组件在输入确认后能够关闭模态框;子组件能够输入,确认后能够将值传给父组件。

复制代码
<!-- 父组件 -->
<template>
  <!-- 定义了两个v-bind:xxx.sync来实现两个双向绑定 -->
  <ModalInput :value.sync="value" :show.sync="show" />
</template>
<script>
export default {
  data() {
    return {
      value: '',
      show: false
    }
  }
}
</script>

<!-- 子组件 ModalInput -->
<template>
  <!-- 这里假设Modal是一个带“确认”按钮,点击触发confirm事件,并利用v-model来控制展示的模态框 -->
  <Modal v-model="showModal" @confirm="onConfirm">
    <input v-model="input">
  </Modal>
</template>
<script>
export default {
  props: {
    value: String,
    show: Boolean,
  },
  data() {
    return {
      input: ''        // 在这个例子中,使用 data 来声明 input,
                  // 因为只有在点击了“确认”按钮后,才要把值传给父组件(而不是实时传)
    }
  },
  computed: {
    showModal: {
      get() {
        return this.show;
      },
      set(val) {
        this.$emit('update:show', val);
      }
    }
  },
  methods: {
    onConfirm() {
      this.$emit('update:value', this.input);
      this.showModal = false
    }
  }
}
</script>
复制代码

2.合并绑定

上面是绑定了两个独立变量的双向绑定,按照官方的文档,我们甚至还可以用 v-bind.sync 来绑定整个对象(的所有成员!)。下面假设一个表单组件,同时收集个人多个信息

复制代码
<!-- 父组件 -->
<template>
  <UserInfoForm v-bind.sync="inputs" />
</template>
<script>
export default {
  data() {
    return {
      inputs: {
        name: '',
        age: 0,
        addr: '',
        phone: ''
      }
    }
  }
}
</script>

<!-- 子组件 UserInfoForm -->
<template>
  <form>
    <input v-model="name">
    <input v-model.number="age">
    <input v-model="addr">
    <input v-model="phone">
  </form>
</template>
<script>
// 与上面例子实现方式相似,这里省略代码若干行。。。
// 其实就是声明入参 props 有哪些
// 用 computed 来声明各个变量的 getter 和 setter
// getter 返回传进来的 prop,setter 中触发 update:xxxx 事件
</script>

标签:vue,return,自定义,绑定,value,export,组件,model
From: https://www.cnblogs.com/xuxuguaiguai/p/18322383

相关文章

  • 涨见识了!脱离vue项目竟然也可以使用响应式API
    前言vue3的响应式API大家应该都特别熟悉,比如ref、watch、watchEffect等。平时大家都是在vue-cli或者vite创建的vue项目里面使用的这些响应式API,今天欧阳给大家带来一些不一样的。脱离vue项目,在node.js项目中使用vue的响应式API。关注公众号:【前端欧阳】,给自己一个进阶vue的机会......
  • vue大小写总结
    1.组件组件的定义有两种命名方式:PascalCase  和   kebab-casePascalCase 定义的组件的引用:PascalCase  和   kebab-case  均可//PascalCase定义方式Vue.component('MyComponentName',{/*...*/})//引用方式一<my-component-name/>//引用方......
  • Vue Router【实用教程】(2024最新版)vue3 路由管理
    VueRouter是Vue官方的客户端路由解决方案,在单页应用(SPA)中,用户在应用中浏览不同页面时,URL会随之更新,但页面不需要从服务器重新加载。核心思想:通过配置路由来告诉VueRouter为每个URL路径显示哪些组件。官网https://router.vuejs.org/zh/guide/安装通常......
  • Flask-WTF:如何在 Flask FormField 中定义自定义变量
    我正在尝试在Flask中设置一个动态表单,其中该表单具有动态填充的FormFieldsFieldList。虽然大部分都有效,但我不断遇到每个FormField的变量问题。我需要每个FormField有一个标签,它是FormField的名称(并在页面上呈现)和一个在显示/隐藏脚本中使用的自定义ID,该脚本使用动态......
  • Enhancing Diffusion Models with Reinforcement Learning
    EnhancingDiffusionModelswithReinforcementLearningSep27,2023 | UncategorizedTL;DRTodaywe'regoingtotellyouallabout DRLX -ourlibraryforDiffusionReinforcementLearning!Releasedafewweeksago,DRLXisalibraryforscalabledist......
  • 计算机专业论文 (SpringBoot/SpringCloud+Vue+MySql)
    (可辅导论文)需要源码dd毕业设计(论文)  论文题目:基于Vue和SpringCloud的旅游网站设计与实现 摘 要 本论文主要介绍了基于Vue和SpringCloud的旅游网站的设计与实现。如今,旅游业已成为社会发展中的重要组成部分,旅游平台聚集多种多样的旅行方案以及攻略,越来越多的人......
  • Vue全家桶 - pinia 的理解和学习1(Pinia 核心概念的 Store、State、Getter、Action)
    Pinia(Vue的专属状态管理库)Pinia和Vuex的区别设计理念和架构Vuex采用集中式架构,所有状态存储在一个全局状态树中,通过mutations和actions来修改和处理状态。Pinia采用去中心化的架构,每个模块有自己的状态,这使得Pinia在代码分割和模块化方面更加灵活。TypeSc......
  • 一文弄清楚自定义流程表单开发的多个优势特征
    随着行业竞争的激烈化,很多企业都希望实现降本、提质、增效的发展目的。什么样的软件平台可以帮助企业实现这一目标?低代码技术平台、自定义流程表单开发拥有可视化界面、易操作、更灵活等优势特点,在助力降本增效的过程中事半功倍,深得客户喜爱。要了解它的重要性,可以先学习它的定义......
  • 学习vue第一天
    文章目录1.什么是Vue?2.渐进式框架3.如何新建一个vue项目1.什么是Vue?Vue(发音为/vjuː/,类似 view)是一款用于构建用户界面的JavaScript框架。它基于标准HTML、CSS和JavaScript构建,并提供了一套声明式的、组件化的编程模型,帮助你高效地开发用户界面。无......
  • 修改el-popover样式不生效问题,vue中element-ui样式修改不生效问题
    修改el-popover样式不生效问题在最近公司写的项目中,使用到了el-popover,但是想要修改弹出层中文本的字体样式,尝试过很多方法之后,发现修改的样式都没有生效,查阅资料发现:el-popover比较特殊,他生成的div不在当前组件之内,甚至不在App.vue组件的div内,他和App.vue组件的div平级,需要设置......