业务场景

当自己想封装ui组件库的modal组件时,我们最初的设想是父组件传递一个布尔值(isShow)给子组件,子组件根据该值显示隐藏;但是组件通过v-model绑定的数据是双向绑定的,意味着这个数据必须可以set数据,但是vue里的props是单向数据流,是不能set数据给父组件的(会造成数据流混乱)。
以前我是这么做的,通过在自组件定义方法,然后父组件直接调用$ref.xxx来改变子组件的数据,从而达到显示隐藏的目的。以下为代码:

<template>
  <div>
    <Modal v-model="isShow" width="600px" title="title">
      <div slot="footer">
        <Button @click="isShow = false">关闭</Button>
      </div>
    </Modal>
  </div>
</template>

<script lang="ts">
import { Component, Vue, Prop, Watch, Emit } from 'vue-property-decorator';

@Component
export default class SecretKeyManage extends Vue {
  isShow: boolean = false
}
</script>

但是这样直接调用子组件的方法总归不太优雅,vue推荐使用props将父组件的数据向下传递,于是有了下面的这种写法:

代码实现

<template>
  <div>
    <Modal v-model="isShow" width="600px" title="title">
      <div slot="footer">
        <Button @click="isShow = false">关闭</Button>
      </div>
    </Modal>
  </div>
</template>

<script lang="ts">
import { Component, Vue, Prop, Watch, Emit } from 'vue-property-decorator';

@Component
export default class MyModal extends Vue {
  // 父组件传递的值 用于初始化 isShow 
  @Prop({ default: false }) isMyModalShow!: boolean;

  // 用于绑定v-model
  get isShow() {
    return this.isMyModalShow;
  }
  set isShow(val) {
    this.handleEmit(val)
  }
  @Emit('update:isMyModalShow')
  handleEmit(val: boolean) {
    return val;
  }

  @Watch('isShow')
  handleShowModal(val: boolean) {
    if (!val) return;
    // 当显示modal组件的时候 do something
    
  }
}
</script>

// 父组件调用
<MyModal :isMyModalShow.sync="isMyModalShow" />
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';

export default class MyModal extends Vue {
  isMyModalShow: boolean = false
}
    
</script>

其实很简单 就是通过 set 将数据回传给父组件,需要注意的是父组件绑定isMyModalShow的时候需要加sync修饰符。

以上所有代码使用ts实现


韦磊
90 声望11 粉丝

沉稳,踏实,坚持,这正是我所欠缺的