• 实现组件props双向绑定解决方案


    注意: 子组件不能直接修改prop过来的数据,会报错

    方案一:

    1. 用data对象中创建一个props属性的副本

    2. watch props属性 赋予data副本 来同步组件外对props的修改

    3. watch data副本,emit一个函数 通知到组件外

    HelloWorld组件代码如下:(代码里面有相应的注释)

    复制代码
    <template>
      <div class="hello">
        <h1 v-show="visible">测试显示隐藏</h1>
        <div @click="cancel">点我点我</div>
      </div>
    </template>
    
    <script>
    export default {
      name: 'HelloWorld',
      props: {
          value: {
            type: Boolean,
            default:false
          }
        },
      data () {
        return {
          visible: false
        }
      },
      watch:{
        value(val) {
          this.visible = val;
        },
    // 只有这一步 才触发父组件的方法 由父组件的 paretnVisibleChange 方法去改变父组件的数据
      visible(val) { this.$emit("paretnVisibleChange",val); } },
      // 子组件修改的只能是子组件 本身的data数据 methods:{ cancel(){ this.visible = !this.visible; } },
    // 注意这段代码 为了同步父组件的数据 mounted() { if (this.value) { this.visible = true; } } } </script> <style scoped> </style>
    复制代码

    父组件代码如下:

    复制代码
    <template>
      <div id="app">
        <HelloWorld :value = 'visible' @paretnVisibleChange="visibleChange" />
      </div>
    </template>
    
    <script>
    import HelloWorld from './components/HelloWorld'
    
    export default {
      name: 'App',
      components: {
        HelloWorld
      },
      data () {
        return {
          visible: true
        }
      },
      methods:{
    // 父子组件就是靠的这个方法改变数据的 visibleChange(val){ this.visible = val; } } } </script>
    复制代码

    方案一 的缺点就是 父组件必须有个 visibleChange 这样的方法,有点累赘。

    这时候 想到了 v-model 

    因为

    <input v-model = 'someThing'>

    是下面这段代码的语法糖

    <input :value = 'someThing'  @input = 'someThing = $event.target.value'>

    也就是说 v-mode 自带了 一个改变父组件的方法 类似方案一的   paretnVisibleChange

    但是使用 v-model 的时候 需要注意两点:

    1. 子组件要接受  value  属性

    2. value改变时 要触发input 事件

    方案二:

    HelloWorld 子组件的代码如下;

    复制代码
    <template>
      <div class="hello">
        <h1 v-show="visible">测试显示隐藏</h1>
        <div @click="cancel">点我点我</div>
      </div>
    </template>
    
    <script>
    export default {
      name: 'HelloWorld',
      props: {
          value: {
            type: Boolean,
            default:true
          }
        },
      data () {
        return {
          visible: false
        }
      },
      watch:{
        value(val) {
          this.visible = val;
        },
    // 子组件 改变的就是这段代码 visible(val) { this.$emit("input",val); } }, methods:{ cancel(){ this.visible = !this.visible; } }, mounted() { if (this.value) { this.visible = true; } } } </script>
    复制代码

    父组件代码如下:(父组件省去了 paretnVisibleChange 方法)

    复制代码
    <template>
      <div id="app">
        <HelloWorld v-mode = 'visible'/>
      </div>
    </template>
    
    <script>
    import HelloWorld from './components/HelloWorld'
    
    export default {
      name: 'App',
      components: {
        HelloWorld
      },
      data () {
        return {
          visible: true
        }
      }
    }
    </script>
    复制代码

    方案三:

    vue 2.3.0之后新增了 .sync 属性 使用方法跟 v-model  类似 具体 请参考 : https://cn.vuejs.org/v2/guide/components-custom-events.html#sync-修饰符

    下面我写了一个简单的sync 的使用实例:

    父组件的代码如下:

    复制代码
         <li
            is="DragCompent"
            v-for="(item, index) in layoutItem"
            :item="item"
            v-model="cloneLeftItemText"
            :leftDragItemIsDraged.sync = 'leftDragItemIsDraged'
            :key="index"></li>
    复制代码

    子组件的代码如下:

    复制代码
    props: {
        leftDragItemIsDraged: {
          type: Boolean,
          default: false
        }
      },
    watch:{
        leftDragItemIsDraged(val) {
        this.thisLeftDragItemIsDraged = val;
    },
    thisLeftDragItemIsDraged(val){
        this.$emit('update:leftDragItemIsDraged', val)
    }
    }
    复制代码

    效果如下:

  • 相关阅读:
    RESTful Web 服务
    关于 Java API for RESTful Web Services (JAX-RS) 介绍
    IPV6正则表达式
    使用MyBatis-generator 自动生成MyBatis代码
    JSON.stringfy妙用
    浅拷贝与深拷贝
    vue双向绑定原理与实践
    vue路由当中的导航钩子中关于next()方法的理解
    Promise 异步备忘
    封装van-popup为自己的弹窗组件解决v-moel props单向数据流不能修改的问题。
  • 原文地址:https://www.cnblogs.com/amujoe/p/11769269.html
Copyright © 2020-2023  润新知