vue支持双向数据流吗?
除了最开始angularJs支持数据的双向流动之外,其他两大框架是均不支持的
vue之所以被常说数据流,其实是错误的。是因为它是双向绑定被有些人理解为双向数据流。
如果发现了一下的错误信息,那就是你违反了不能双向数据流的规定
vue.runtime.esm.js?2b0e:619 [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: "userName"
双向数据流的利弊
首先肯定,弊肯定是大于利的,不然vue直接就支持‘双向数据流’了。
弊端是数据流动不可追踪,无法保证数据源的唯一性,一旦出现问题很难找到错误的位置。
优点是有的时候,在某些特定的场景下,会很方便。比如封装的弹窗显隐控制,表单数据等。
vue如何使用双向数据流
1、props传入引用类型
vue检测props只能检测基本类型的值,而对于复合类型(即对象),只能检测引用地址有没有变化,而属性值变化,不会被加测到。
利用这一特性,我们可以偷偷的绕过“props是只读的”这一检测,来达到“双向数据流”目的。
子组件
<template> <div class="hello"> 姓名:<input type="text" v-model="formData.name"><br/> 年龄:<input type="text" v-model="formData.age"> </div> </template> <script> export default { name: 'userInfo', props: { formData: Object } } </script>
父组件
<template> <div id="app"> <user-info :formData="userInfoForm"/> <button @click="getUserInfoForm">提交</button> </div> </template> <script> import UserInfo from './components/user-info.vue'; // 用户信息表单 export default { name: 'app', components: { UserInfo }, data(){return{ userInfoForm:{ name:'小丁', age: 20 } }}, methods:{ getUserInfoForm(){ console.log(this.userInfoForm); } } } </script>
效果图
2.利用.async来支持双向数据流(原自定组件使用v-model)
父组件
<template> <div class="hello"> 姓名:<input type="text" :value="userName" @input="userNameChange"><br/> </div> </template> <script> export default { name: 'userInfo', props: { userName: String }, methods:{ userNameChange(e){ // 会直接修改父组件的数据 this.$emit('update:userName', e.target.value) } } } </script>
子组件
<template> <div class="hello"> 姓名:<input type="text" :value="userName" @input="userNameChange"><br/> </div> </template> <script> export default { name: 'userInfo', props: { userName: String }, methods:{ userNameChange(e){ // 会直接修改父组件的数据 this.$emit('update:userName', e.target.value) } } } </script>
原理
<user-info :userName.sync="userNameVal"/> <!-- 会被扩展为: --> <user-info :userName="userNameVal" @update:userName="val => userNameVal = val"/> 当子组件需要更新 userName 的值时,它需要显式地触发一个更新事件: this.$emit('update:userName', newValue)