插件中的 Vue.js 绑定上下文?

Posted

技术标签:

【中文标题】插件中的 Vue.js 绑定上下文?【英文标题】:Vue.js binding context in plugin? 【发布时间】:2016-07-06 02:19:02 【问题描述】:

我正在尝试在 Vue.js 中创建一个简单的插件来包装 vue-resource 插件以跟踪请求的状态。

function State() 

State.prototype.post = function (ctx, name, url, data, successCB, errorCB) 
    var options = ;

    if (errorCB) 
        options.error = function (resp) 
            ctx[name] = 'error';

            return errorCB(resp);
        ;
    

    ctx[name] = 'sending';

    ctx.$http.post(url, data, function (res, code, req) 
        ctx[name] = 'sent';

        return successCB(res, code, req);
    , options);
;

function install(Vue) 
    Object.defineProperties(Vue.prototype, 
        $state: 
            get: function () 
                return new State;
                // return Vue.state.bind($vm: this);
            
        
    );


module.exports = install;

您将看到我从调用 Vue 传递了 ctx 上下文以访问它的 data 值。我已经看到 vue-resource 插件有一种方法可以通过插件自动绑定它,但语法不太正确。

基本上我想避免每次都传递ctx 上下文,它应该已经有了正确的上下文。

编辑

为了澄清,我正在寻找一种解决方案来传递正确的上下文。以上只是一个示例,我不是在寻找跟踪状态的解决方案。

例如在 vue-resource 插件中,如果我们发出任何 http 请求。

this.$http.get('/some/url', , function () 
    this.func();

    console.log(this.var);
);

上下文已经存在于回调中。我不需要做某种var _this = this 来进入视图范围。我想为我的插件实现相同的目标,以便正确的this 就在那里。我试图从vue-resource 插件中找出答案,但很难遵循所有代码。

【问题讨论】:

所以你的 Vue 组件上有一个 name 属性,并且你希望这个插件随着 HTTP 请求的进行更新该值?我认为这给了你一个糟糕的责任链。您能否创建一个名为statusState 属性已更新?那么您可以使用this.$state.status 知道当前状态吗?然后插件负责它的用途,组件保持独立 【参考方案1】:

将我的评论扩展到答案 -

所以你的 Vue 组件上有一个 name 属性,并且你希望这个插件随着 HTTP 请求的进行更新该值?我认为这给了你一个糟糕的责任链。您的 Vue 实例需要具有 name 属性,并且您的插件不会是独立的。

最好让插件自己处理所有状态跟踪。您可以创建一个名为 status 的 State 属性,该属性会随着请求的进行而更新。然后您可以使用this.$state.status 了解当前状态。然后插件负责它的用途,组件保持独立

State.prototype.status = "not sent"; 

State.prototype.post = function (url, data, successCB, errorCB) 
    var options = ;

    if (errorCB) 
        options.error = function (resp) 
            this.status = 'error';

            return errorCB(resp);
        ;
    

    this.status = 'sending';

    this.Vue.http.post(url, data, function (res, code, req) 
        this.status = 'sent';

        return successCB(res, code, req);
    , options);
;

function install(Vue) 
    Object.defineProperties(Vue.prototype, 
        $state: 
            get: function () 
                var state = new State;
                state.Vue = Vue;
                return state;
            
        
    );

然后在html中:

<div v-if="$state.status == 'sending'">Sending...</div>
<div v-if="$state.status == 'sent'">Sent!</div>
<div v-if="$state.status == 'error'">Error!</div>

如果您确实想按照自己的方式做事,我认为您只需在 Vue 组件中每次将 this 绑定到 post()

this.$state.post(args)

.bind(this)

所以在post 函数中this 就是你的Vue。我认为第一种方法是最好的

编辑 --

函数 successCberrorCb 已经在 Vue 组件的范围内运行,因为您在那里定义了它们。在您的情况下,vue-resource 回调具有State 的范围,因为您在此处定义了它们,除非您按照您所做的那样传递上下文,否则它不会改变。但这里的重点是你的插件不需要知道组件的上下文,就像vue-resource 永远不知道组件的上下文一样。它只是获取数据、发送请求并运行回调。对调用组件一无所知。

因此,在您作为回调发送到 this.$state.post 的函数中,您可以使用 this.var 编辑您的 Vue 数据 - 您应该能够。在您从您的州发送到Vue.http.post 的回调中,您可以编辑State 对象的属性 - 再次,预期的行为。您需要将 namestatus 变量作为 State 的一部分,然后在 Vue 组件中将其引用为 this.$state.name 以检查状态。

编辑 2:

您甚至可以有一个变量$state.response 并传入myCustomVar,然后跟踪$state.response.myCustomVar。这样您就可以在每个请求中传递不同的自定义变量并独立跟踪它们

【讨论】:

我想你误会了。没有$state.status。当调用 this.$state.post(ctx, 'someStateVar...` 时被传入。在该请求期间,ctx['someStateVar'] 会更新状态。这个想法是不必传递ctx 上下文,它应该就在那里。无论如何,这只是一个例子,重点是在那里获得适当的上下文。例如vue-resource 插件,您可以在successerror 回调中执行this.func()this.var,而无需在范围外引用var _this = this。我正在努力实现同样的目标。 您已经可以在成功和错误回调中调用this.func()this.var。它们是写在 Vue 组件的作用域中然后传入的,所以它们仍然有原来的作用域。从这里,您只需将它们称为cb()errorCb()。关键是插件永远不需要知道它被调用的上下文。你永远不应该从插件更新ctx['someStateVar'],而应该是插件的一个属性。否则,您的插件取决于该变量,这不是一个好主意。我编辑了更多... 已经是自定义变量了。我的评论写错了,但是如果您查看示例,您会发现插件中没有任何硬编码。只是ctx[someVar]$http 再次以某种方式绑定它,因此可以在不传递 ctx 或调用 bind 的情况下进行绑定。只是想弄清楚如何。 这在哪里使用调用上下文? github.com/vuejs/vue-resource/blob/master/src/http/index.js#L81 。在您的编辑示例中,该函数定义在 Vue 组件内部,因此它当然具有正确的上下文。在您的完整代码中,它在State 中定义,因此它具有该上下文。 vue-resource 没有在这里绑定任何东西 这里有一个绑定函数...你可以访问你插件中的变量this.$vm吗? github.com/vuejs/vue-resource/blob/master/src/http/index.js#L81【参考方案2】:

我最终解决了这个问题,比我想象的要容易。

这只是vue-router$http 方法的简单快捷包装,因此可以像这样进行调用:

this.$state.get('/buildings', data, function (resp) 
    this.buildings = resp.data;
, 
    track: 'getBuildingState'
);

或者

this.$state('/buildings', 
    data: data,
    track: 'getBuildingState',
    success: function (resp) 
        this.buildings = resp.data;
    
);

可以查看 Gihub 上的 sn-p here

【讨论】:

到 Github 的 sn-p 链接失效了,能否请您在此处提供 sn-p 或新链接?我一直在试图找出一种在插件中实现相同功能的方法。非常感谢您的帮助。

以上是关于插件中的 Vue.js 绑定上下文?的主要内容,如果未能解决你的问题,请参考以下文章

17/6/18随笔

uni-app使用Vue.js

通过调用Local Method响应Vue.js事件总线时丢失上下文

从自定义 .js 文件访问应用程序上下文以获取语言环境消息

computed

Ninject之旅之八:Ninject插件模型