Vue组件

作者: lwz4070 | 来源:发表于2019-01-15 10:25 被阅读0次

Prop属性

prop定义了这个组件有哪些可配置的属性,组件的核心功能也都是它来确定的。写通用组件时,props 最好用对象的写法,这样可以针对每个属性设置类型、默认值或自定义校验属性的值,这点在组件开发中很重要,然而很多人却忽视,直接使用 props 的数组用法,这样的组件往往是不严谨的。比如我们封装一个按钮组件<i-button>

<template>
  <button :class="'i-button-size-'+size" :disabled="disabled">登陆</button>
</template>
<script>
  //判断参数是否是其中之一
  function oneOf(value, validList) {
    for(let i = 0; i< validList.length; i++) {
      if(value === validList[i]) {
        return true;
      }
    }
    return false;
  }
  export default {
    name: 'IButton',
    props: {
      size: {
        validator(value) { // 自定义验证函数
          return oneOf(value, ['small', 'large', 'default']);
        },
        default: 'default'
      },
      disabled: {
        type: Boolean,
        default: false
      }
    }
  }
</script>

<style scoped>
  .i-button-size-small {
    border: 1px solid red;
  }
  .i-button-size-large {
    border: 1px solid blue;
  }
  .i-button-size-default {
    border: 1px solid skyblue;
  }
</style>

引入组件:

components: {
    iButton
  }

使用组件:

<i-button size="large"></i-button>
<i-button disabled></i-button>

组件中定义了两个属性:尺寸 size 和 是否禁用 disabled。其中 size 使用 validator 进行了值的自定义验证,也就是说,从父级传入的 size,它的值必须是指定的 small、large、default 中的一个,默认值是 default,如果传入这三个以外的值,都会抛出一条警告。

要注意的是,组件里定义的 props,都是单向数据流,也就是只能通过父级修改,组件自己不能修改 props 的值,只能修改定义在 data 里的数据,非要修改,也是通过后面介绍的自定义事件通知父级,由父级来修改。

在使用组件时,也可以传入一些标准的 html 特性,比如 id、class:

<i-button id="btn1" class="btn-submit"></i-button>

这样的 html 特性,在组件内的 <button> 元素上会继承,并不需要在 props 里再定义一遍。这个特性是默认支持的,如果不期望开启,在组件选项里配置 inheritAttrs: false (Vue2.4.0以上版本支持)就可以禁用了。

插槽Slot

如果要给上面的按钮组件 <i-button> 添加一些文字内容,就要用到组件的第二个 API:插槽 slot,它可以分发组件的内容,比如在上面的按钮组件中定义一个插槽:

<button :class="'i-button-size-'+size" :disabled="disabled">
    <!--插槽-->
    <!--父组件里的span会替换掉slot所以这里的123是看不见的-->
    <!--如果父组件在使用子组件testSlot的时候不在里面加内容则这里的slot会显示出来-->
    <slot>123</slot>
  </button>

这里的 <slot> 节点就是指定的一个插槽的位置,这样在组件内部就可以扩展内容了:

<div class="hello">
    <vue-toast></vue-toast>
    <i-button class="bg" size="large" id="large-button"><span>按钮一</span></i-button>
    <i-button disabled><span>按钮二</span></i-button>
  </div>

当需要多个插槽时,会用到具名 slot,比如上面的组件我们再增加一个 slot,用于设置另一个图标组件:

<template>
  <button :class="'i-button-size' + size" :disabled="disabled">
    <slot name="icon"></slot>
    <slot></slot>
  </button>
</template>
<i-button>
  <i-icon slot="icon" type="checkmark"></i-icon>
  按钮 1
</i-button>

这样,父级内定义的内容,就会出现在组件对应的 slot 里,没有写名字的,就是默认的 slot。

自定义事件 event

现在我们给组件 <i-button> 加一个点击事件,目前有两种写法,我们先看自定义事件 event(部分代码省略):

//子组件
template>
  <button :class="'i-button-size-'+size" :disabled="disabled" @click="chilHandleClick">
    <slot>123</slot>
  </button>
</template>
<script>
methods: {
      chilHandleClick(event) {
        console.log("children",event);
        this.$emit('on-click', {event, name: "lucy"});
      }
    }
</script>

通过 $emit,就可以触发自定义的事件 on-click ,在父级通过 @on-click 来监听:

    <i-button  @on-click="parentHandleClick"><span>按钮一</span></i-button>

<script>
methods: {
    parentHandleClick({event,name}) {
      console.log("parent",name)
      console.log("parent",event)
    }
  }
</script>

上面的 click 事件,是在组件内部的 <button> 元素上声明的,这里还有另一种方法,直接在父级声明,但为了区分原生事件和自定义事件,要用到事件修饰符 .native,所以上面的示例也可以这样写:

<i-button @click.native="handleClick"></i-button>

如果不写 .native 修饰符,那上面的 @click 就是自定义事件 click,而非原生事件 click,但我们在组件内只触发了 on-click 事件,而不是 click,所以直接写 @click 会监听不到。

Vue生命周期

Vue.js 生命周期 主要有 8 个阶段:
创建前 / 后(beforeCreate / created):在 beforeCreate 阶段,Vue 实例的挂载元素 el 和数据对象 data 都为 undefined,还未初始化。在 created 阶段,Vue 实例的数据对象 data 有了,el 还没有。

载入前 / 后(beforeMount / mounted):在 beforeMount 阶段,Vue 实例的 $el 和 data 都初始化了,但还是挂载之前为虚拟的 DOM 节点,data 尚未替换。在 mounted 阶段,Vue 实例挂载完成,data 成功渲染。

更新前 / 后(beforeUpdate / updated):当 data 变化时,会触发 beforeUpdate 和 updated 方法。这两个不常用,且不推荐使用。

销毁前 / 后(beforeDestroy / destroyed):beforeDestroy 是在 Vue 实例销毁前触发,一般在这里要通过 removeEventListener 解除手动绑定的事件。实例销毁后,触发 destroyed。

相关文章

网友评论

      本文标题:Vue组件

      本文链接:https://www.haomeiwen.com/subject/jdyedqtx.html