2016-03-19 18 views
5

Tôi đang cố tạo một plugin đơn giản trong Vue.js để bao bọc plugin vue-resource để theo dõi trạng thái yêu cầu.Ngữ cảnh ràng buộc Vue.js trong plugin?

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; 

Bạn sẽ thấy tôi vượt qua ctx bối cảnh từ Vue gọi để có được quyền truy cập vào nó data giá trị. Tôi đã nhìn thấy với các plugin vue-resource rằng có một cách để tự động ràng buộc điều này thông qua các plugin dơi không thể hoàn toàn có được cú pháp đúng.

Về cơ bản tôi muốn tránh phải vượt qua ngữ cảnh ctx trong mỗi lần, nó chỉ cần có ngữ cảnh phù hợp.

EDIT

Để làm rõ Tôi đang tìm kiếm một giải pháp để vượt qua những bối cảnh thích hợp trong. Trên đây chỉ là loại một ví dụ và tôi không tìm kiếm một giải pháp để theo dõi trạng thái.

Ví dụ: trong plugin vue-resource nếu chúng tôi thực hiện bất kỳ yêu cầu http nào.

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

    console.log(this.var); 
}); 

Ngữ cảnh đã có trong gọi lại. Tôi không cần phải thực hiện một số loại var _this = this để tham gia vào phạm vi xem. Tôi muốn đạt được điều tương tự cho plugin của mình sao cho phù hợp với this chỉ ở đó. Tôi đang cố gắng tìm ra từ plugin vue-resource nhưng có một thời gian khó khăn sau tất cả các mã.

+0

Vì vậy, bạn có thuộc tính 'name' trên thành phần Vue của mình và bạn muốn plugin này cập nhật giá trị đó khi yêu cầu HTTP diễn ra? Tôi nghĩ điều đó mang lại cho bạn một chuỗi trách nhiệm xấu. Bạn có thể tạo một thuộc tính 'State' được gọi là' status' được cập nhật không? Sau đó, bạn có thể biết trạng thái hiện tại bằng cách sử dụng 'this. $ State.status'? Sau đó, các plugin chịu trách nhiệm cho mục đích của nó, và các thành phần vẫn độc lập – Jeff

Trả lời

1

Tôi đã kết thúc việc phân loại này, nó dễ hơn tôi nghĩ.

Nó chỉ là một wrapper phím tắt đơn giản xung quanh $http phương pháp trong vue-router để các cuộc gọi có thể được thực hiện như sau:

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

Hoặc

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

có thể kiểm tra các đoạn mã trên Gihub here

+2

Liên kết đoạn trích tới Github không hoạt động, bạn có thể vui lòng cung cấp đoạn trích ở đây hoặc liên kết mới không? Tôi đã cố gắng tìm ra cách để thực hiện tương tự trong một plugin. giúp đỡ của bạn sẽ được nhiều đánh giá cao. – Donkarnash

3

Mở rộng nhận xét của tôi đến một câu trả lời -

Vì vậy, bạn có một tài sản name trên phần Vue của bạn, và bạn muốn plugin này để cập nhật giá trị như các yêu cầu HTTP tiến triển? Tôi nghĩ điều đó mang lại cho bạn một chuỗi trách nhiệm xấu. Ví dụ Vue của bạn sẽ được yêu cầu có thuộc tính name và plugin của bạn sẽ không độc lập.

Sẽ tốt hơn nếu làm cho plugin xử lý tất cả theo dõi trạng thái. Bạn có thể tạo một tài sản của Nhà nước được gọi là status được cập nhật khi yêu cầu được tiến hành. Sau đó, bạn có thể biết trạng thái hiện tại bằng cách sử dụng this.$state.status. Sau đó, các plugin chịu trách nhiệm về mục đích của nó, và các thành phần còn lại độc lập

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; 
      } 
     } 
    }); 
} 

Sau đó, trong 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> 

Nếu bạn muốn làm mọi thứ theo cách của bạn, tôi nghĩ rằng bạn muốn chỉ cần ràng buộc this để post() mỗi lần từ bên trong thành phần Vue của bạn:

this.$state.post(args){ 

}.bind(this) 

Vì vậy, trong phạm vi chức năng postthis sẽ là Vue của bạn. Tôi nghĩ rằng cách đầu tiên là tốt nhất

Edit -

Các chức năng successCberrorCb đang chạy trong phạm vi của các thành phần Vue, bởi vì bạn đã định nghĩa chúng ở đó. Gọi lại vue-resource trong trường hợp của bạn có phạm vi State vì bạn đã xác định chúng ở đây, điều đó sẽ không thay đổi trừ khi bạn chuyển ngữ cảnh như bạn đã thực hiện.Nhưng điểm ở đây là plugin của bạn không cần phải biết ngữ cảnh của thành phần, giống như vue-resource không bao giờ biết ngữ cảnh của thành phần. Nó chỉ nhận dữ liệu, gửi yêu cầu và chạy gọi lại. Không bao giờ biết gì về thành phần gọi điện.

Vì vậy, trong các chức năng mà bạn gửi cho this.$state.post như callbacks, bạn có thể chỉnh sửa dữ liệu Vue của bạn sử dụng this.var-như bạn sẽ có thể. Trong các cuộc gọi lại bạn gửi đến Vue.http.post từ Tiểu bang của mình, bạn có thể chỉnh sửa các thuộc tính trên đối tượng State - một lần nữa, hành vi mong đợi. Bạn cần thực hiện biến số name hoặc status một phần của State và sau đó tham chiếu nó là this.$state.name từ bên trong thành phần Vue của bạn để kiểm tra trạng thái.

chỉnh sửa 2:

bạn thậm chí có thể có một biến $state.response và vượt qua trong myCustomVar, và sau đó theo dõi $state.response.myCustomVar. Bằng cách đó bạn có thể chuyển qua các biến tùy chỉnh khác nhau trên mỗi yêu cầu và theo dõi chúng một cách độc lập

+0

Tôi nghĩ rằng bạn hiểu lầm. Không có '$ state.status'. Khi gọi 'this. $ State.post (ctx, 'someStateVar' ...' được truyền vào. Trong suốt yêu cầu đó 'ctx [' someStateVar ']' get được cập nhật với trạng thái. Ý tưởng là không phải truyền ' Dù sao, nó chỉ là một ví dụ, điểm là về việc nhận được bối cảnh thích hợp trong đó.Ví dụ, plugin 'vue-resource', bạn chỉ có thể làm' this.func() ' hoặc 'this.var' bên trong các callback' success' và 'error' mà không cần tham chiếu là' var _this = this' bên ngoài phạm vi. Tôi đang cố gắng đạt được điều tương tự. – Rob

+0

Bạn đã có thể gọi 'this. func() 'hoặc' this.var' trong các lời gọi thành công và lỗi của bạn, chúng được viết trong phạm vi thành phần Vue và sau đó được truyền vào, vì vậy chúng vẫn có phạm vi ban đầu. Từ đây, bạn chỉ cần gọi chúng là 'cb() 'hoặc' errorCb() 'Điểm là một plugin không bao giờ cần phải biết ngữ cảnh mà nó đang được gọi. Bạn không nên cập nhật' ctx ['someStateVar'] 'từ một plugin, thay vào đó nó nên là thuộc tính trên plugin. Nếu không, plugin của bạn phụ thuộc vào biến số đó không phải là một ý tưởng hay. Tôi đã chỉnh sửa nhiều hơn ... – Jeff

+0

Đã có biến tùy chỉnh. Tôi đã viết bình luận của tôi sai, nhưng nếu bạn nhìn vào ví dụ, bạn sẽ thấy không có gì là khó mã hóa trong các plugin. Nó chỉ là 'ctx [someVar]'. Một lần nữa '$ http' không ràng buộc nó bằng cách nào đó để có thể thực hiện nó mà không truyền' ctx' hoặc gọi 'bind'. Chỉ cần cố gắng tìm ra cách. – Rob

Các vấn đề liên quan