如何优雅地写一个Vue全局组件

如何优雅地写一个Vue全局组件


在Vue开发过程中,为了实现高内聚,低耦合的代码,组件复用是一件稀松平常的事情。

你可能看到过在多个组件中频繁import,并且添加到components里,最后,还要在template模板中引用。

引入

import childCom from '@/components/childCom.vue';

注册

components:{
    childCom
}

引用

<childCom/>

以上只是最普通的用法,当你需要父子组件进行数据传递的时候,各种props,$emit,业务越多,就越有一种剪不断理还乱的感慨。It's so messy


高级一点的,你可能会想,与其频繁地import,我干嘛不使用全局组件呢?恭喜你,已经很接近真相了!Vue为我们提供了注册全局组件的方法:

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

这样是省去了组件引入和注册的步骤,但是还不够,我们还需要在父组件模板中引用,父子组件之间数据交互依然很麻烦


我依稀记得,那是一个雨后的下午,空气中充斥着泥土的芳香,我百无聊赖地躺在椅子上,鼠标在网页上游曳,突然一个东西闯入我的眼帘,它好像长着倒钩,勾起了我无限的好奇心。那天月挂星稀的时候,我依然在文档里陶醉。

前戏那么多,该到正题了。。。。

官网的介绍很简单:使用基础 Vue 构造器,创建一个“子类”。参数是一个包含组件选项的对象。也就是说他可以接收的对象里面可以包括data,methods等组件属性。那么我们是不是可以利用这一点做一个定制度高的全局组件呢?

那么我们就来搞一个全局model框~~
首先在src目录下创建model文件夹

在index.vue中敲出model的基本样式布局,默认属性配置:

<template>
  <div class="model" v-show="showModel">
    <div class="content">
      <div class="title">{{ title }}</div>
      <div class="operate">
        <div class="cancel" @click="cancelModel" :style="{color: cancelTextColor}">{{ cancelText }}</div>
        <div class="confirm" @click="confirmModel" :style="{color: confirmTextColor,background: confirmBgColor}">{{ confirmText }}</div>
      </div>
    </div>
  </div>
</template>
data () {
    return {
      title: '标题',
      cancelText: '取消',
      confirmText: '确定',
      showModel:true,
      cancelTextColor: '#424141',
      confirmTextColor: '#fff',
      confirmBgColor:'cornflowerblue'
    }
  },
.model {
    position: fixed;
    left: 0;
    right: 0;
    top: 0;
    bottom: 0;
    z-index: 100;
    display: flex;
    justify-content: center;
    align-items: center;
    background-color: rgba(0,0,0,.5);
}
.content {
    width: 300px;
    height: 150px;
    background: #FFFFFF;
    border-radius: 10px;
    overflow: hidden;
    text-align: center;
}
.title {
    font-size: 20px;
    line-height: 100px;
}
.operate {
    height: 50px;
    display: flex;
    font-size: 20px;
    line-height: 50px;
}
.cancel {
    box-sizing: border-box;
    flex: 1;
    border-top: 1px solid #ddd;
}
.confirm {
    flex: 1;
    background: cornflowerblue;
    color: #FFFFFF;
}

下来我们再来搞如何将这个组件注册成全局,在index.js中:

引入index.vue组件,vue依赖

import vue from 'vue'
import model from './index.vue'

使用extend方法创建vue的子类

const modelConstructor = vue.extend(model);

new出子类实例,混入配置对象,并且将该实例挂载到DOM中去。

function showModel (options,callback) {
  const modelDom = new modelConstructor({
    data () {
      return options
    },
    methods:{
      cancelModel () {
        this.remove()
      },
      confirmModel () {
        callback && callback()
        this.remove()
      },
      remove(){
        this.showModel = false
        document.body.removeChild(modelDom.vm.$el)
      }
    }
  })
  modelDom.vm = modelDom.$mount()
  console.log(modelDom.vm)
  document.body.appendChild(modelDom.vm.$el)
}

将初始化函数挂载到Vue原型链上。

function initModel () {
  vue.prototype.$showModel = showModel
}

最后,抛出初始化函数

export default initModel

在main.js中进行插件注册:

import initModel from './model/index.js'
Vue.use(initModel)

以上,全局组件就已经写好了,下来我们全局任何地方使用了,比如,在home.vue中:

默认调用:

<div @click='showModel'>显示model框</div>
showModel () {
  this.$showModel()
}

自定义调用(自定义样式,配置回调函数):

this.$showModel({
  showModel:true,
  title:'model标题',
  cancelTextColor:'#96063d',
  confirmTextColor:'#68f609',
  confirmBgColor:'#f9a6a6'
  },()=>{
  console.log(123)
})

OK,that's all,Are you get it?~Bye~

讨论数量: 4

镇楼图有点东西~

4年前

听君一席话胜读十年书!

4年前

大佬牛逼!!!

4年前

我是因为第一张图片来的

4年前

请勿发布不友善或者负能量的内容。与人为善,比聪明更重要!