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 $attrs &amp; inheritAttr实现button禁用效果案例
Dec 07 Vue.js
Vue与React的区别和优势对比
Dec 18 Vue.js
Vue+penlayers实现多边形绘制及展示
Dec 24 Vue.js
基于Vue3.0开发轻量级手机端弹框组件V3Popup的场景分析
Dec 30 Vue.js
深入了解Vue动态组件和异步组件
Jan 26 Vue.js
Vue详细的入门笔记
May 10 Vue.js
详解vue中v-for的key唯一性
May 15 Vue.js
vue点击弹窗自动触发点击事件的解决办法(模拟场景)
May 25 Vue.js
VUE之图片Base64编码使用ElementUI组件上传
Apr 09 Vue.js
vue route新窗口跳转页面并且携带与接收参数
Apr 10 Vue.js
vue本地构建热更新卡顿的问题“75 advanced module optimization”完美解决方案
Aug 05 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生成缩略图的函数代码(修改版)
2011/01/18 PHP
php导出csv数据在浏览器中输出提供下载或保存到文件的示例
2014/04/24 PHP
Ajax和PHP正则表达式验证表单及验证码
2016/09/24 PHP
php array_map使用自定义的函数处理数组中的每个值
2016/10/26 PHP
php处理静态页面:页面设置缓存时间实例
2017/06/22 PHP
Mootools 1.2教程 输入过滤第二部分(字符串)
2009/09/15 Javascript
Js Jquery创建一个弹出层可加载一个页面
2014/05/08 Javascript
JavaScript通过prototype给对象定义属性用法实例
2015/03/23 Javascript
原生javascript实现匀速运动动画效果
2016/02/26 Javascript
jQuery解决IE6、7、8不能使用 JSON.stringify 函数的问题
2016/05/31 Javascript
JS采用绝对定位实现回到顶部效果完整实例
2016/06/20 Javascript
JS JSOP跨域请求实例详解
2016/07/04 Javascript
微信小程序 实现拖拽事件监听实例详解
2016/11/16 Javascript
Base64(二进制)图片编码解析及在各种浏览器的兼容性处理
2017/02/09 Javascript
Angularjs分页查询的实现
2017/02/24 Javascript
javascript数组定义的几种方法
2017/10/06 Javascript
javaScript手机号码校验工具类PhoneUtils详解
2017/12/08 Javascript
vsCode安装使用教程和插件安装方法
2020/08/24 Javascript
Vue组件通信$attrs、$listeners实现原理解析
2020/09/03 Javascript
如何在vue中使用video.js播放m3u8格式的视频
2021/02/01 Vue.js
Windows下Python的Django框架环境部署及应用编写入门
2016/03/10 Python
Python卸载模块的方法汇总
2016/06/07 Python
selenium+python实现自动登录脚本
2018/04/22 Python
Python模块_PyLibTiff读取tif文件的实例
2020/01/13 Python
git查看、创建、删除、本地、远程分支方法详解
2020/02/18 Python
基于HTML5新特性Mutation Observer实现编辑器的撤销和回退操作
2016/01/11 HTML / CSS
iphoneX 适配客户端H5页面的方法教程
2017/12/08 HTML / CSS
公司保密承诺书
2014/03/27 职场文书
交通工程专业推荐信
2014/09/06 职场文书
2014年社区综治工作总结
2014/11/17 职场文书
2014年电厂个人工作总结
2014/11/27 职场文书
2014年服务员个人工作总结
2014/12/23 职场文书
骆驼祥子读书笔记
2015/06/26 职场文书
公司员工培训管理制度
2015/08/04 职场文书
假期读书倡议书3篇
2019/08/19 职场文书
USB TYPE-C 或将成为所有智能手机充电标准
2022/04/21 数码科技