Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vue.extend #132

Open
TieMuZhen opened this issue Mar 17, 2022 · 0 comments
Open

Vue.extend #132

TieMuZhen opened this issue Mar 17, 2022 · 0 comments
Labels

Comments

@TieMuZhen
Copy link
Owner

一、前言

Vue.extend属于 Vue 的全局 API,在实际业务开发中我们很少使用,因为相比常用的Vue.component写法,使用extend步骤要更加繁琐一些。但是在一些独立组件开发场景中,Vue.extend + $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')来挂载到指定的元素上。

三、动态创建实例

在Vue中,如果我们想要动态地来控制一个组件的显示和隐藏,比如通过点击按钮显示一个对话框或者弹出一条信息。我们通常会提前写好这个组件,然后通过v-if = “show”来控制它的显示隐藏。如下所示:

<div>
  <button @click = "show = !show">弹出</button>
  <span v-if = "show">这是一条通过按钮控制显示隐藏的信息</span>   
</div>

另外还有一种实现方法就是通过Vue.extend来动态地创建实例,在想要进行显示的时候创建实例。在需要隐藏的时候删除这个实例。

1、通过Vue.extend创建构造器,这个构造器用于需要显示是创建实例。

const Constructor = Vue.extend({
    template:` <span>{{message}}</span> `,
    data(){
        return {
            message:'这是一条通过按钮控制显示隐藏的信息'
        }
    }
})

2、需要显示时创建实例

showHandle(){
    const MessageCom = this.MessageCom = new Constructor({
        propsData:{
            show:true
        }
    }).$mount();

    this.$refs.message.appendChild(MessageCom.$el);
}

3、需要隐藏时删除实例

hiddenHandle(){
    this.MessageCom.$el.remove()
    this.MessageCom.$destroy()
    this.MessageCom = null
}

这样的话就同样实现了一个显示,隐藏效果。

四、使用场景

通过上面的分析,我们发现这种操作完全没有必要,相比于通过属性来控制显示和隐藏;创建实例显得更加麻烦。
但是它同样具有一定的使用场景。比如:单元测试 时:

1、单元测试

在进行单元测试时,为了实现在Vue中的测试,我们必须创建一个基于某个组件的实例,然后才能进行测试。
如下所示:

it('可以设置icon.', () => {
    const Constructor = Vue.extend(Button)
    const vm = new Constructor({
    propsData: {
        icon: 'settings'
    }
    }).$mount()
    const useElement = vm.$el.querySelector('use')
    expect(useElement.getAttribute('xlink:href')).to.equal('#i-settings')
    vm.$destroy()
})

2、替代DOM操作

在一些场合下,我们可能需要创建一个div这种,通常的实现方式如下:

let oDiv = document.createElement();
oDiv.innerHTML = 'hello,world';
document.body.appendChild(oDiv);

但是,在Vue中操作DOM是非常不推荐的写法,这时候我们建议使用Vue.extend来实现DOM的操作。

const Constructor = Vue.extend(Toast);
let oDiv = new Constructor();
oDiv.$slots.default = [message];
oDiv.$mount(); //必须使用$mount()进行挂载,否则所有的生命周期的函数都不会执行
document.body.appendChild(oDiv.$el)

参考文献

@TieMuZhen TieMuZhen added the Vue label Mar 17, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant