通过 Vue.extend 或“new Vue()”创建组件时的不同行为:如果通过 new Vue 创建,则无法访问视图模型的数据和方法

Posted

技术标签:

【中文标题】通过 Vue.extend 或“new Vue()”创建组件时的不同行为:如果通过 new Vue 创建,则无法访问视图模型的数据和方法【英文标题】:Different behavior when component is created via Vue.extend or via "new Vue()": view-model's data and methods not accessible if created via new Vue 【发布时间】:2017-08-10 02:44:03 【问题描述】:

我有一个简单的组件你好:

<template>
  <div class="hello">
    <h1> msg </h1>
  </div>
</template>

<script>
export default 
  name: 'hello',
  props: 'myprop': String,
  data () 
    return 
      msg: 'Welcome ' + this.myprop
    
  ,
  methods: 
    mymethod: function () 
      return 'hi there'
    
  

</script>

现在,根据组件的创建方式,可以访问方法和数据。最简单的说明方法是通过测试,请阅读测试中的 cmets:

import Vue from 'vue'
import Hello from '@/components/Hello'

describe('Hello.vue', () => 
  it('with Vue Extend', () => 
    const Constructor = Vue.extend(Hello)
    const vm = new Constructor( propsData:  myprop: 'from test via propsdata'  ).$mount()
    // following 3 expections will all SUCCEED
    expect(vm.$el.querySelector('.hello h1').textContent)
      .to.equal('Welcome from test via propsdata')
    expect(vm.myprop).to.equal('from test via propsdata')
    expect(vm.mymethod()).to.equal('hi there')
  )

  it('with new Vue', () => 
    const vm = new Vue(
      
        template: "<div><hello myprop='from template in test'></hello></div>",
        components:  'hello': Hello 
      ).$mount()
    // following expectation SUCCEDS
    expect(vm.$el.querySelector('.hello h1').textContent)
      .to.equal('Welcome from template in test')
    // following TWO expections will FAIL
    expect(vm.mymethod()).to.equal('hi there')
    expect(vm.myprop).to.equal('from template in test')
  )
)

我怎样才能让最后 2 个期望起作用?

谢谢。

【问题讨论】:

【参考方案1】:

您必须先注册您的自定义组件。有两种方法:

全球注册:

// register
Vue.component('hello', 
    template: "<div><hello myprop='from template in test'></hello></div>",
    // ...
);

// create your root instance
const vm = new Vue(
    el: '#root' // assume root eventually renders the 'hello' component
);

Vue.js 文档state that:

一旦注册,组件就可以在实例的模板中用作自定义元素 [...] 请确保组件在 实例化根 Vue 实例之前已注册。

通过本地注册:

// declare
var hello = 
    template: "<div><hello myprop='from template in test'></hello></div>",
    // ...
;

// create your root instance, registering everything in 'components'
const vm = new Vue(
    components:  'hello': Hello 
);

对于您的情况,前者似乎更合适,因为您希望保持 SOC 完整,并且只测试组件的功能。

【讨论】:

对不起,SOC是什么? 您能否以这样的方式提供测试 2 的完整代码,以使最后 2 个期望成功。我没看到:( 以下预期在测试 2 中失败:expect(vm.mymethod()).to.equal('hi there') expect(vm.myprop).to.equal('from template in test' ) 我的意思是,在 TEST 2 中,第一个期望成功,所以我假设组件安装正确,不是吗?仅在测试 2 中,期望 2 和 3 因不明原因而失败。 我真的不知道。您将不得不调试您的代码和/或发布一些错误,以便我们知道什么不起作用。【参考方案2】:

好的,我找到了解决方案。 要确定最后 2 个期望:

expect(vm.$children[0].mymethod()).to.equal('hi there')
expect(vm.$children[0].myprop).to.equal('from template in test')

回想起来,很明显,因为我们在 div 中添加了组件。

【讨论】:

以上是关于通过 Vue.extend 或“new Vue()”创建组件时的不同行为:如果通过 new Vue 创建,则无法访问视图模型的数据和方法的主要内容,如果未能解决你的问题,请参考以下文章

new Vue/Vue.Component/Vue.extend的区别

前端框架vue.js系列:Vue.extendVue.component与new Vue

Vue.extend与Vue.component的区别

Vue.extend

vue2源码-- Vue.extend

vue2源码-- Vue.extend