vue 使用 v-model 双向绑定父子组件的值遇见的问题及解决方案


Posted in Vue.js onMarch 01, 2021

场景

今天在使用 v-model 进行组件双向数据绑定的时候遇到了一个奇怪的问题,网页本身运行正常,浏览器一直出现警告信息。

[Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "value"

引发这个警告的是一个自定义组件 RxSelect

Vue.component("RxSelect", {
 model: {
 prop: "value",
 event: "change",
 },
 props: {
 value: [Number, String],
 map: Map,
 },
 template: `
  <select
   v-model="value"
   @change="$emit('change', value)"
  >
   <option
   v-for="[k,v] in map"
   :value="k"
   :key="k"
   >{{v}}</option>
  </select>
  `,
});

吾辈使用的代码看起来代码貌似没什么问题?

<main id="app">
 当前选择的性别是: {{map.get(sex)}}
 <div>
 <rx-select :map="map" v-model="sex" />
 </div>
</main>

JavaScript 代码

new Vue({
 el: "#app",
 data: {
 map: new Map().set(1, "保密").set(2, "男").set(3, "女"),
 sex: "",
 },
});

经测试,程序本身运行正常,父子组件的传值也没什么问题,双向数据绑定确实生效了,然而浏览器就是一直报错。

尝试解决

吾辈找到一种方式

  1. 为需要双向绑定的变量在组件内部 data 声明一个变量 innerValue,并初始化为 value
  2. select 上使用 v-model绑定这个变量 innerValue
  3. 监听 value 的变化,在父组件中 value 变化时修改 innerValue 的值
  4. 监听 innerValue 的变化,在变化时使用 this.$emit('change', val) 告诉父组件需要更新 value 的值
Vue.component("RxSelect", {
 model: {
 prop: "value",
 event: "change",
 },
 props: {
 value: [Number, String],
 map: Map,
 },
 data() {
 return {
  innerValue: this.value,
 };
 },
 watch: {
 value(val) {
  this.innerValue = val;
 },
 innerValue(val) {
  this.$emit("change", val);
 },
 },
 template: `
 <select v-model="innerValue">
 <option
  v-for="[k,v] in map"
  :value="k"
  :key="k"
 >{{v}}</option>
 </select>
 `,
});

使用代码完全一样,然而组件 RxSelect 的代码却多了许多。。。

解决

一种更优雅的方式是使用 computed 计算属性以及其的 get/set,代码增加的程度还是可以接受的

Vue.component("RxSelect", {
 model: {
 prop: "value",
 event: "change",
 },
 props: {
 value: [Number, String],
 map: Map,
 },
 computed: {
 innerValue: {
  get() {
  return this.value;
  },
  set(val) {
  this.$emit("change", val);
  },
 },
 },
 template: `
 <select v-model="innerValue">
 <option
  v-for="[k,v] in map"
  :value="k"
  :key="k"
 >{{v}}</option>
 </select>
 `,
});

以上就是vue 使用 v-model 双向绑定父子组件的值遇见的问题及解决方案的详细内容,更多关于vue 使用 v-model 双向绑定父子组件的值的资料请关注三水点靠木其它相关文章!

Vue.js 相关文章推荐
Vue router传递参数并解决刷新页面参数丢失问题
Dec 02 Vue.js
Vue如何实现验证码输入交互
Dec 07 Vue.js
基于Vue3.0开发轻量级手机端弹框组件V3Popup的场景分析
Dec 30 Vue.js
详解Vue2的diff算法
Jan 06 Vue.js
Vue包大小优化的实现(从1.72M到94K)
Feb 18 Vue.js
vue+flask实现视频合成功能(拖拽上传)
Mar 04 Vue.js
详解Vue中$props、$attrs和$listeners的使用方法
Feb 18 Vue.js
浅谈Vue的computed计算属性
Mar 21 Vue.js
vue实现可以快进后退的跑马灯组件
Apr 08 Vue.js
解决vue中provide inject的响应式监听
Apr 19 Vue.js
Vue操作Storage本地化存储
Apr 29 Vue.js
vue使用watch监听属性变化
Apr 30 Vue.js
vue前端和Django后端如何查询一定时间段内的数据
Feb 28 #Vue.js
vue-router路由懒加载及实现的3种方式
Feb 28 #Vue.js
vue-router懒加载的3种方式汇总
Feb 28 #Vue.js
Vue SPA 首屏优化方案
Feb 26 #Vue.js
vue 动态添加的路由页面刷新时失效的原因及解决方案
Feb 26 #Vue.js
vue项目配置 webpack-obfuscator 进行代码加密混淆的实现
Feb 26 #Vue.js
vue中h5端打开app(判断是安卓还是苹果)
Feb 26 #Vue.js
You might like
php 购物车实例(申精)
2009/05/11 PHP
php的ZipArchive类用法实例
2014/10/20 PHP
thinkphp框架下实现登录、注册、找回密码功能
2016/04/06 PHP
php 多进程编程父进程的阻塞与非阻塞实例分析
2020/02/22 PHP
jQuery textarea的长度进行验证
2009/05/06 Javascript
跨域请求之jQuery的ajax jsonp的使用解惑
2011/10/09 Javascript
关于JS判断图片是否加载完成且获取图片宽度的方法
2013/04/09 Javascript
js实现瀑布流的一种简单方法实例分享
2013/11/04 Javascript
javascript求日期差的方法
2016/03/02 Javascript
Javascript 正则表达式校验数字的简单实例
2016/11/02 Javascript
bootstrap css样式之表单
2017/01/19 Javascript
Webpack性能优化 DLL 用法详解
2017/08/10 Javascript
详解如何在react中搭建d3力导向图
2018/01/12 Javascript
vue与原生app的对接交互的方法(混合开发)
2018/11/28 Javascript
vue中通过使用$attrs实现组件之间的数据传递功能
2019/09/01 Javascript
Vue 自定义标签的src属性不能使用相对路径的解决
2019/09/17 Javascript
Javascript新手入门之字符串拼接与变量的应用
2020/12/03 Javascript
Python程序员鲜为人知但你应该知道的17个问题
2014/06/04 Python
详解Python如何获取列表(List)的中位数
2016/08/12 Python
Python二叉树的定义及常用遍历算法分析
2017/11/24 Python
利用python将图片版PDF转文字版PDF
2019/05/03 Python
python语言基本语句用法总结
2019/06/11 Python
Python使用matplotlib绘制三维参数曲线操作示例
2019/09/10 Python
keras CNN卷积核可视化,热度图教程
2020/06/22 Python
如何通过安装HomeBrew来安装Python3
2020/12/23 Python
英国户外装备和冒险服装零售商:alloutdoor
2018/01/30 全球购物
美国女士时尚珠宝及配饰购物网站:Icing
2018/07/02 全球购物
标记环介质访问控制协议
2016/03/27 面试题
大唐面试试题(CPU,UNIX等等)
2012/01/11 面试题
写求职信有哪些注意事项
2014/05/08 职场文书
物理学专业求职信
2014/07/04 职场文书
七一建党节演讲稿
2014/09/11 职场文书
2014年班组建设工作总结
2014/12/01 职场文书
药品销售员2015年终工作总结
2015/10/22 职场文书
人生感悟经典句子
2019/08/20 职场文书
使用springMVC所需要的pom配置
2021/09/15 Java/Android