封装组件系列-(二)-父子组件传值

一,单向数据流props传值

父组件:

主要按钮

子组件:

<template>
  <button
    class="biu-button"
    :class="[
      `biu--button--${type}`,
      {
        'is-plain': plain,
        'is-disabled': disabled,
        'is-round': round,
        'is-circle': circle,
      },
    ]"
    @click="handleClick"
    :disabled="disabled"
  >
    <i v-if="icon" :class="`biu-icon-${icon}`">i>
    
    <span v-if="$slots.default"><slot>slot>span>
  button>
template>

<script>
export default {
  name: "BiuButton",
  props: {
    type: {
      type: String,
      default() {
        return "default";
      },
    },
    plain: {
      type: Boolean,
      default: false,
    },
    round: {
      type: Boolean,
      default: false,
    },
    circle: {
      type: Boolean,
      default: false,
    },
    disabled: {
      type: Boolean,
      default: false,
    },
    icon: {
      type: String,
      default: "",
    },
  },
};
script>

主要使用下面方式接收:

props: {
    type: {
      type: String,
      default() {
        return "default";
      },
    },
}

二,子组件事件绑定修改父组件的值

父组件:

<template>
  <div id="app">
    <biu-dialog
      title="温馨提示"
      :visible="visible"
      v-on:handleClose="handleClose"
    >
    biu-dialog>
  div>
template>

<script>
export default {
  name: "App",
  data() {
    return {
      visible: true,
    };
  },
  methods: {
    handleClose() {
      this.visible = false;
    },
  },
};
script>

子组件:

<template>
  <div class="biu-dialog_wrapper" v-show="visible">
    <div class="biu-dialog">
      <div class="biu-dialog_header">
        <button class="biu-dialog_headerbtn">
          <i class="biu-icon-basic_refresh1" @click="handleClose">i>
        button>
      div>
    div>
  div>
template>

<script>
export default {
  name: "biu-dialog",
  props: {
    visible: {
      type: Boolean,
      default() {
        return false;
      },
    },
  },
  methods: {
    handleClose() {
      this.$emit("handleClose", false);
    },
  },
};
script>

子组件通过@click="handleClose"调用子组件的

this.$emit(“handleClose”, false);从而调用 父组件的handleClose函数,修改父组件的visible值。然后visible单向传递给子组件。

三,子组件事件绑定修改父组件值简化.sync修饰符

vue提供了一个.sync 修饰符来简化第二节中的代码:

父组件:

<template>
  <div id="app">
    <div>
    <biu-dialog title="温馨提示" :visible.sync="visible">
    biu-dialog>
  div>
template>

<script>
export default {
  name: "App",
  components: {},
  data() {
    return {
      visible: true,
    };
  },
  methods: {},
};
script>

子组件:




也就是父组件不需要再绑定子组件需要触发的事件了。

四,v-model配合事件绑定

在直接使用input的时候,可以直接使用v-mode进行数据的双向绑定,而当我们使用自定义组件的时候。也可以利用这一点。

一个组件上的 v-model 默认会利用名为 value 的 prop 和名为 input 的事件,

这时候就可以在父组件中:

<template>
  <div id="app">
    
    <biu-input
      v-model="username"
    >biu-input>
  div>
template>

<script>
export default {
  name: "App",
  data() {
    return {
      username: "",
    };
  }
};
script>

也就是使用了v-model的组件biu-input,该子组件内部默认会生成名为value的prop,和绑定名为input的事件。(而该input事件,就是更新父组件的v-model绑定的属性)

于是可以在这个子组件中进行接收使用名为value的prop:



子组件先接收value,子组件触发input修改事件handleInput后触发父组件的input事件,从而修改了父组件的username值。

自定义组件的v-model 和 .sync修饰符其实本质上都是vue的语法糖,用于实现父子组件的“数据”双向绑定,vue3中已经不再有.sync修饰符了,新的v-model取代了vue2中的v-model和.sync修饰符。

相比较之下,.sync 更加灵活,它可以给多个 prop 使用,而 v-model 在一个组件中只能有一个。(Vue3中v-model已经可以给多个prop使用了)
从语义上来看,v-model 绑定的值是指这个组件的绑定值,比如 input 组件,select 组件,日期时间选择组件,颜色选择器组件,这些组件所绑定的值使用 v-model 比较合适。其他情况,没有这种语义,个人认为使用 .sync 更好。

五,v-model配合子组件computed

在第四节中,v-model是配合@input方法,让子组件调用父组件的input方法。

实际上,还可以在子组件使用compute的set和get方法实现这一功能。

父组件:

<biu-radio v-model="gender" label="0"></biu-radio>
data() {
    return {
      gender: "",
	};
}

子组件:

  <input
        type="radio"
        class="one-radio_original"
        :value="label"
        v-model="model"
      />


//计算属性
  computed: {
    model: {
      get() {
        return this.value;
      },
      set(value) {
        // 触发父组件的input事件
        this.$emit("input", value);
      },
    },
  },

input的值是label定义的。当选中时,input的绑定值变成label,触发computed的set,就会调用父组件的input函数,从而修改父组件的gender值。

(上文说过,自定义组件的v-model会给子组件内部默认生成名为value的prop,和绑定名为input的事件)

六,provide配和inject

这对选项需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在其上下游关系成立的时间里始终生效。

祖先组件:


子孙组件:

export default {
  inject: {
    RadioGroup: {
      default: "",
    },
  },
}

这样,RadioGroup默认是是空字符串,如果有传入,则是组件RadioGroup。子组件中就可以直接使用了。

你可能感兴趣的:(#,组件封装,javascript,前端,vue.js)