Close read Vue official documentation series 🎉


Why?

By binding properties or methods to the prototype object of Vue constructor, the global sharing and reuse of data and functions is realized.

Contrast modular code reuse

The require/import approach is more verbose, but produces a clearer list of dependencies and is more maintainable for large, collaborative applications. Extending the prototype is easier and more flexible to use. You can get the properties of these extension members directly from the component instance’s this. For example, this.$foo(), and the extended member methods can also use context objects to get resources on the currently bound component instance, such as props, datas, datas, datas, attrs, $options, computed properties, and other methods.

This convenience, of course, comes at the expense of explicit expression.

Vue.prototype.$http = axios;
Copy the code

Without a clear understanding of the mechanism behind this, it can be confusing to know where the $HTTP method came from.

How?

To avoid overwriting the same names as props, data, methods, calculation properties, etc., of the component instance itself, members of the prototype extension should have their names identified with a specific prefix for scope isolation. For example, $or ω.

To better manage “property on instance”, we should use it as a “plugin”.

alternative

In applications without a modular system (such as Webpack or Browserify), there is a pattern that is common to any jS-heavy front-end application: a global App object.


var App = Object.freeze({
  name: 'My App'.version: '2.1.4'.helpers: {
    // This is the '$reverseText' method we've seen before
    // a pure version of the function
    reverseText: function (text) {
      return text
        .split(' ')
        .reverse()
        .join(' ')}}})Copy the code

Using object.freeze () to freeze an Object prevents it from being modified in the future. The effect is similar to that of an immutable constant defined by const.

Best practices in TS

First, the Vue type declaration file is modified to add new instance type declarations to its constructors using TypeScript’s Module augmentation mechanism.

// types/shims-vue.d.ts
import {$f, $filters} from './filters.ts';
declare module 'vue/types/vue' {
     interface Vue {
        $filter: typeof $filters,
        $f:typeof $f
     }
}
Copy the code

We can then make a plug-in to implement the properties and methods to be extended:

//filter.ts
export const $filters = {
    toUpperCase(v){
        returnv.toUpperCase(); }};export const $f = function (data:any, ... pipeLines) {
    let value = data;
    for(const pipeline of pipeLines) {
       value = pipeline(value);
    }
    return value;
}

export defalut install(Vue){
    Object.defineProperty(Vue.prototype, '$filters', {
        get() {
            return $filters
        }
    });
    Object.defineProperty(Vue.prototype, '$f', {
        get() {
            return $f
        }
    });
}
Copy the code

Finally, use plug-ins.

import filters from './filters';
Vue.use(filters);
Copy the code

Vue Typescript modules add more declaration types:

declare module 'vue/types/vue'{
    interface Vue {} // Declare the type for the instance member on constructor prototype.
    interface VueConstuctor {} // Declare globally static member types for the Vue constructor.
    interface ComponentOptions <V extends Vue> {} // Declare the type declaration of the component option member.
}
Copy the code