An overview of

Review formula:

  • Object. Proto === constructor. Prototype
  • Function. Proto == Function. Prototype

so

  • vm.proto === Vue.prototype
  • Vue.proto === Function.prototype
  • Naming Vue instances vm is a particularly Rainy Creek custom that we should continue
  • The VM object encapsulates all operations on the view, including data reads and writes, event binding, and DOM updates
  • The constructor of a VM is Vue, and in ES6 parlances, the class to which the VM belongs is Vue
  • Options are arguments to a new Vue, usually called options or constructors (options after constructors).
  • Take a look at the five question marks in the figure

One: What is in options

Supplementary knowledge: the difference between methods and functions

Additional knowledge: lifecycle and hooks

  • Lifecycle refers to the process of code execution. For Vue, lifecycle means created, Mounted, updated and destroyed, etc
  • A hook is a callback function that performs some logical processing during code execution.
  • In general, the lifecycle is defined in the framework, and you just need to mount your logic on the lifecycle, called hooks.

Introduction to attribute

El – Mount point (substituted with $mount)

  • Type: string | Element

  • Restriction: Only applies when an instance is created with new.

  • Details:

    Provide a DOM element that already exists on the page as the mount target for the Vue instance. It can be a CSS selector or an HTMLElement instance.

    After the instance is mounted, the element can be accessed with vm.$el.

    If this option is present at instantiation time, the instance will start compiling immediately; otherwise, you need to explicitly call vm.$mount() to manually start compiling.

  • Example: Replacement relationship with $mount

/ / el new Vue ({el: '# app', / / in the corresponding HTML id = app render: h = > h (Demo)}) / / mount new Vue ({render: h = > h (Demo)}). $mount (' # app)Copy the code

Data – Internal data (functions are preferred to avoid data sharing between two components)

  • Type: Object | Function

  • Limitation: The component definition accepts function only.

  • Details:

    Vue instance data object. Vue recursively converts data’s property to getters/setters so that data’s property can respond to data changes. The object must be a pure object (with zero or more key/value pairs) : a native object created by the browser API, and the property on the prototype is ignored. In general, data should only be data – it is not recommended to observe objects with stateful behavior.

  • The sample

// object new Vue({data:{n:0}, template:'', The methods of ${}}). The mount (' # app ') / / function new Vue ({data: the function () {/ / : can be omitted the function return {n: 0}}, the template: "', methods:{} }).$mount('#app')Copy the code

Methods (event handlers/common handlers)

  • Type: {[key: string]: Function}

  • Details:

    Methods will be blended into the Vue instance. These methods can be accessed directly from a VM instance or used in an instruction expression. Method this is automatically bound to a Vue instance.

    Note that arrow functions should not be used to define method functions (such as plus: () => this.a++). The reason is that the arrow function is bound to the context of the parent scope, so this will not point to the Vue instance as expected and this.a will be undefined.

  • The sample

var vm = new Vue({
  data: { a: 1 },
  methods: {
    plus: function () {
      this.a++
    }
  }
})
vm.plus()
vm.a // 2
Copy the code

Componens – Use Vue components, case sensitive

  • Type: the Object

  • Details:

    A hash table containing components available for Vue instances.

  • The sample

  • 1. References (preferred)

  • 2. Global definition

  • 3. Combine the first two methods

  • 4. The file name should be all lowercase and the first letter of the component should be uppercase

Four hook

  • Created – Instances appear in memory
  • Mounted – The instance appears in the page
  • Updated – The instance is updated
  • Destroyed – the instance is destroyed from the page and memory (e.g., the child component that clicks on the button is unvisible, which triggers a destroyed view)

Props – External data/properties

  • Pass string (message=”n”)

  • (1) :message=”n” pass this.n; ②:fn=”add” passes this.add function)

  • fame

Advanced properties

Computed – Computes attributes

  • Type: {[key: string] : Function | {get: the Function, the set: the Function}}

  • Details:

    The calculated properties will be mixed into the Vue instance. The This context of all getters and setters is automatically bound to Vue instances.

    Note that if you use the arrow function for a calculated property, this does not point to an instance of the component, but you can still access the instance as the first argument to the function.

    The result of the evaluated property is cached, except for recalculation of dependent responsive property changes. Note that if a dependency (such as a non-reactive property) is outside the instance scope, the calculated property is not updated.

computed: {
  aDouble: vm => vm.a * 2
}
Copy the code
  • Characteristics of the

    • I don’t need parentheses

      When computed is used in the template, write the method name directly without parentheses

    • Caches based on whether dependencies change (as opposed to methods)

      As long as the Message has not changed, multiple visits to the reversedMessage evaluating properties will immediately return the previous result without having to execute the function again

      Instead of writing the same function in methods, calling the method executes the function again every time it starts rendering again

      The advantage of caching is that if computations have A performance-expensive A, then A lot of computations need to be done, and then other computed attributes depend on A. If there were no caching, you’d have to execute A’s getter multiple times.

  • Example 1

import Vue from "vue/dist/vue.js";

Vue.config.productionTip = false;

new Vue({
  data: {
    user: {
      email: "[email protected]",
      nickname: "方方",
      phone: "13812312312"
    }
  },
  computed: {
    displayName: {
      get() {
        const user = this.user;
        return user.nickname || user.email || user.phone;
      },
      set(value) {
        console.log(value);
        this.user.nickname = value;
      }
    }
  },
  // DRY don't repeat yourself
  // 不如用 computed 来计算 displayName
  template: `
    <div>
      {{displayName}}
      <div>
      {{displayName}}
      <button @click="add">set</button>
      </div>
    </div>
  `,
  methods: {
    add() {
      console.log("add");
      this.displayName = "圆圆";
    }
  }
}).$mount("#app");

Copy the code
  • Example 2
    • Men and women are not screened by computed tomography
Import Vue from "Vue /dist/ Vue. Js "; Vue.config.productionTip = false; let id = 0; const createUser = (name, gender) => { id += 1; return { id: id, name: name, gender: gender }; }; new Vue({ data() { return { users: [createUser (" all ", "male"), createUser (" yuan yuan ", "female"), createUser (" small new ", "male"), createUser (" little kwai ", "female")], displayUsers: []}; }, created() {// initialize this.displayUsers = this.users; }, methods: {showMale() {this.displayUsers = this.users.filter(u => u.gender === "male "); }, showFemale() {this.displayUsers = this.users.filter(u => u.gender === "female "); }, showAll() { this.displayUsers = this.users; } }, template: <div> <div> < button@click ="showAll"> all </ button@click ="showMale"> male </ button@click ="showMale"> male </ button@click ="showAll" Female @ click = "showFemale" > < / button > < / div > < ul > < li v - for = "(u, index) in displayUsers" : the key = "index" > {{u.n ame}} - {{u.gender}}</li> </ul> </div> ` }).$mount("#app");Copy the code
  • Screening men and women by computed tomography
Import Vue from "Vue /dist/ Vue. Js "; Vue.config.productionTip = false; let id = 0; const createUser = (name, gender) => { id += 1; return { id: id, name: name, gender: gender }; }; new Vue({ data() { return { users: [createUser (" all ", "male"), createUser (" yuan yuan ", "female"), createUser (" small new ", "male"), createUser (" little kwai ", "female")], gender: ""}; }, computed: {displayUsers() {const hash = {male: "male ", female:" female "}; const { users, gender } = this; If (gender === "") {return users; } else if (typeof gender === "string") { return users.filter(u => u.gender === hash[gender]); } else {throw new Error(" Gender is an unexpected value "); } } }, methods: { setGender(string) { this.gender = string; } }, template: '<div> <div> < button@click ="setGender(')"> All </ button@click ="setGender('male')"> male </ button@click ="setGender('male')" @ click = "setGender (' female ')" > women < / button > < / div > < ul > < li v - for = "(u, index) in displayUsers" : the key = "index" > {{u.n ame}} - {{u.g ender}} < / li > / / v - for loop < / ul > < / div > `}) $mount (" # app ");Copy the code

Watch – monitor/listen

  • Type: {[key: string] : string | Function | Object | Array}

  • Details:

    An object whose key is the expression to observe and whose value is the corresponding callback function. The value can also be a method name, or an object that contains options. The Vue instance will call $watch() at instantiation time, iterating through each property of the Watch object.

This approach is most useful when asynchronous or expensive operations need to be performed when data changes.

var vm = new Vue({
  data: {
    a: 1,
    b: 2,
    obj: {
        x:"kiki",
    } 
  },
  watch: {
    a: function (val, oldVal) {
      console.log('new: %s, old: %s', val, oldVal)
    }
  }
})
Copy the code
  • Characteristics of the
    • Whenever data changes, the function is executed

      Note that the update is asynchronous at this point

    • What is change?

      Simple types look at values, complex types look at addresses (essentially the “===” rule)

  • Example 1
Import Vue from "Vue /dist/ Vue. Js "; Vue.config.productionTip = false; New Vue({data: {n: 0, history: [], inUndoMode: false}, watch: {n: Function (newValue, oldValue) {function(newValue, oldValue) {function(newValue, oldValue) {console.log(this.inundomode); if (! this.inUndoMode) { this.history.push({ from: oldValue, to: newValue }); }}}, // Better to use computed displayName template: ` <div> {{n}} <hr /> <button @click="add1">+1</button> <button @click="add2">+2</button> <button @ click = "minus1" > 1 < / button > < button @ click = "minus2" > 2 < / button > < hr / > < button @ click = "undo" > cancel < / button > < hr / > {{history}} </div> `, methods: { add1() { this.n += 1; }, add2() { this.n += 2; }, minus1() { this.n -= 1; }, minus2() { this.n -= 2; }, undo() { const last = this.history.pop(); this.inUndoMode = true; console.log("ha" + this.inUndoMode); const old = last.from; this.n = old; $nextTick(() => {this.inundomode = false; }); } } }).$mount("#app");Copy the code
  • Example 2: Using watch to simulate computed, silly.

    Handler and immediate need to be added because watch does not listen on the process from scratch by default

Deep meaning

Add the following code to the template, watch section

template:` <div> <button @click = "a += 1">a+1</button> <button @click = "obj.x += 1">obj.x + 'hi'</button> </div> `, Watch: {(b) {the console. The log (changed "b")}, obj () {the console. The log (: "obj changed")}, "obj. A" : the function () {the console. The log (" obj. A changed ")}}Copy the code

If you change obj. A, the console will type “obj has changed “instead of “obj has changed”, because the address of obj has not changed, only the value of a has changed, and then add deep:true:

Obj (){handler(){console.log(:"obj changed ")} deep:true}Copy the code

If you change obj. A again, the console will type “OBj has changed” and listen whenever the object’s properties change, no matter how deep the nesting.

Deep is used to determine if obJ is looking deep when listening.

Watch is asynchronous. How do YOU perform delayed callbacks in Vue

Vue. NextTick ([callback, the context]) parameters: {Function}[callback] {Object}[context] vm. MSG = 'Hello' Vue.Copy the code

The complete syntax of watch

  • Grammar a
var vm = new Vue({ data: { a: 1, b: 2, c: 3, d: 4, e: { f: { g: 5 } } }, watch: { a: Function (val, oldVal) {console.log('new: %s, old: %s', val, oldVal)}, Handler: function (val, oldVal) {handler: function (val, oldVal) {/*... */}, deep: true}, // This callback will be called immediately after listening starts d: {handler: 'someMethod', immediate: true}, // You can pass in an array of callbacks and they will be called one by one e: [ 'handle1', function handle2 (val, oldVal) { /* ... */ }, { handler: function handle3 (val, oldVal) { /* ... */ }, /* ... */ } ], // watch vm.e.f's value: {g: 5} 'e.f': function (val, oldVal) { /* ... */ } } }) vm.a = 2 // => new: 2, old: 1Copy the code
  • Grammar two
vm.$watch('xxx',function(){... },{deep:... ,immediate:... })Copy the code
  • Note that you should not use arrow functions to define watcher functions (e.gsearchQuery: newValue => this.updateAutocomplete(newValue)). The reason is that the arrow function is bound to the context of the parent scope, so this will not point to the Vue instance as expected,this.updateAutocompleteWill be undefined. (The arrow function does not contain this, so if you use this in an arrow function, you can only refer to window or global)

The difference between computed and Watch

  • Computed is a calculated attribute, and watch is a listener

  • Computed is used to calculate a value:

    • 1. No parentheses are required. You can use it as a property
    • 2. The cache is automatically cached based on dependencies. If the dependency does not change, computed values are not recalculated
  • Watch is used to listen. When the monitored data changes, a function is executed with two options:

    • Immediate, which indicates whether the function is executed on the first rendering
    • Deep, which controls whether to listen for changes in the properties of the object (otherwise, if the value of a in obj changes, watch defaults to obj)
  • Watch allows us to:

    • 1. Perform asynchronous operations (accessing an API),

    • 2. Limit how often we perform this operation,

    • 3. And before we get the final result, set the intermediate state,

      These computations can’t do that

  • Conclusion:

    If a piece of data depends on other data, design it for computed

    If you need to do something about a data change, use Watch to observe the data change

Directives and instructions

  • Type: the Object

  • Details:

    Hash table containing instructions available for Vue instance.

  • Declare a global directive global means that this directive can be used in any component

Vue.directive('x',{
  inserted: function (el) {
    el.addEventListener('click',()=>{
      console.log('x')
    })
  }
})
Copy the code

For example, if the instance is defined in main.js and refers to another component, then all other components can use the V-x directive. V minus x is added to whatever element is el. Inserted Indicates that a click event is added to el after the element is inserted into the DOM.

  • Declare a local directive
new Vue({ ... , directives:{ 'x':{ inserted: function(el) { el.addEventListener("click", () => { console.log("x"); }); } }, 'y':directiveOptions } })Copy the code

Declare in the directives option of an instance or component, using the Caching option, more than one directive can be declared. The V-X directive can only be used in this component, not anywhere else, including the component it references.

directiveOptions

DirectiveOptions has five function properties:

  • bind(el,info,vnode,oldVnode): called only once, the first time a directive is bound to an element. This is where you can perform one-time initialization Settings. (similar to created)
  • [Insert]: called when the bound element is inserted into the parent node (the parent node is guaranteed to exist, but not necessarily inserted into the document). (similar to mounted)
  • Update (as above): is called when the component’s VNode is updated, but may occur before its child VNodes are updated. The value of the instruction may or may not have changed. But you can ignore unnecessary template updates by comparing the values before and after the update. (similar to the updated)
  • componentUpdated: invoked after the VNode of the component where the directive resides and its child VNodes are all updated.
  • Unbind (arguments as above): called only once, when directives are unbound from elements. (similar to destroyed)

The first two and the last are more commonly used.

The four arguments in the function property:
  • El: The element bound by the directive that can be used to manipulate the DOM directly.

  • Info: an object containing the following properties:

    • name: Indicates the command name, excluding the V – prefix.
    • value: The binding value of the directive, for example:v-my-directive="1 + 1", the binding value is 2.
    • oldValue: The value preceding the instruction binding, only inupdatecomponentUpdatedHooks are available. Available regardless of whether the value changes.
    • expression: Command expression in the form of a string. For example,v-my-directive="1 + 1"Where, the expression is"1 + 1".
    • arg: Optional parameter passed to the instruction. For example,v-my-directive:fooWhere, the parameter is"foo".
    • modifiers: an object that contains modifiers. Such as:v-my-directive.foo.bar, the modifier object is{ foo: true, bar: true }.
  • Vnode: virtual node generated by Vue compilation.

  • OldVnode: Last virtual node, available only in update and componentUpdated hooks.

Implement v-ON yourself

import Vue from "vue/dist/vue.js"; Import App from "./ app.vue "; Vue.config.productionTip = false; New Vue({directives: {on2: {// bind can be changed to Inserted Bind (el, info) {el.adDeventListener (info.arg, info.value); }, unbind(el, info) {el.removeEventListener(info.arg, info.value); }}} template: ` < v - on2 button: click = "hi" > me < / button > `, the methods: () {{hi console. The log (" hi "); } } }).$mount("#app");Copy the code

Declare a local directive, on2. When a directive is bound to an element, an event listener is added to the element. The name of the event is not yet known, but needs to be passed by the user. For example, it is a click event, which can be obtained from info.arg. The event handler is obtained from info.value.

It is a good practice to unbind elements at a certain time after they have been monitored for binding events. The event listener is then removed when the element dies.

What the directive does: Reduce duplicate DOM operations

  • Vue instances/components are mainly used for data binding, event listening, and DOM updates
  • The main purpose of the directive is native DOM manipulation
  • Native DOM operations can be encapsulated as Vue instructions
  • If a DOM operation is frequently used or complex, it can be encapsulated as an instruction

Mixins – mix/copy

  • Type: Array < Object >

  • Details:

    The mixins option accepts an array of mixins. These mixins can contain instance options just like normal instance objects, which will be merged into the final options using the same opt-merge logic as vue.extend (). That is, if your mixin contains a Created hook and the created component itself has one, then both functions will be called.

    Mixin hooks are called in incoming order and are called before the component’s own hooks are called.

  • The sample a

var mixin = {
  created: function () { console.log(1) }
}
var vm = new Vue({
  created: function () { console.log(2) },
  mixins: [mixin]
})
// => 1
// => 2
Copy the code

– Example 2

Suppose there are five components on app. vue, each of which has data name,time; The hook created, beforeDestroy, prints a prompt when called and tells the survival time.Copy the code
//APP.vue
<template>
  <div id="app">
    <Child1/>
    <button>x</button>
    <Child2/>
    <button>x</button>
    <Child3/>
    <button>x</button>
    <Child4/>
    <button>x</button>
    <Child5/>
    <button>x</button>
  </div>
</template>

<script>
import Child1 from "./components/Child1.vue";
import Child2 from "./components/Child2.vue";
import Child3 from "./components/Child3.vue";
import Child4 from "./components/Child4.vue";
import Child5 from "./components/Child5.vue";
export default {
  name: "App",
  data() {},
  components: {
    Child1,
    Child2,
    Child3,
    Child4,
    Child5
  }
};
</script>

<style>
#app {
  font-family: "Avenir", Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>
Copy the code
<template> <div>Child1</div> </template> <script> import log from ".. /mixins/log.js"; export default { data() { return { name: "Child1" time: undefined }; }, created() { this.time = new Date(); Console. log(' ${this.name} was born '); }, beforeDestroy() { const now = new Date(); Console. log(' ${this.name} dead, live ${now-this. time} ms'); }}; </script>Copy the code

Control the appearance or death of components by a variable. Click the button, the variable becomes false, the component dies, and the beforeDestroy hook is called.

With the object

Since five components of the options, data created, beforeDestroy is same, repeat too much trouble to write five times. You can then use the Mixins option. Put all the same choices together, in one object. The mixins option is then used to copy the object and merge it with its own properties.

//log.js const log={ data() { return { name: undefined, time: undefined }; }, created() { if (! This.name) {throw new Error(" no name"); } this.time = new Date(); Console. log(' ${this.name} was born '); }, beforeDestroy() {console.log(' ${this.name} dead, live ${new Date() - this.time} ms'); } } export default logCopy the code

The name of each component is different, so define undefined in the mixins object first and define the name in your own component.

Components that use mixin objects
//Child1.vue <template> <div>Child1</div> </template> <script> import log from ".. /mixins/log.js"; export default { data() { return { name: "Child1" }; }, mixins: [log]//name will automatically merge}; </script>Copy the code

All the five components need to do is import mixins, use mixins in the mixins option, and this component has all the properties of mixins, that is, copy the properties of mixins.

Smart merger

When components and mixins have options with the same name, those options are “merged” in the appropriate way.

In this example, both the mixin object and the component have a name attribute, and the result is that the name in the component’s own options takes precedence.

The hook function of the same name will be merged into an array, so both will be called. In addition, hooks mixed in with objects are called before the component’s own hooks.

What instructions do: Reduce repetition

  • Directives are used to reduce duplication of DOM operations
  • Mixins reduce duplication of data,methods, and hooks

Extends – Inheritance (rarely used)

  • Type: Object | Function

  • Details:

    Allows you to declare extensions to another component (which could be a simple option object or constructor) without using vue.extend. This is mainly for the convenience of extending single-file components.

    This is similar to mixins.

  • The sample

import Vue from "vue"; const myVue=Vue.extend({ data() { return { name: undefined, time: undefined }; }, created() { if (! This.name) {throw new Error(" no name"); } this.time = new Date(); Console. log(' ${this.name} was born '); }, beforeDestroy() {console.log(' ${this.name} dead, live ${new Date() - this.time} ms'); } }) export default myVueCopy the code

Using vue.extend’s base-based Vue constructor, create a “subclass” of myVue. We can then use new myVue() vue.extend () and mixins, for example:

Import Vue from "Vue "; import log from "./mixins/log.js"; const myVue=Vue.extend({ mixins:[log] }) export default myVueCopy the code

In the component:

//Child1.vue
<template>
  <div>Child1</div>
</template>

<script>
import log from "../mixins/log.js";
export default {
  extends:myVue,
  data() {
    return {
      name: "Child1"
    };
  }
};
</script>
Copy the code

Extends is not an array because you can only inherit from one

conclusion

Use mixins when you can. Add a mixins/extends option because it’s also a first entry.

Unless you have a lot of mixins and don’t want to write them all. Just write this many mixins all at once inside vue.extend ({}) and just extends. But it’s also rare

Provide & Inject – Provide and inject

  • Type:

    Dojo.provide: Object | () = > Object

    Inject: Array < string > | {[key: string] : string | Symbol | Object}

  • Details:

    This pair of options needs to be used together to allow an ancestor component to inject a dependency into all of its descendants, regardless of how deep the component hierarchy is, and remain in effect for as long as its upstream and downstream relationships are established. If you’re familiar with React, this is very similar to the context features of React.

    The provide option should be an object or a function that returns an object. This object contains properties that can be injected into its descendants. You can use ES2015 Symbols as keys in this object, but this only works if Symbol and reflect.ownKeys are natively supported.

    • The Inject option should be:

      • An array of strings, or
      • An object whose key is the local binding name and value is:
        • Search for the key (string or Symbol) used in the available injection content, or
        • An object of which:
          • fromProperty is the key (string or Symbol) to search for in the available injection content
          • defaultProperty is the value used in the degraded case

Tip: Provide and Inject binding are not responsive. This is intentional. However, if you pass in a listening object, the object’s property is still responsive.

  • The sample
    • demand

      One-touch skin: Click on a button and the color of the button and text changes throughout the page.

    • structure

      We use a three-tier nested component.

      The top layer is app.vue, which contains five Child components.

      The second layer is child1.vue (2/3/4/5), which contains a text Child1, and a color switch component.

      The third layer is ChangethemeButton.vue, which has only one “skin” button.

// app.vue // Switch colors by changing the class name. // There is a themeName in data, which is blue by default. // When red, use CSS styles to make it red. <template> <div :class="`app theme-${themeName}`"> <Child1/> <button>x</button> <Child2/> <button>x</button> <Child3/> <button>x</button> <Child4/> <button>x</button> <Child5/> <button>x</button> </div> </template> <script> import Child1 from "./components/Child1.vue"; import Child2 from "./components/Child2.vue"; import Child3 from "./components/Child3.vue"; import Child4 from "./components/Child4.vue"; import Child5 from "./components/Child5.vue"; export default { name: "App", data() { return { themeName: "blue", // 'red' fontSize: "normal" // 'big' | 'small' }; }, components: { Child1, Child2, Child3, Child4, Child5 } }; </script> <style> .app { font-family: "Avenir", Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px; } .app.theme-blue button { background: blue; color: white; } .app.theme-blue { color: darkblue; } .app.theme-red button { background: red; color: white; } .app.theme-red { color: darkred; } </style>Copy the code
Vue <template> <div>Child 1 <change-theme-button/> </div> </template> <script> import ChangeThemeButton from "./ changethemebutton.vue "; export default { components: { ChangeThemeButton } }; </script>Copy the code
// Changethemebutton. vue <template> <div> <button> </button> </div> </template>Copy the code

We need to change a data of the topmost component in the third component. You need to use provide, which provides the data needed in the uppermost component. Namely themeName

//App.vue <script> import Child1 from "./components/Child1.vue"; import Child2 from "./components/Child2.vue"; import Child3 from "./components/Child3.vue"; import Child4 from "./components/Child4.vue"; import Child5 from "./components/Child5.vue"; export default { name: "App", provide() { return { themeName: this.themeName, fontSizeNmae: FontSizeName, changeTheme: this. ChangeTheme, // If this doesn't work, refresh codesandBox changeFontSize: this. ChangeFontSize}; }, data() { return { themeName: "blue", // 'red' fontSizeName: "normal" // 'big' | 'small' }; }, methods: { changeTheme() { if (this.themeName === "blue") { this.themeName = "red"; } else { this.themeName = "blue"; } }, changeFontSize(size) { if (["normal", "big", "small"].indexOf(size) === -1) { throw new Error(`wront size: ${size}`); } this.fontSizeName = size; } }, components: { Child1, Child2, Child3, Child4, Child5 } }; </script> <style> .app { font-family: "Avenir", Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px; } .app.theme-blue button { background: blue; color: white; } .app.theme-blue { color: darkblue; } .app.theme-red button { background: red; color: white; } .app.theme-red { color: darkred; } .app.fontSize-normal { font-size: 16px; } .app button { font-size: inherit; } .app.fontSize-small { font-size: 12px; } .app.fontSize-big { font-size: 20px; } </style>Copy the code

Because this.themeName is a string, the themeName supplied is a copy of the original string. That is, if you change themeName elsewhere, the original data will not be affected

So in the button component, after injecting this variable, you cannot click the button to modify this.themename directly.

So what to do?

It doesn’t work in your place, so I (app.vue) write a function in my own body, modify my own data, and then provide this function to you, you inject this function, you can use it.

// changethemebutton. vue <template> <div> < button@click ="changeTheme"> </button> <button @click="changeFontSize('small')"> </button> </button @click="changeFontSize('normal')" </button> </div> </template> ["themeName", "changeTheme", "changeFontSize"] }; </script>Copy the code

It can be seen that the provide/inject option is similar to ancestors planting trees so that future generations enjoy the shade.

In the top of my method, data are provided well, below the descendants who can use, who wants to use inject, into their own body, is this.

Use of data and methods in a wide range.

You cannot pass themeName without passing the changeTheme method. Because the value of themeName was copied to the provide when I provided it, it was different from the original value, so changing the copied value would not affect the original value.

You can also define the data by changing the string to an object and providing a reference. So it is possible to change the original value directly in the button component. But this is not recommended. Easy to control

Summary of advanced attributes