使用Vue.extend封装组件

6,724 阅读1分钟

既然要使用Vue.extend()封装组件,那这玩意儿到底是什么呢?我们且来看官方解释

官方眼里的Vue.extend()

1.参数:

{Object} options

2.用法:

使用基础 Vue 构造器,创建一个“子类”。参数是一个包含组件选项的对象。

data 选项是特例,需要注意 - 在 Vue.extend() 中它必须是函数

<div id="mount-point"></div>

// 创建构造器
var Profile = Vue.extend({
  template: '<p>{{firstName}} {{lastName}} aka {{alias}}</p>',
  data: function () {
    return {
      firstName: 'Walter',
      lastName: 'White',
      alias: 'Heisenberg'
    }
  }
})
// 创建 Profile 实例,并挂载到一个元素上。
new Profile().$mount('#mount-point')
结果如下:

<p>Walter White aka Heisenberg</p>

在下眼里的Vue.extend()

1.且听分解

按照目前的使用情况来讲,它一般用来封装通用(公共)的通知组件,类似ElementUI的Message提示组件等。

2.使用方式

它的使用方式与message组件是不一样的,它是函数式调用(eg:this.$message('test')),类似的组件还有alert提示组件等通用的函数式组件,实现方法与此类似。

3.需要用到的vue的api

const Message = Vue.extend(message) // 使用基础 Vue 构造器,创建一个“子类”
const _Message = new Message({}) // 实例化组件
let vm = _Message.$mount() // 挂载, vm 就是组件里的this

4.使用场景(实例)

此处以Message消息提示组件的封装为例, 源码src文件地址 (内含Message消息提示组件和MessageBox弹框的封装)

1)效果图

1620179434125.gif

2) 代码实现

文件目录展示

![4PY160WO1{$`@132V(VTIX (1).png

// index.js
/* eslint-disable no-mixed-operators */
import Vue from 'vue';
// 导入的message对象为message.vue的配置项
import message from './Message';
// 将组件message.vue的配置项,作为Message类(VUe类,Vue构造器)的默认配置项,
const Message = Vue.extend(message);// 使用基础 Vue 构造器,创建一个“子类”

const vmArr = [];
function $message(opts) {
  // 接收参数,传递给message类,覆盖默认值  比如:提示文字/自动关闭时间/主题颜色
  // eslint-disable-next-line no-underscore-dangle
  const _message = new Message({
    data() {
      return {
        msg: opts.message || '默认提示',
        type: opts.type,
        isVisible: false,
        // eslint-disable-next-line no-mixed-operators
        top: `${vmArr.length * 68 + 20}px`,
      };
    },
    methods: {
      show() {
        this.isVisible = true;
        vmArr.push(this);
      },
      hide() {
        this.isVisible = false;
        vmArr.shift();
        vmArr.forEach((item, index) => {
          // eslint-disable-next-line no-param-reassign
          item.top = `${index * 68 + 20}px`;
        });
      },
    },
    mounted() {
      this.show();
      setTimeout(() => {
        this.hide();
      }, 3000);
    },
  });// 实例化组件
  // 模板编译到实例的$el属性
  _message.$mount();
  // 手动挂载到指定节点body
  document.body.appendChild(_message.$el);
}

export default {
  // eslint-disable-next-line no-shadow
  install(Vue) {
    // eslint-disable-next-line no-param-reassign
    Vue.prototype.$message = $message;
  },
};
// Message.vue
<template>
  <transition name="fade">
    <div
      v-if="isVisible"
      class="message"
      :style="{top: top}"
      :class="type"
    >
      <svg v-if="type === 'success'" t="1619519648259" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2605" width="14" height="14"><path d="M0 512a512 512 0 1 0 1024 0A512 512 0 1 0 0 512z" fill="#67c23a" p-id="2606" data-spm-anchor-id="a313x.7781069.0.i0" class=""></path><path d="M439.012 766.976a53.532 53.532 0 0 1-61.44 0.683 55.41 55.41 0 0 1-14.678-14.223L181.248 548.41a36.238 36.238 0 0 1 51.2-51.2l172.146 152.12 397.938-372.28a35.271 35.271 0 0 1 49.891 49.835L447.943 759.24a55.182 55.182 0 0 1-8.931 7.737z" fill="#ffffff" p-id="2607" data-spm-anchor-id="a313x.7781069.0.i1" class="selected"></path></svg>
      <svg v-if="type === 'info'" t="1619520503387" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7563" width="14" height="14"><path d="M511.8464 0.4608C229.888 0.4608 0.6144 229.9392 0.6144 512.2048c0 282.2656 229.2736 511.744 511.232 511.744 282.0096 0 511.232-229.4784 511.232-511.744 0-282.2656-229.2224-511.744-511.232-511.744z m79.872 699.648c-38.2976 57.5488-77.4656 102.3488-143.7696 102.3488-44.6976-7.168-63.8976-39.9872-53.504-72.7552l84.6848-281.4976a13.4144 13.4144 0 0 0-7.9872-16.7424c-6.4-2.4064-18.432 5.5808-29.5936 17.5616l-50.2784 63.1808c-1.6384-10.3936 0-27.1872 0-34.4064 38.2976-57.5488 102.1952-103.936 144.5376-103.936 40.7552 3.9936 59.904 36.7616 52.736 72.7552l-85.504 283.0848c-0.768 6.4 2.4576 12.8 8.0384 15.1552 6.3488 2.4064 19.1488-5.5808 30.3616-17.5616l51.0976-61.5936c1.5872 9.6256-0.8192 28.0064-0.8192 34.4064zM580.608 332.288c-32.768 0-59.0848-24.0128-59.0848-58.368 0-35.1744 26.3168-58.368 59.0848-58.368 32.768 0 59.136 23.9616 59.136 58.368 0 35.1744-26.368 58.368-59.136 58.368z" p-id="7564" data-spm-anchor-id="a313x.7781069.0.i14" class="selected" fill="#909399"></path></svg>
      {{msg}}
    </div>
  </transition>
</template>

<script>
export default {
  name: 'Message',
};
</script>

<style>
.message {
  box-sizing: border-box;
  width: 380px;
  text-indent: 20px;
  line-height: 48px;
  font-size: 14px;
  border: 1px solid;
  border-radius: 4px;
  position: fixed;
  z-index: 99;
  top: 20px;
  left: 50%;
  transform: translate(-50%);
  transition: all .4s;
}
.success {
  color: #67c23a;
  border-color: #e1f3d8;
  background-color: #f0f9eb;
}
.info {
  color: #909399;
  border-color: #ebeef5;
  background-color: #edf2fc;
}
.message > .icon {
  margin-right: 10px;
  transform: translateY(2px);
}
.fade-enter,.fade-leave-to {
  opacity: 0;
  transform: translate(-50%, -68px);
}
.fade-enter-to,.fade-leave {
  opacity: 1;
  transform: translate(-50%);
}
.fade-enter-active,.fade-leave-active {
  transition: all .4s;
}
</style>
//main.js
/* eslint-disable no-new */
import Vue from 'vue';
import App from './App';
import $message from './components/message';

Vue.use($message);

new Vue({
  el: '#app',
  name: 'Root',
  template: '<App/>',
  components: { App },
});

// App.vue
<template>
  <div class="container">
    <button @click="message('success')">成功提示</button>
    <button @click="message('info')">消息提示</button>
  </div>
</template>

<script>
export default {
  name: 'App',
  methods: {
    message(type) {
      this.$message({
        type,
        message: type === 'success' ? '恭喜你,这是一条成功消息' : '这是一条消息提示',
      });
    },
  },
};
</script>

<style>
* {
  margin: 0;
  padding: 0;
  user-select: none;
}
.container{
 text-align: center;
 line-height: 800px;
}
</style>

以上就是使用Vue.extend()将Message提示组件封装成通用组件的全部代码了

特此说明

比起在座各位,在下还只是个超级小白白......还希望各位不吝赐教,毕竟我心里有数,代码是真的写的一般