为什么在安装期间在组件中未定义此全局本地Vue属性?

时间:2019-01-21 13:51:52

标签: javascript vue.js mocha karma-runner vue-test-utils

我创建了一个自定义Vue插件,该插件会在Vue上创建一个全局属性,如下所示:

function (Vue, options) {
    Vue.$detector = new TranslatableStringDetector();
}

在我的组件中,我在这样的计算属性内使用它:

export default {
    // ...
    computed: {
        decoratedProfileName () {
            return this.$detector.decorate(this.$props.profileName);
        }
    }
    // ...
}

在Karma / Mocha测试中,我将其设置如下:

before(() => {
            const localVue = createLocalVue();
            localVue.use(Vuex);
            localVue.use(TranslationDetector);

            store = new Vuex.Store(cloneDeep(storeDefinition));
            store.commit(SET_USER_DATA, userData);

            wrapper = shallowMount(Avatar, {
                localVue,
                store,
                propsData: {
                    id: 0,
                    inputElPrio: 2,
                    profileName: 'Default'
                }
            });
        });

shallowMount()失败并显示以下错误消息:

[Vue warn]: Error in config.errorHandler: "TypeError: Cannot read property 'decorate' of undefined"
TypeError: Cannot read property 'decorate' of undefined
    at VueComponent.decoratedProfileName (http://localhost:9877/base/index.js?22adbcd7eb33d018f956122e913fca2646b1c60b:132143:35)
    at Watcher.get (http://localhost:9877/base/index.js?22adbcd7eb33d018f956122e913fca2646b1c60b:71415:25)
    at Watcher.evaluate (http://localhost:9877/base/index.js?22adbcd7eb33d018f956122e913fca2646b1c60b:71522:21)
    at VueComponent.computedGetter [as decoratedProfileName] (http://localhost:9877/base/index.js?22adbcd7eb33d018f956122e913fca2646b1c60b:71780:17)
    at Object.get (http://localhost:9877/base/index.js?22adbcd7eb33d018f956122e913fca2646b1c60b:70216:20)
    at Proxy.render (http://localhost:9877/base/index.js?22adbcd7eb33d018f956122e913fca2646b1c60b:180100:43)
    at VueComponent.Vue._render (http://localhost:9877/base/index.js?22adbcd7eb33d018f956122e913fca2646b1c60b:72817:22)
    at VueComponent.updateComponent (http://localhost:9877/base/index.js?22adbcd7eb33d018f956122e913fca2646b1c60b:71061:21)
    at Watcher.get (http://localhost:9877/base/index.js?22adbcd7eb33d018f956122e913fca2646b1c60b:71415:25)
    at new Watcher (http://localhost:9877/base/index.js?22adbcd7eb33d018f956122e913fca2646b1c60b:71404:12)
[Vue warn]: Error in render: "TypeError: Cannot read property 'decorate' of undefined"

found in

---> <Avatar> at src/components/controls/Avatar.vue
       <Root>
TypeError: Cannot read property 'decorate' of undefined
    at VueComponent.decoratedProfileName (http://localhost:9877/base/index.js?22adbcd7eb33d018f956122e913fca2646b1c60b:132143:35)
    at Watcher.get (http://localhost:9877/base/index.js?22adbcd7eb33d018f956122e913fca2646b1c60b:71415:25)
    at Watcher.evaluate (http://localhost:9877/base/index.js?22adbcd7eb33d018f956122e913fca2646b1c60b:71522:21)
    at VueComponent.computedGetter [as decoratedProfileName] (http://localhost:9877/base/index.js?22adbcd7eb33d018f956122e913fca2646b1c60b:71780:17)
    at Object.get (http://localhost:9877/base/index.js?22adbcd7eb33d018f956122e913fca2646b1c60b:70216:20)
    at Proxy.render (http://localhost:9877/base/index.js?22adbcd7eb33d018f956122e913fca2646b1c60b:180100:43)
    at VueComponent.Vue._render (http://localhost:9877/base/index.js?22adbcd7eb33d018f956122e913fca2646b1c60b:72817:22)
    at VueComponent.updateComponent (http://localhost:9877/base/index.js?22adbcd7eb33d018f956122e913fca2646b1c60b:71061:21)
    at Watcher.get (http://localhost:9877/base/index.js?22adbcd7eb33d018f956122e913fca2646b1c60b:71415:25)
    at new Watcher (http://localhost:9877/base/index.js?22adbcd7eb33d018f956122e913fca2646b1c60b:71404:12)

这怎么可能?使用console.debug()语句(Chrome最近中断了调试),我可以确认localVue.$detector的设置正确。但是在我的组件内部,它不能作为this.$detector使用。在示例中,这导致“未定义”:

export default {
    // ...
    created: function () {
        console.debug(this.$detector);
    }
    // ...
}

2 个答案:

答案 0 :(得分:2)

the Vue.js documentation误导了,我认为“全局”是指对所有组件可用的单个对象。坚持使用文档,我实际上希望拥有一个“实例方法”,该实例确实为所有组件提供了一个属性。这是一个很小但很重要的区别,可以解决问题。我以某种方式尝试过并跳过了该方法,因为其他原因无法解决。安装应如下所示:

import requests

url = 'https://pypi.python.org/packages/source/x/xlrd/xlrd-0.9.4.tar.gz'
target_path = 'xlrd-0.9.4.tar.gz'

response = requests.get(url, stream=True)
if response.status_code == 200:
    with open(target_path, 'wb') as f:
        f.write(response.raw.read())

答案 1 :(得分:0)

据我了解,由于this引用了父对象,所以在生命周期挂钩中使用lambda函数(匿名函数)将无法工作。

改为使用function() { /*your code*/ }