vue弹窗组件的使用(传值),以及弹窗只能触发一次的问题

vue弹窗组件的使用以及弹窗只能触发一次

1.父组件引入并注册子组件

  1. import BusinessDialog from ‘../../components/BusinessDialog’
  2. export default {
  3.      components: {
  4.      BusinessDialog
  5.      },
  6.      data() {
  7.      return {
  8.      dialog:false;
  9.      };
  10.      },

2.在父组件中使用子组件

  1. <business-dialog :dialog.sync=“dialog”></business-dialog>
  2. //这里的dialog就是要传递给子组件的值,默认是false(不弹出)

3.事件触发改变dialog的值

  1. openDialog() {
  2.      this.dialog = true
  3.      },
  4.      //在父组件中点击编辑按钮,触发弹窗

以下是子组件的操作

  1. export default {
  2. //子组件通过props接收父组件传递过来的值 dialog控制弹窗的弹出及隐藏
  3.      props: {
  4.      dialog: {
  5.      type: Boolean,
  6.      default: false,
  7.      },
  8.      },
  9.      data() {
  10.      return {
  11.      };
  12.      },
  13.      methods: {
  14.      checkDate(val) {},
  15.      //解决弹窗只能弹一次的问题(点击确定和取消按钮的时候,给dialog做一个重新赋值)
  16.      confirm() {
  17.      this.$emit(“update:dialog”, false);
  18.      },
  19.      cancle() {
  20.      this.$emit(“update:dialog”, false);
  21.      },
  22.      //子组件传值给父组件(onChange是传递给父组件的事件名, true是传递给父组件的值)
  23.      this.$emit(‘onChange’,true)
  24.      },
  25. };

父组件怎么接收子组件传的值呢?

  1. <business-dialog :dialog.sync=“dialog” @onChange=getData></business-dialog>
  2. methods:{
  3. getData(val) {
  4.      //这个val就是接收到的子组件传递过来的值啦~~~~
  5.      }
  6. }

关于弹窗组件的优化处理

在之前的项目中,发现很多页面中有很多选择各种数据的弹窗,如下:

-1

一般来说,在vue的项目中写成一个子组件,在父组件中引用即可。

问题在于

  • 1.在父组件中要定义变量,什么时候展示该子组件
  • 2.父子组件中的通信,父组件要定义方法传给子组件调用
  • 3.大量的父组件需要用到这个组件时,难免要重复上面的操作

于是,我想出一种思路,可不可以在父组件中通过调用方法的方式调用这个子组件,不需要在父组件中定义变量定义方法,省去一部分代码,如下:

  1. this.alertWbs(); // 打开上面的弹窗

具体思路如下

当调用这个方法的时候采用Vue.extend动态构建一个组件,具体代码如下:

  1. import Vue from ‘vue’;
  2. import wbs from ‘./wbs’; // 子组件
  3. const Wbs = Vue.extend(wbs);
  4. var instance = null; // 这里做一个处理,只需要一个实例
  5. export function alertWbs(){
  6.      if(!instance){
  7.          instance = new Wbs();
  8.          instance.$mount();
  9.          document.body.appendChild(instance.$el);
  10.      }
  11.      instance.projectAreaDialog = true; // 控制子组件自己的显示
  12. }

这样以后,调用alertWbs方法以后,子组件会显示出来。

那么还存在另外一个问题,当子组件中选择完了数据以后如何告知父组件

思路:在点击子组件按钮的时候,通知父组件,我已经选好数据了。

如何通知?

第一时间想到的是Promise,利用Promise的机制,当我点击了子组件的按钮时将数据通过resolve的方式推送给父组件,那么父组件里面的方法就可以写成这样

  1. this.alertWbs().then(res=>{
  2.      console.log(res); // 此时传过来的res应该就是子组件中选择的数据了
  3. })

那么,改造一下子组件,让子组件返回一个Promise对象

  1. import Vue from ‘vue’;
  2. import wbs from ‘./wbs’;
  3. const Wbs = Vue.extend(wbs);
  4. var instance = null;
  5. export function alertWbs(){
  6.      if(!instance){
  7.          instance = new Wbs();
  8.          instance.$mount();
  9.          document.body.appendChild(instance.$el);
  10.      }
  11.      instance.projectAreaDialog = true;
  12.      return new Promise((resolve,reject)=>{
  13.          instance.promise = { // 将promise挂载到子组件实例上,因为目前为止,谁也不知道什么时候resolve数据
  14.              resolve,reject
  15.          }
  16.      })
  17. }

在wbs.vue文件中

  1. choose(value){
  2.      this.promise.resolve(value); // 向父组件传值
  3.      this.projectAreaDialog = false; // 改变自己的状态,隐藏
  4. }

大功告成!!!

进一步优化,父组件如何传值给子组件呢?

在一个方法中,最容易想到的肯定是方法的参数,改变一下父组件调用的方法

  1. this.alertWbs(params).then(res=>{
  2.      console.log(res); // 此时传过来的res应该就是子组件中选择的数据了
  3. })

子组件接受值

  1. import Vue from ‘vue’;
  2. import wbs from ‘./wbs’;
  3. const Wbs = Vue.extend(wbs);
  4. var instance = null;
  5. export function alertWbs(params){
  6.      if(!instance){
  7.          instance = new Wbs();
  8.          instance.$mount();
  9.          document.body.appendChild(instance.$el);
  10.      }
  11.      instance.projectAreaDialog = true;
  12.      instance.params = params; // 直接放在子组件的实例上
  13.      return new Promise((resolve,reject)=>{
  14.          instance.promise = { // 将promise挂载到子组件实例上,因为目前为止,谁也不知道什么时候resolve数据
  15.              resolve,reject
  16.          }
  17.      })
  18. }

当然为了让子组件更加灵活,可以内置一个钩子函数,当子组件显示的时候自动调用,我这里用的是init方法,完整的代码如下:

  1. import Vue from ‘vue’;
  2. import wbs from ‘./wbs’;
  3. const Wbs = Vue.extend(wbs);
  4. var instance = null;
  5. export function alertWbs(){
  6.      if(!instance){
  7.          instance = new Wbs();
  8.          instance.$mount();
  9.          document.body.appendChild(instance.$el);
  10.      }
  11.      instance.projectAreaDialog = true;
  12.      // init方法获取页面数据
  13.      instance.init();
  14.      return new Promise((resolve,reject)=>{
  15.          instance.promise = {
  16.              resolve,reject
  17.          }
  18.      })
  19. }

init方法其实就是wbs.vue中的普通方法,需要定义

以上调用方法使用到的this,是由于该方法挂载在vue的原型对象上,不需要在每个组件中引用

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

标签

发表评论