Vue实现自定义组件数据双向绑定

前言:使用Vue进行项目开发的时候,通常会用到Vue提供的组件化机制封装开发所需要的组件以达到开发项目的需求,大到项目中的一快筛选模块、数据表格,小到分页面板、级联面板、乃至一个小小的button按钮,之所以组件化也是为提高我们实际的开发效率,那到底什么是组件化呢?参考一张尤玉溪大大的图就会很快明白;

简单来讲一个完整项目会分为很多部分,每个部分都会有各自独立的功能,每个独立的功能组件又是由很多小的组件构成,了解了什么是组件之后,就必须要明白组件之间的通讯方式。Vue官方为我们提供了子传父、父传子的方法以及属性,但是单纯使用这些是远远不能够满足我们的实际开发需求,因为很多时候我们需要父组件与子组件直接双向绑定数据,但是Vue中父子组件通信,都是单项的数据流,具体如下:

父组件:

<!-- 父组件 -->
<template>
  <div class="Parent">
    <el-col :span="12">
      <el-card class="box-card">
        <div slot="header" class="clearfix">
          <h2>Parent(父组件)</h2>
          <el-button style="float: right; padding: 3px 0" type="text">查看详情</el-button>
        </div>
        <el-button type="primary" icon="el-icon-plus" circle @click.native="Add(off)"></el-button>
        <Children :Data="off"></Children>
        <el-col :span="12">
          <span>来自子组件的数据:</span>
          {{msg}}
        </el-col>
      </el-card>
    </el-col>
  </div>
</template>

子组件:

<!-- 子组件 -->
<template>
  <div class="Children">
    <el-dialog
      width="30%"
      top="15%"
      title="Children(子组件)"
      :visible.sync="off"
      :before-close="handleClose"
      modal-append-to-body="false"
      append-to-body="false"
    >
      <el-input v-model="input" placeholder="请输入内容"></el-input>
      <span slot="footer" class="dialog-footer">
        <el-button @click="off = false">取 消</el-button>
        <el-button type="primary" @click="off = false">提 交</el-button>
      </span>
    </el-dialog>
  </div>
</template>

预览:

功能:父组件点击“+”按钮之后调用子组件,子组件提交数据、父组件蓝色部分显示子组件提交的数据;

思路:首先得明白子组件显示与否依赖于off,也就是点击"+"号之后,父组件必须改变子组件的off值子组件数据),父组件data里必须也有个off值用于传递数据父组件数据,从而达到父子组件数据双向绑定的需求;

接下来改造代码:

<!-- 父组件 -->
<template>
  <div class="Parent">
    <el-col :span="12">
      <el-card class="box-card">
        <div slot="header" class="clearfix">
          <h2>Parent(父组件)</h2>
          <el-button style="float: right; padding: 3px 0" type="text">查看详情</el-button>
        </div>
        <el-button type="primary" icon="el-icon-plus" circle @click.native="Add()"></el-button>
        <Children :Data="off" @GetData="GetData"></Children>
        <el-col :span="12">
          <span>来自子组件的数据:</span>
          {{msg}}
        </el-col>
      </el-card>
    </el-col>
  </div>
</template>

<script>
import Children from "./Children"; //引入Children
export default {
  components: {
    Children
  },
  data() {
    return {
      msg: "暂无", //穿传递初始数据
      off: false
    };
  },
  methods: {
    Add() {
      this.off = true; //修改off 打开子组件
    },
    GetData(off,input) { //这里的off是接收子组件传递过来的值
      this.off = off; //把子组件的数据同步到父组件中
      this.msg = input; //同上
    }
  }
};

Parent解释:在父组件中引入子组件Children,使用v-bind绑定父组件的off传递给子组件,当点击“+”号之后执行Add方法改变off为true,使用自定义事件监听子组件事件是否触发,触发之后接收到来自子组件的数据并同步更新到父组件对应的状态;

<!-- 组件说明 -->
<template>
  <div class="Children">
    <el-dialog
      width="30%"
      top="15%"
      title="Children(子组件)"
      :visible.sync="off"
      :modal-append-to-body="false"
      :append-to-body="false"
    >
      <el-input v-model="input" placeholder="请输入内容"></el-input>
      <span slot="footer" class="dialog-footer">
        <el-button @click="Submit(0)">取 消</el-button>
        <el-button type="primary" @click="Submit(1)">提 交</el-button>
      </span>
    </el-dialog>
  </div>
</template>

<script>
export default {
  components: {},
  data() {
    return {
      input: "",
      off: this.Data //赋初始值 等价于off:false
    };
  },
  props: ["Data"], //接收来自父组件的数据
  watch: {
    Data(N, O) {
      this.off = N; //每次Props数据改变的时候同步更新到off
    }
  },
  methods: {
    Submit(key){
      if(key){          //点击提交按钮
        alert("提交!")
        // if(....)    //此处编写表单效验通过后的业务逻辑
        this.off = false
      }else if(!key){
        alert("取消!") //点击取消按钮
        this.off = false
      }
      this.$emit('GetData',this.off,this.input)
    }
  }
};
</script>

Children解释:props对象接收父组件数据,组件创建完毕之后第27行初始化来自父组件的数据(此处由于父组件中off值为false,所以第一次赋值也是false,注意这里只能赋初始值 后面的父组件传递的数据将不会改动,必须由watch监听变化再更新到data > off),取消/提交调用Submit方法,(38行kye==1 1隐式转换之后为true所以不用麻烦写if(key==1),42行同理),执行Submit之后改变off的值为false即关闭子组件,并且使用$emit创建自定义事件GetData (此处GetData必须与父组件中第11行绑定的方法一致才可以触发自定义事件),触发子组件的GetData事件并且同步更新到父组件中;

至此 结束,看一下效果!

发布了17 篇原创文章 · 获赞 76 · 访问量 9655

猜你喜欢

转载自blog.csdn.net/qq_43471802/article/details/101118147