Vue中Vue.extend()的使用及解析

目录
  • Vue Vue.extend()的使用
    • 应用场景
    • 简单实用
  • 使用Vue.extend()编写vue插件
    • Vue.extend()
    • 如何编程式使用组件呢
    • 具体使用

Vue Vue.extend()的使用

Vue.extend 属于 Vue 的全局 API,在实际业务开发中我们很少使用,因为相比常用的 Vue.component 写法使用 extend 步骤要更加繁琐一些。但是在一些独立组件开发场景中,Vue.extend + $mount 这对组合是我们需要去关注的。

应用场景

在 vue 项目中,初始化的根实例后,所有页面基本上都是通过 router 来管理,组件也是通过 import 来进行局部注册,所以组件的创建不需要去关注,相比 extend 要更省心一点点。但是这样做会有几个缺点:

组件模板都是事先定义好的,如果我要从接口动态渲染组件怎么办?所有内容都是在 #app 下渲染,注册组件都是在当前位置渲染。如果我要实现一个类似于 window.alert() 提示组件要求像调用 JS 函数一样调用它,该怎么办?

这时候,Vue.extend + vm.$mount 组合就派上用场了。

简单实用

基础用法

Vue.extend( options )

  • 参数:{Object} options
  • 用法:使用基础 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>

可以看到,extend 创建的是 Vue 构造器,而不是我们平时常写的组件实例,所以不可以通过 new Vue({ components: testExtend }) 来直接使用,需要通过 new Profile().$mount(’#mount-point’) 来挂载到指定的元素上。

第二种写法

可以在创建实例的时候传入一个元素,生成的组件将会挂载到这个元素上,跟 $mount 差不多。

// 1. 定义一个vue模版
let  tem ={
    template:'{{firstName}} {{lastName}} aka {{alias}}',
    data:function(){
    return{
	    firstName:'Walter',
	    lastName:'White',
	    alias:'Heisenberg'
    }
}
// 2. 调用
const TemConstructor = Vue.extend(tem)
const intance = new TemConstructor({el:"#app"}) // 生成一个实例,并且挂载在 #app 上

使用Vue.extend()编写vue插件

今天,我们使用Vue.extend()编程式的写法来编写一个vue插件,本质是将插件实例挂载到Vue的原型上。然后,就像element-ui的toast组件那样,使用this.$toast()实例方法去调用插件。

Vue.extend()

使用Vue这个基础构造器,构造出一个“子类”,其实就是个构造函数,通过new运算符生成vue实例。具体见官方文档Vue-extend。

如何编程式使用组件呢

比如,我们要实现个弹窗功能。通过编程式导航,我们就不用在模板中写了,可以使用js直接编写唤出弹窗。首先,我们正常的编写弹窗组件。如下:

<template>
  <div class="gulu-toast" :class="toastClasses">
    <div class="toast" ref="toast">
      <div class="message">
        <slot v-if="!enableHtml"></slot>
        <div v-else v-html="$slots.default[0]"></div>
      </div>
      <div class="line" ref="line"></div>
      <span class="close" v-if="closeButton" @click="onClickClose">
        {{closeButton.text}}
      </span>
    </div>
  </div>
</template>
<script>
  //构造组件的选项
  export default {
    name: 'Toast',
    props: {
      autoClose: {
        type: [Boolean, Number],
        default: 5,
        validator (value) {
          return value === false || typeof value === 'number';
        }
      },
      closeButton: {
        type: Object,
        default () {
          return {
            text: '关闭', callback: undefined
          }
        }
      },
      enableHtml: {
        type: Boolean,
        default: false
      },
      position: {
        type: String,
        default: 'top',
        validator (value) {
          return ['top', 'bottom', 'middle'].indexOf(value) >= 0
        }
      }
    },
    mounted () {
      // 这里是为了防止不断点击,出现多个弹窗
      const toast = document.getElementsByClassName('gulu-toast')[0]
      toast && document.body.removeChild(toast)
      this.updateStyles()
      this.execAutoClose()
    },
    computed: {
      toastClasses () {
        return {
          [`position-${this.position}`]: true
        }
      }
    },
    methods: {
      updateStyles () {
        this.$nextTick(() => {
          this.$refs.line.style.height =
            `${this.$refs.toast.getBoundingClientRect().height}px`
        })
      },
      execAutoClose () {
        if (this.autoClose) {
          setTimeout(() => {
            this.close()
          }, this.autoClose * 1000)
        }
      },
      close () {
        this.$el.remove()
        this.$emit('close')
        this.$destroy()
      },
      onClickClose () {
        this.close()
        if (this.closeButton && typeof this.closeButton.callback === 'function') {
          this.closeButton.callback(this)//this === toast实例
        }
      }
    }
  }
</script>

接下来,就是Vue.extend()出场了。

import Toast from './src/toast.vue';
Toast.install = function (Vue) {
    // 其实就是全局挂载使用
    Vue.prototype.$toast = function (text, props) {
        const ToastMain = Vue.extend(Toast)
        const instance = new ToastMain({
            propsData: props // 这里必须是propsData
        })
        instance.$slots.default = [text] // 插槽内容
        // instance.$mount().$el 该段代码意义为:
        // 文档之外渲染,并且获取该实例的根DOM元素,将其插入到body元素中。
        document.body.appendChild(instance.$mount().$el) 
    }
}
export default Toast

我们在main.js入口文件中,使用Vue.use()安装后,就可以在任何地方使用了~~。

具体使用

this.$toast("关闭吗?", {
        closeButton: {
          text: "关闭",
          callback: () => {
            console.log('已经关闭了');
          },
        },
        autoClose: 12,
        position: 'bottom'
      });

小结:

首先,Vue.extend 获得是一个构造函数,可以通过实例化生成一个 Vue 实例。

实例化时可以向这个实例传入参数,但是需要注意的是 props 的值需要通过 propsData 属性来传递。

还可以通过$slots来自定义插槽内容。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • 如何巧用Vue.extend继承组件实现el-table双击可编辑(不使用v-if、v-else)

    目录 问题描述 效果图 代码思路 代码思路中的三个问题解答 问题一:如何创建一个el-input标签? 问题二三:el-input标签和span标签的来回替换恢复 完整代码 目录结构 用于继承的el-input组件 用于继承的span组件 统一继承并暴露data.js文件 使用继承的three.vue组件 总结 问题描述 有一个简单的表格,产品要求实现双击可编辑 看了一下网上的帖子,大多数都是搞两部分dom,一块是输入框,用于编辑状态填写:另一块是普通标签,用于在不编辑显示状态下呈现单元格文字内

  • Vue.extend 登录注册模态框的实现

    模态框是我们 UI 控件中一个很重要的组件,使用场景有很多种,我们在 Vue 组件中创建模态框组件而用到的一个知识点是利用 Vue.extend 来创建. 文档中的解释是 在最近在做一个常用的类似下面的 登录/注册 业务场景时,利用 Vue.extend 来改善我们的代码,使我们代码逻辑更清晰化. 需求:点击登录或注册出现各自的模态框. 我们对于这种常见的登录注册业务,一般都是分为 Sigin.vue 和 Register.vue 两个组件,然后把两个组件写入 App.vue 组件中,或者是 l

  • Vue.extend实现组件库message组件示例详解

    目录 概述 Vue.extend message 组件配置对象(就是.vue文件) message 生成组件的函数 使用方法 效果图 总结 概述 当我们使用组件库的时候,某些组件并不是直接放到模板当中进行使用,而是通过api的方式调用生成组件并且挂在到我们的页面中,其中最常见的就是message组件,我们在组件库中看到的多数都是api调用的方式生成.记录自己基本实现message组件. Vue.extend 在vue中,要实现通过api方式实现组件的使用,这个aip是必不可少的,因此我们先了解下

  • Vue.extend 编程式插入组件的实现

    前言 日常中我们要使用一个弹框组件的方式通常是先通过Vue.component 全局或是 component 局部注册后,然后在模版中使用.接下来我们尝试编程式的使用组件. 实现 其实步骤很简单 通过 Vue.extend() 创建构造器 通过 Vue.$mount() 挂载到目标元素上 目标实现一个 alert 弹框,确认和取消功能如下图 document.createElement 其实想要插入一个元素,通过 document.createElement 就可以实现,并非一定需要上面两步,但

  • vue使用Vue.extend方法仿写个loading加载中效果实例

    目录 需求描述 效果图 代码实现 第一步,新建loading组件 第二步,新建index.js文件 第三步,在main.js中引入之 第四步,命令式调用 Vue.extend方法的理解 总结 需求描述 本文我们使用vue的extend方法实现一个全屏loading加载效果 通过命令就可以让弹框开启或关闭,比如this.$showDialog()开启,this.$hideDialog()关闭 方法可以传参更改loading中的文字 也可以传参更改loading背景色 当然这里除了文字,背景色什么的

  • 通过vue.extend实现消息提示弹框的方法记录

    前提回顾 在项目开发中我们经常使用的组件注册分为两种,一个是全局注册和另一个是局部注册,假设我们的业务场景是用户在浏览注册页面时,点击页面中的注册按钮后,前端根据用户的注册信息先做一次简单的验证,并根据验证弹出一个对应消息提示弹框 我们拿到这个需求后,便开始着手准备要通过局部注册消息弹框组件的方法来实现这个场景,在通过局部注册消息弹框组件的方法解决完这个需求后,自然是沾沾自喜,紧接着又迎来了一个需求,该需求是用户在点击该注册按钮时,点击几次就要出现几次这个消息弹框,你开始犯了难,并思考难道我要在

  • Vue中 Vue.prototype使用详解

    目录 1. 基本示例 2. 为实例prototype设置作用域 3. 注册和使用全局变量 4. 原型方法的上下文 5. 应用示例 5.1 引入 axios Vue.prototype.Vue.component和Vue.use区别 1.Vue.prototype 2.vue.component 3.Vue.use 我们可能会在很多组件里用到数据/实用工具,但是不想污染全局作用域.这种情况下,可以通过在原型上定义它们使其在每个 Vue 的实例中可用. 1. 基本示例 在main.js中添加一个变量

  • Vue中Vue.use()的原理及基本使用

    目录 前言 1. 举例理解 2. 分析源码 3. 小结 总结 前言 相信很多人在用 Vue 使用别人的组件时,会用到 Vue.use() .例如:Vue.use(VueRouter).Vue.use(MintUI).但是用 axios时,就不需要用 Vue.use(axios),就能直接使用.那这是为什么呐? 因为 axios 没有 install. 1. 举例理解 在新建的项目中创建两个文件:plugins.js use.js: // plugins.js const Plugin1 = {

  • Vue中Vue.extend()的使用及解析

    目录 Vue Vue.extend()的使用 应用场景 简单实用 使用Vue.extend()编写vue插件 Vue.extend() 如何编程式使用组件呢 具体使用 Vue Vue.extend()的使用 Vue.extend 属于 Vue 的全局 API,在实际业务开发中我们很少使用,因为相比常用的 Vue.component 写法使用 extend 步骤要更加繁琐一些.但是在一些独立组件开发场景中,Vue.extend + $mount 这对组合是我们需要去关注的. 应用场景 在 vue

  • 浅谈vue中.vue文件解析流程

    我们平时写的 .vue 文件称为 SFC(Single File Components),本文介绍将 SFC 解析为 descriptor 这一过程在 vue 中是如何执行的. vue 提供了一个 compiler.parseComponent(file, [options]) 方法,来将 .vue 文件解析成一个 descriptor: // an object format describing a single-file component. declare type SFCDescrip

  • vue中view-model双向绑定基础原理解析

    利用Object.defineProperty进行数据劫持 代码如下 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Vue

  • vue中then后的返回值解析

    目录 then后的返回值 获取.then()中的返回值 解决方法如下 调用此方法 then后的返回值 Promise 中处理的是异步调用,异步调用是非阻塞式的,在调用的时候并不知道它什么时候结束,也就不会等到他返回一个有效数据之后再进行下一步处理 可以使用 async 和 await来得到我们的返回值 在vue 中的函数加上async async del(id){       var that=this              var params={               sensor

  • vue中push()和splice()的使用解析

    目录 vue push()和splice()的使用解析 push()使用 splice()使用 使用splice()修改数据,动态渲染dom不更新 vue push()和splice()的使用解析 push()使用 push() 方法可向数组的末尾添加一个或多个元素,并返回新的长度. 注意: 1. 新元素将添加在数组的末尾. 2.此方法改变数组的长度. 数组中添加新元素: var fruits = ["Banana", "Orange", "Apple&q

  • Vue中computed及watch区别实例解析

    计算属性computed : 1. 支持缓存,只有依赖数据发生改变,才会重新进行计算 2. 不支持异步,当computed内有异步操作时无效,无法监听数据的变化 3.computed 属性值会默认走缓存,计算属性是基于它们的响应式依赖进行缓存的,也就是基于data中声明过或者父组件传递的props中的数据通过计算得到的值 4. 如果一个属性是由其他属性计算而来的,这个属性依赖其他属性,是一个多对一或者一对一,一般用computed5.如果computed属性属性值是函数,那么默认会走get方法:

  • Vue中的路由配置项meta使用解析

    目录 Vue路由配置项meta使用 这里简单的举两个例子 Vue路由中的meta问题 meta (元数据) Vue路由配置项meta使用 meta简单来说就是路由元信息 也就是每个路由身上携带的信息. 这里简单的举两个例子 其次还有一个功能就是能够控制公共组件的显示或隐藏 请忽视 keep-alive标签 Vue路由中的meta问题 我们经常会在进入一个页面时判断是否已经登陆,经常会用到路由导航守卫router.beforeEach(to, from, next), 一个两个页面还好,但是多的话

  • VUE中的无限循环代码解析

    代码如下所示: <template> <div id=""> <ul v-for="(item,index) in listaaa"> <li v-if='dealFun(item.cdate,index)'>{{item.cdate}}</li> </ul> </div> </template> <script> export default { name:

随机推荐