2020你应该有一个自己的组件

简介: 2020你应该有一个自己的组件

一、概述

组件化是长期开发过程中一个提炼精华的过程,目的主要是提高复用性、解耦、提升开发效率。本次主要以Vue.js为例来讲解前端组件开发的注意事项,并且带领大家封装自己的组件并发布到npm。

二、环境

  • window10 x64
  • node v10.16.3
  • npm v6.13.4
  • yarn

三、什么叫做组件化

Vue.js 有两大特性,一个是数据驱动,另一个就是组件化。接下来我就针对这两个问题一一解答,所谓组件化,就是把页面拆分成多个组件,每个组件依赖的 CSS、JS、模板、图片等资源放在一起开发和维护。 因为组件是资源独立的,所以组件在系统内部可复用,组件和组件之间可以嵌套,如果项目比较复杂,可以极大简化代码量,并且对后期的需求变更和维护也更加友好。

四、如何进行组件化开发

Vue.js 提供了 2 种组件的注册方式,全局注册和局部注册。

4.1 全局注册

在vue.js中我们可以使用Vue.component(tagName,options)进行全局注册。 例如:

Vue.component('my-component', {
  // 选项
})

4.2 局部注册

Vue.js 也同样支持局部注册,我们可以在一个组件内部使用 components 选项做组件的局部注册。 例如:

import HelloWorld from './components/HelloWorld'
export default {
  components: {
    HelloWorld
  }
}

区别:全局组件是挂载在 Vue.options.components 下,而局部组件是挂载在 vm.$options.components 下,这也是全局注册的组件能被任意使用的原因。

五、组件开发的要素

  • 组件的名称
  • 控制参数
  • 自定义内容
  • 自定义事件

六、封装一个Vue组件

6.1 开发vue组件要素

6.6.1 组件的名称name(必填)

js 中使用驼峰式命令,HTML 使用kebab-case命名。

<my-component/>
<my-component></my-component>
……
<script>
export default {
  name: 'MyComponent',
  props: {
    prefixCls: {
      type: String,
      default: 'ant-editor-wang'
    },
    // eslint-disable-next-line
    value: {
      type: String
    }
}
……
</script>

6.6.2 props参数

组件属性,用于父子组件通信,可通过this.msg访问。

父对子传参,就需要用到 props,通常的 props 是这样的:

props:['data','type']

// show: Boolean // 默认false //msg: [String, Boolean]  // 多种类型

但是通用组件的的应用场景比较复杂,对 props 传递的参数应该添加一些验证规则,常用格式如下:

props: {
    // 基础类型检测 (`null` 意思是任何类型都可以)
    propA: Number,
    // 多种类型
    propB: [String, Number],
    // 必传且是字符串
    propC: {
      type: String,
      required: true
    },
    // 数字,有默认值
    propD: {
      type: Number,
      default: 100
    },
    // 数组/对象的默认值应当由一个工厂函数返回
    propE: {
      type: Object,
      default: function () {
        return { message: 'hello' }
      }
    },
    // 自定义验证函数
    propF: {
      validator: function (value) {
        return value > 10
      }
    }
  }

对于通过 props 传入的参数,不建议对其进行操作,因为会同时修改父组件里面的数据 // vue2.5已经针对 props 做出优化,这个问题已经不存在了 如果一定需要有这样的操作,可以这么写:

let copyData = JSON.parse(JSON.stringify(this.data))

6.6.3 computed:

处理data或者props中的属性,并返回一个新属性。(注:因为props,data和computed在编译阶段都会作为vm的属性合并,所以不可重名)

<template>
  <div>{{newMsg}}</div>
</template>
<script>
    export default {
        computed: {
        newMsg() {
          return '前端微服务 ' + this.msg
        }
    },
        ……
    }
</script>

6.6.4 render

用render函数描述template。

<my-component tag='button'>前端微服务</my-component>
<script type="text/javascript">
  export default {
    name: 'MyComponent',
    props: {
      tag: {
        type: String,
        default: 'div'
      },
    },
    // h: createElement
    render(h) {
      return h(this.tag,
        {class: 'demo'}, 
        this.$slots.default)
    }
  }
</script>

注意: render 中的 h 其实就是 createElement,它接受三个参数,返回一个 vnode

h 参数解释:

  1. args1:stringFunction | Object用于提供DOM的html内容
  2. args2: {Object} 设置DOM样式、属性、绑定事件之类
  3. args3: {array} 用于设置分发的内容

注:vue编译顺序: template–> compile --> render --> vnode --> patch --> DOM

6.6.5 slot定制插槽

分发内容,有传入时显示,无传入 DOM 时显示默认,分为无名和具名两种,this.slots.default默认指向无名插槽,多个slot时用法this.slots.name,一个通用组件,往往不能够完美的适应所有应用场景 所以在封装组件的时候,只需要完成组件 80% 的功能,剩下的 20% 让父组件通过 solt 解决。

// 子组件
<div class="child-btn">
    <!-- 具名插槽 -->
    <slot name="button"></slot>
    <!-- 匿名插槽(每个组件只能有一个) -->
    <slot><slot>
</div>
// 父组件
<child>
    <!-- 对应子组件中button的插槽 -->
    <button slot="button">slot按钮</button>
</child>

组件封装

<my-component>
  <div slot='header'>header</div>
  <div class="body" slot='body'>
    <input type="text">
  </div>
  <div slot='footer'>footer</div>
  <button class='btn'>button</button>
</my-component>
<template>
  <div>
    <slot name='header'></slot>
    <slot name='body'></slot>
    <slot name='footer'></slot>
    <slot></slot>
  </div>
</template>
<script>
  export default {
    name: 'MyComponent',
    mounted() {
      this.$slots.header // 包含了slot="foo"的内容
      this.$slots.default // 得到一个vnode,没有被包含在具名插槽中的节点,这里是button
    }
  }
</script>

6.6.6  定义子组件的类名class

// 父组件
<my-component round type='big'/>
// 子组件
<div :class="[
  type ? 'my-component__' + type : '',
  {'is-round': round},
]">控制</div>
//真实DOM
<div class='my-component__big is-round'>hello</div>

6.6.7 向子组件传递样式 style

// 父组件
<my-component :bodyStyle='{color: "red"}'/>
// 子组件
<template>
  <div :style='bodyStyle'>hello world</div>
</template>
<script>
  export default {
    name: 'MyComponent',
    props: {
      bodyStyle: {},
    },
  }
</script>

6.2 其他属性

6.2.1 $attrs

v-bind="$attrs" 将除class和style外的属性添加到父组件上,如定义input:

<input v-bind="$attrs">

6.2.2 v-once

组件只渲染一次,后面即使数据发生变化也不会重新渲染。比如例子中val不会变成2020

<template>
  <div>
    <button @click="show = !show">button</button>
    <button @click="val = '2020'">button</button>
    <div v-once v-if="show">
      <span>{{val}}</span>
    </div>
  </div>
</template>
<script>
export default {
  data() {
    return{
      show: false,
      val: '123'
    }
  },
};
</script>

6.2.3 mixins

// mixin.js
export default {
  data() {
    return{
       msg: 'hello world'
    }
  },
  methods: {
    clickBtn() {
      console.log(this.msg)
    }
  },
}
// index.vue
<button @click="clickBtn">button</button>
import actionMixin from "./mixin.js";
export default {
  methods: {},
  mixins: [actionMixin]
}

6.3  封装button组件

index.vue

<template>
  <button>MyButton</button>
</template>
<script>
export default {
  name: 'MyButton'
}
</script>

index.js

import MyButton from './src/index'
MyButton.install = (Vue) => {
  Vue.component(MyButton.name, MyButton)
}
export default MyButton

其中 install 是 Vue.js 提供了一个公开方法,这个方法的第一个参数是 Vue 构造器,第二个参数是一个可选的选项对象。MyPlugin.install = function (Vue, options){}

七、发布到npm

7.1 登陆npm

$ npm login

7.2 发布

$ npm publish
目录
相关文章
|
3月前
|
监控 数据可视化 索引
四个组件配置说明
官方文档!!!!!!!!! 1.在Filebeat中配置info.log日志文件的路径,以及要将日志发送到Logstash的地址和端口,可以在Filebeat的配置文件 filebeat.yml中添加如下配置: Copy filebeat.inputs: - type: log paths: - /usr/logs/info.log fields: log_type: info output.logstash: hosts: ["localhost:5044"] 这里使用filebeat.inputs指定要监控的日志文件路径
49 5
|
6月前
在组件上使用
在组件上使用
|
6月前
|
JavaScript
组件上使用 v-for
组件上使用 v-for
|
6月前
|
JavaScript 前端开发
Vue3中的组件:组件的定义、组件的属性和事件、组件的Slots和动态组件
Vue3中的组件:组件的定义、组件的属性和事件、组件的Slots和动态组件
137 0
|
设计模式 JavaScript 前端开发
可复用性的组件详解
可复用性的组件详解
223 0
可复用性的组件详解
|
JavaScript API
Vue子组件与父组件(看了就会)
Vue子组件与父组件(看了就会)
350 1
|
负载均衡 网络协议 Java
SprongCloud组件
SprongCloud组件
|
架构师 定位技术 iOS开发
关于组件,你真的了解么?
最近经常听到“组件化开发”,那架构设计里,组件到底如何定义、设计和应用呢,今天我们一起来聊聊。
关于组件,你真的了解么?
|
开发者
NSAlert组件应用总结
NSAlert组件应用总结
448 0
NSAlert组件应用总结