-
vue 父子组件传值 子组件修改父组件值的解决办法
2019-11-08 09:01:59vue中父组件向子组件传值时,其父子prop之间形成单向下行绑定,反过来则不行,这样会防止子组件意外改变父组件的值,从而数据流变的难以理解;另外,每次父组件的数据发生更新时,子组件的都会刷新到最新的数据,但...最近在前端项目中遇到了父子组件传值的问题...
vue中父组件向子组件传值时,其父子prop之间形成单向下行绑定,反过来则不行,这样会防止子组件意外改变父组件的值,从而数据流变的难以理解;另外,每次父组件的数据发生更新时,子组件的都会刷新到最新的数据,但不能改变子组件内部改变prop,这样浏览器就会发出警告
解决办法来啦
解决办法一、子组件想要修改时,需要通过$emit派发一个自定义事件,父组件收到后,由父组件进行修改
子组件在computed中,
computed:{ currentActiveNames: { get() { return this.activeNames //父组件传给子组件的值 }, set(val) { // 改变由父组件控制 this.$emit('on-change-activeNames', val) } } }
这样子组件告诉父组件自己修改了父组件传过来的值
接下来呢,父组件中在引用子组件的地方添加@on-change-activeNames="changeActiveNames",另外,在methods方法中定义changeActiveNames用来接收父组件传过来的值
methods:{ changeActiveNames(val){ console.log(‘子组件传过来的值’,val) } }
解决办法二、
注意在 JavaScript 中对象和数组是引用类型,指向同一个内存空间,如果 prop 是一个对象或数组,在子组件内部改变它会影响父组件的状态。
大概意思就是:只要prop是对象或者数组,在子组件里面就可以修改从而改变父组件的值
那具体要怎么写呢...
1. 父组件中引入子组件 <child :par-obj="parObj"><child/> child为子组件的名称(这里提一下 子组件名若为驼峰式,父组件引用的时候用‘-’连接 例如子组件名称为 childCom 引用时则用child-com)
2. parObj为传给子组件的对象,在data中定义 重点来啦....在data中可以这样定义
parObj:{ parVal: 1 },
这样palVal才是你需要真正传给子组件的值
3. 在子组件中
props: { parObj: { type: Object, default: null } },
拿到parObj后,子组件就可以肆意的改变parObj对象中的parVal啦
-
vue 子组件给父组件传值_vue组件引用传值的最佳实践
2020-12-12 03:31:49下述组件传值指引用类型(数组或对象)传值。准备:单向数据流所有的 prop 都使得...额外的,每次父级组件发生变更时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你不应该在一个子组件内部改变 prop。如果...下述组件传值指引用类型(数组或对象)传值。
准备:单向数据流
所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外变更父级组件的状态,从而导致你的应用的数据流向难以理解。
额外的,每次父级组件发生变更时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你不应该在一个子组件内部改变 prop。如果你这样做了,Vue 会在浏览器的控制台中发出警告。
- 这个 prop 用来传递一个初始值;这个子组件接下来希望将其作为一个本地的 prop 数据来使用。 定义一个本地的 data property 并将这个 prop 用作其初始值
props: ['initialCounter'], data: function () { return { counter: this.initialCounter } }
- 这个 prop 以一种原始的值传入且需要进行转换。 使用这个 prop 的值来定义一个计算属性
props: ['size'], computed: { normalizedSize: function () { return this.size.trim().toLowerCase() } }
注意在 JavaScript 中对象和数组是通过引用传入的,所以对于一个数组或对象类型的 prop 来说,在子组件中改变变更这个对象或数组本身将会影响到父组件的状态。
问题
父子组件间,通过引用类型传值,为什么控制台不会告警(基本类型会告警)?
Object.assign()
或者JSON.parse(JSON.stringify())
是在子组件中传引用值的标准处理方法吗?问题1
父组件 App.vue
<template> <div id="app"> <child :initialValue="valueEmit"> </child> </div> </template> <script> import childEmit from './components/child.vue' export default { data () { return { valueEmit: {dog: 1, cat: 2} } }, components: { child } } </script>
子组件 components/child.vue
<template> <div class="child-container"> <p> <label for="cat">猫 :</label> <input id="cat" type="text" v-model="value.cat" /> </p> <p> <label for="dog">狗 :</label> <input id="dog" type="text" v-model="value.dog" /> </p> </div> </template> <script> export default { name: 'child', props: { initialValue: Object }, data () { return { value = Object.assing({}, this.initialValue) } } } </script>
子组件内的修改,父组件也会直接变更,且不告警!
问题2
修改子组件,子组件 components/child.vue
export default { name: 'child', props: { initialValue: Object }, data () { return { valueEmit: Object.assign({}, this.initialValue) } } }
切断了引用,但是父组件变化不会触发子组件响应!(computed or watch 可以实现)
问题3
父组件 App.vue
<template> <div id="app"> <child :initialValue="valueEmit" @update-value-by-child="updateParentValue"> </child> </div> </template> <script> import childEmit from './components/child.vue' export default { data () { return { valueEmit: {dog: 1, cat: 2} } }, components: { child }, methods: { updateParentValue(newValue) { this.valueEmit = newValue } } } </script>
子组件 components/child.vue
<template> <div class="child-container"> <p> <label for="cat">猫 :</label> <input id="cat" type="text" v-model="valueEmit.cat" @input="$emit('update-value-by-child', valueEmit)" /> </p> <p> <label for="dog">狗 :</label> <input id="dog" type="text" v-model="valueEmit.dog" /> </p> </div> </template> <script> export default { name: 'child', props: { initialValue: Object }, data() { return { valueEmit: Object.assign({}, this.initialValue) } } } </script>
现象:
- 首先对“dog”进行修改,父组件的 initialValue 并未发生改变
- 对“cat”进行修改,父组件的 initialValue 发生变化(dog、cat都被修改了)
- 此时,在对“dog”修改,父组件的 initialValue 发生变化!
总结
- 纯展示 直接使用父组件属性,不会有副作用!
<template> <div> {{parentObj.value}} </div> </template> <script> export default { name: 'child', props: { parentObj: Object } } </script>
2. 只子组件内部修改,父组件不会修改(即,父组件只做初始化)
子组件 data 中声明新的数据,通过Object.assign()
或者JSON.parse(JSON.stringify())
切断引用即可。<template> <div> <input type="text" v-model="childObj.value"> </div> </template> <script> export default { name: 'child', props: { parentObj: Object }, data () { return { childObj: Object.assign({}, this.parentObj) } } } </script>
3. 父子组件都会修改 通过 computed 或者 watch 进行处理
<template> <div> <input type="text" v-model="childObj.value"> </div> </template> <script> export default { name: 'child', props: { parentObj: Object }, computed: { childObj () { return Object.assign({}, this.parentObj) } } } </script>
或者 watch 方式
export default { name: 'child', props: { parentObj: Object }, data () { return { childObj: {} } }, watch: { parentObj: { handler (val, oldVal) { if (val) { this.childObj = Object.assign({}, this.parentObj) } }, deep: true, immediate: true } } }
关于 watch 和 computed 区别: https://ligang.blog.csdn.net/article/details/94590314
欢迎关注 「 Super 前端 」微信公众号
版权声明: 本文原创自我的博客:李刚的学习专栏
-
props验证与默认值,Vue的双向数据绑定,Vue组件父传子,子传父,兄弟通信
2021-01-22 20:35:03每次父级组件发生更新时,子组件中所有的props都将会刷新为最新的值。 不能在子组件内部改变props,否则会导致浏览器控制台发出警告 子组件要修改时,用$emit调用自定义事件,父组件接到后由父组件修改 改变props的...1. props验证与默认值
父props与子props是单向下行绑定:父级的props的值更新会流动到子组件中,但反过来却不行。
避免子组件意外改变父级组件的状态,导致数据流混乱。
每次父级组件发生更新时,子组件中所有的props都将会刷新为最新的值。
不能在子组件内部改变props,否则会导致浏览器控制台发出警告
子组件要修改时,用$emit调用自定义事件,父组件接到后由父组件修改
改变props的常用例子:-
这个用来传递一个初始值;这个组件接下来希望将其作为一个本地的数据来使用,要定义一个本地属性用做初始值、
props:['initialCounter'], data:function(){ return{ counter:this.initialCounter } }
-
这个以一种原始的值传入且需要进行转换,定义一个计算属性
props:['size'], computed:{ normalizedSize:function(){ return this.size.trim().toLowerCase() } }
2. Vue的双向数据绑定
- 定义数据监听器Observer,能够对数据对象所有属性进行监听,数据有变动会获取新值并通知订阅者;
- 定义一个指令解析器Compile,对每个元素节点指令进行扫描,根据指令模板替换数据,以及绑定相应的更新函数;
- 实现一个Watcher,作为连接Observer和Compile的桥梁,能够订阅并收到每个属性变动的通知,执行指令绑定的相应回调函数,从而更新视图;
Vue实现双向数据绑定主要采用:数据劫持结合“发布-订阅”模式的方式,通过Object.defineproperty()的set和get,在数据变动是发布消息给订阅者触发监听。
Vue组件父传子,子传父,兄弟通信
1. 父传子:(通过props实现)
-
在父组件中给子组件标签绑定一个属性,属性上挂载需要传递的值;
-
在子组件通过props[“自定义属性名”]来接受数据;
以下是三种方法,没用vue写,引入vue.js文件,以下是HTML代码:
<body> <div id="app"> <child></child> </div> <script src="./vue.js"></script>//引入vue.js文件 <script> const child = { // props: ['msg'], // 第一种方法 inject: ['name', 'age', 'tel'], template: ` <div> 这是子组件 {{msg}} {{name}} -- {{age}} -- {{tel}} </div> `, data() { return { msg: '' } }, created() { // console.log(this.$parent.msg) // 第二种方法 不建议过多的使用 // this.msg = this.$parent.msg console.log(this.name, this.age, this.tel) } } Vue.component('child', child) new Vue({ provide: { // 第三种方法 开发高阶组件时建议使用 name: "张三", age: 16, tel: 110 }, data:{ msg: '这是要传递给子组件的数据' } }).$mount('#app') </script> </body>
2. 子传父:(通过$emit实现)
-
在父组件中给子组件标签绑定一个自定义事件,给这个事件挂载需要调用的方法;
-
在子组件的方法通过this.$emit(“自定义事件名”)来调用这个方法;
以下是HTML代码:
<body> <div id="app"> <child @senddata="getData"></child> </div> <script src="./vue.js"></script> <script> const child = { template: ` <div> 这是子组件 <button @click="sendData">点击传递数据给父组件</button> </div> `, data() { return { msg: '这是要传递给父组件的数据' } }, methods: { sendData() { this.$emit('senddata', this.msg) } } } Vue.component('child', child) new Vue({ data:{ msg: '' }, mounted() { console.log(this.$children[0].msg) }, methods: { getData(data) { console.log(data) } } }).$mount('#app') </script> </body>
3. 兄弟传参:两种方法
- 通过event bus实现
创建一个空的vue实例eventBUS,作为公共的桥梁;在两个组件中引入创建的bus,组件A用BUS.$ emit(“自定义事件名”,要传递的值)发送数据;组件B用BUS.$on(“自定义事件名”,function(v){挂载从A穿过来的数据})来接受数据
以下是HTML代码:
<body> <div id="app"> <child1></child1> <child2></child2> </div> <script src="./vue.js"></script> <script> const child1 = { template: ` <div> 这是子组件 <button @click="send">点击传递数据给父组件</button> </div> `, data() { return { msg: "这是要传递给父组件的数据", }; }, methods: { send() { this.$bus.$emit("getdata", this.msg); }, }, }; const child2 = { template: ` <div> 这是子组件 {{msg}} </div> `, created() { // console.log(this) // var _this = this this.$bus.$on("getdata", (data) => { // console.log(this) this.msg = data; }); }, data() { return { msg: "", }; }, }; Vue.component("child1", child1); Vue.component("child2", child2); var bus = new Vue(); Vue.prototype.$bus = bus; new Vue({ methods: {}, }).$mount("#app"); </script> </body>
2. 使用vuex来传递
vuex是一个状态管理工具,主要解决中大型复杂项目的数据共享数据
-
State-存放Vuex store实例的状态对象,用于定义共享的数据。
-
Action-动作,向store发出调用通知,执行异步操作。
-
Mutations-修改器,它只用于修改state中定义的状态变量。
-
getter-读取器,外部程序通过它获取变量的具体值,或者在取值前做一些计算(可以认为是store的计算属性)
-
modules对state进行分类处理
流程:dispatch到actions,actions是异步操作,从commit到mutations
使用mutations再通过逻辑操作改变state,同步到组件,更新其数据状态。
-
-
vue-element-ui子组件使用update修改从父组件传过来的变量同时响应更新
2020-12-22 16:01:10子组件修改从父组件传过来的值同时响应更新 我们都知道子组件直接修改父组件传过来的值的话控制台会报错,一般的做法是通过$emit(‘自定义属性名’,value)来实现修改 这里我们使用另外一种方法: 例如: 我们需要当点击...子组件修改从父组件传过来的值同时响应更新
我们都知道子组件直接修改父组件传过来的值的话控制台会报错,一般的做法是通过$emit(‘自定义属性名’,value)来实现修改
这里我们使用另外一种方法:
例如: 我们需要当点击某项操作后刷新表格,需要改变表格loading的状态, 直接修改控制台肯定是会报错的
这个时候我们就需要在父组件中在自定义属性名后加上.sync修饰符
父组件 <children :loading.sync="loading"></children>
然后在子组件中加上update属性就可以实现父组件和子组件同时响应变化
子组件 this.$emit('update:loading',true) this.$api... .then(res => { this.$emit('update:loading',false) /成功调用接口后关闭loading })
这样就修改成功了,同时控制台也不会报错,父组件和子组件也是同时更新的
-
vue父子组件传值
2020-03-27 16:49:06(2)直接在父组件中通过$refs.change(params) 子组件方法(参数)将值传给子组件 (正确用法) 当改变了props的值时,子组件也会自动改变的 (1)在父组件改变props就可以了 (2)如果想组件刷新的话,可以在组件里面... -
vue 强制更新视图 刷新组件
2020-09-17 14:16:15就是子组件的值是父组件中传过来的,当我在父组件改变了子组件的值的时候,发现子组件的视图并没有发生更新,肿么办?** 思路: 只要强制更新视图就行了 解决方法一: 使用了 key-changing // 父组件 <div class=... -
Vue改变数组值,页面视图为何不刷新?
2020-02-12 09:52:591、iview table 自定义序号 将其对应的type设为 index 即可 ...复制代码2、父子组件传值,父组件调用子组件方法 场景:iview 中 封装一个modal 组件公共引用 父组件: // 引入组件 import orderMod... -
Vue url参数改变,DOM树未刷新问题---Vue.nextTick()
2019-07-24 15:40:08此时,父组件值更新,子组件不重新渲染,是因为,父组件值改变子组件不会走mounted的生命周期。 处理方案: 使用watch监听父组件传的值,当值改变的时候,进行对应操作。 2、推荐使用: 子组件中直接使用父组件传... -
解决Vue 刷新页面导航显示高亮位置不对问题
2020-11-28 12:07:50但是当我刷新页面后高亮位置就变成了第一个 在头部组件里面控制导航高亮显示是checked,默认值是0,触发点击事件会重新赋值,跳转路由,当刷新页面,checked值是0...这样会防止从子组件意外改变父级组件的状态, -
解决vue项目刷新后,导航菜单高亮显示的位置不对问题
2020-12-13 04:38:36在头部组件里面控制导航菜单高亮显示是checkindex,默认值是0,触发点击事件contact时候会重新赋值,跳转路由,一旦刷新页面,这个checkindex的值就是0,所以要把这个checkindex值记录下来,时刻监听到变化;... -
vue-router用path,query传参,刷新页面数据消失的问题
2020-11-11 18:41:451.vue-router用path,query传参,刷新页面数据消失的问题 1、要跳转的传参页:先将数组...3.vue中的props是单向绑定的,父组件的属性变化时会传递给子组件,子组件内部不应改变props的值,否则控制台会给出警告。 ... -
[vue] 解决vuex中state页面刷新恢复默认值的一些思路
2019-08-04 01:52:17点击加入购物车按钮时(不同页面都有加入购物车按钮,它们之间是非子父组件之间关系),实时改变购物车数量的变化; 我们都知道,实现它可以使用vuex,但是页面刷新时,要保持vuex中的值不会被还原成默认值,该... -
Vue 爬坑二(json数组数据操作,不刷新)
2018-12-14 15:05:58在项目中使用到json数据的次数还是很多的,小编奔到的第一个问题就是,父传子的json数据在子组件操作的时候,会顺带的改变父组件的值,试了好几个办法,最后是使用的JSON.parse(JSON.stringify('传的值')做的处理,... -
【前端】vue遇到的坑
2019-05-15 11:10:002、在父页面引入子组件时,子组件修改以后,想要重新刷新(vue组件实现局部刷新)。 答:在引入子组件时,增加v-if属性,通过控制v-if的值,控制刷新。(v-if的值改变时,该组件会重新加载刷新) 实现方法如... -
vue 数据流研究
2021-02-01 23:15:29父组件与子组件的数据交流方式: ...每次父级组件发生变更时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你不应该在一个子组件内部改变 prop。 <uni-popup-dialog type="success" cont -
Vue 踩坑记录(持续跟新)
2018-06-14 00:01:23父组件向子组件传值 Prop 单向数据流 所有的 prop 都使得其父子 prop ...额外的,每次父级组件发生更新时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你不应该在一个子组件内部改变 prop。如果你这样做... -
直接修改props中的值,浏览器发出警告
2019-01-14 07:07:55改变了子组件中的props中的值,浏览器会发出警告在vue文档中的单向数据流也提到了 每次父级组件发生更新时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你不应该在一个子组件内部改变 prop。如果你这样做了... -
Avoid mutating a prop directly since the value will be overwritten whenever
2020-12-11 15:08:22在vue中,父组件向子组件传值, 并在子组件改变了父组件的值,就会发出警告 所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件... -
prop 验证,和默认值
2020-09-14 21:00:57额外的,每次父级组件发生更新时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你不应该在一个子组件内部改变 prop。如果你这样做了,Vue 会在浏览器的控制台中发出警告。子组件想修改时,只能通过 $emit ... -
qiankun 对于 props 的应用类似于 react 框架的父子组件通信,传入 data 数据供自组件使用,传入 fn 函数给子组件触发向上回调。 按照这个思路我们将主应用的 main.js 和子应用的 main.js 都改造一番(此改造会在...
-
SecureCRT 连接 GNS3/Linux 的安全精密工具
-
一水甲酸锂最佳相位匹配角的计算
-
JQuery设计自定义分页组件
-
2021-02-25
-
Git设置分支保护实现CodeReview卡点
-
AndroidMVVM应用框架构建过程详解
-
多线程:静态代理模式
-
小秘密(学习)
-
Liunx 优化思路与实操步骤
-
git_practice-源码
-
Galera 高可用 MySQL 集群(PXC v5.6 + Ngin
-
LVS + Keepalived 实现 MySQL 负载均衡与高可用
-
uboot移植文档.zip
-
Cakebrew:使用Cakebrew通过样式管理您的Homebrew公式-源码
-
虚幻4引擎基础
-
学习算法:算法练习笔记-源码
-
【科技改变生活,区块链改变世界】欧科云链徐明星的区块链密码朋克世界
-
PPTP_NNN 服务生产环境实战教程
-
欧易OKEx的回流之战
-
DHCP 动态主机配置服务(在Linux环境下,配置单网段或跨网段提)