Vue passes the object Option

1. El:
  • 1) type: string | HTMLElement
  • Function: Determines which DOM object to manage
2. data:
  • (1) type: Object | Function (component of the data must be a Function)
  • ② Function: Data object corresponding to Vue instance
3. The methods:
  • {[key:string]:Function}
  • ② Function: define methods that belong to Vue, which can be called elsewhere or in instructions
4. Watch:
  • 1) type: {[key: string] : the Function | Object}
  • ② Function: listener function, monitoring a data or method changes and the implementation of the side effect

Vue basic syntax

1. Interpolation operation

1-1 Mustache Grammar (double brace)

Not only can you write variables directly, but you can also write simple expressions

<div id="app">
    <! Mustache's syntax allows you to write not just variables directly, but also simple expressions -->
    <h2>{{firstName + " " + lastName}}</h2> // kevin durant
    <h2>{{firstName}} {{lastName}}</h2>     // kevin durant
    <h2>{{count * 2}}</h2>/ / 200</div>
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
  <script>
    const app = new Vue({
      el:"#app".data: {firstName:"kevin".lastName:"durant".count:100}})</script>
Copy the code

1-2, v – once

Render only once, not as data changes. It’s not followed by an expression.

1-3, v – HTML

Identifying HTML tags

  <div id="app">
    <h2 v-html="url"></h2>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
  <script>
    const app = new Vue({
      el:"#app".data: {url:}})</script>
Copy the code

1-4, v – text

V-text is a little bit like Mustache: It’s used to put data in an interface and V-text usually takes a string

<div id="app">
    <h2 v-text="message"></h2>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
  <script>
    const app = new Vue({
      el:"#app".data: {message:"Hello?"}})</script>
Copy the code

But generally not, not flexible enough.

1-5, v – pre

Displays the text as it is, without following the expression

<div id="app">
	<h2>{{message}}</h2>/ / hello<h2 v-pre>{{message}}</h2>  // {{message}}
  </div>
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
  <script>
    const app = new Vue({
      el:"#app".data: {message:"Hello?"}})</script>
Copy the code

1-6, v – cloak

<div id='app' v-cloak></div>The div has the V-cloak attribute before vue parsing. The V-cloak attribute is deleted after vue parsingCopy the code

2. Bind properties

2-1, v – bind

V-bind is used to bind one or more property values, or to pass props to another component to dynamically bind properties, such as image link SRC, website link href, classes, styles, and so on.

v-bind Value
role Dynamically bound properties
abbreviations : (Grammar sugar)
expected any (with argument)
parameter attrOrProp (optional)
    <div id="app">
        <img v-bind:src="imgURL" alt="">
        <a v-bind:href="aHerf">The baidu</a>
        <! -->
        <img :src="imgURL" alt="">
        <a :href="aHerf">The baidu</a>

    </div>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
    <script>
        const app = new Vue({
            el: "#app".data: {
                imgURL: "https://cn.bing.com/th?id=OIP.NaSKiHPRcquisK2EehUI3gHaE8&pid=Api&rs=1".aHerf: "http://www.baidu.com"}})</script>
Copy the code

2-2, bind class

(1) Object syntax

:class=”{class name 1: Boolean, class name 2: Boolean}”

Normally, booleans are not assigned directly, but instead are assigned by variables.

  <div id="app">
    <! -- Dynamically binding class object usage -->
    <! - < h2: class = "{name of the class 1: Boolean, the name of the class 2: Boolean}" > {{message}} < / h2 > -- >
    <h2 :class="{active:isActive}">{{message}}</h2>
    <button @click="change">Click on the color</button>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
  <script>
    const app = new Vue({
      el:"#app".data: {message:"Hello?".active:"active".isActive:true
      },
      methods: {
        change(){
          this.isActive = !this.isActive
        }
      }
    })
  </script>
Copy the code

(2) Array syntax

:class=”[class name 1, class name 2]”; Variables are not quoted. It’s not usually used.

2-3, binding style

Use V-bind :style to bind some CSS inline styles.

When writing CSS property names, for example, font size ① we can use camelCase fontSize ② string form: kebab-case (remember to use single quotation marks) ‘font size’

(1) Object syntax

:style=”{key(attribute):value(attribute)}”

The key of the object is the name of the CSS property and the value of the object is the assigned value. The value can come from a property in data

  <div id="app">
    <! -- Parse as string with single quotes -->
    <h2 :style="{fontSize:'50px'}">{{message}}</h2>
    <! -- without single quotes, variable parsing -->
    <h2 :style="{fontSize:fontSize}">{{message}}</h2>
    <h2 :style="{fontSize:fontSize1 + 'px'}">{{message}}</h2>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
  <script>
    const app = new Vue({
      el:"#app".data: {message:"Hello?".fontSize:'100px'.fontSize1:100}})</script>
Copy the code

(2) Array objects

  <div id="app">
    <h2 :style="[baseStyle1,baseStyle2]">{{message}}</h2>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
  <script>
    const app = new Vue({
      el:"#app".data: {message:"Hello?".baseStyle1: {backgroundColor:'red'.fontSize:'100px'},
        baseStyle2: {backgroundColor:'black'.fontSize:'50px'}}})</script>
Copy the code

3. Compute attributes computed

3-1, the foundation

It’s essentially a property, but it’s written like a function. When naming, try to use the form of attribute name, call is the call name, do not need to add parentheses ()

  <div id="app">
    <! -- Mastache syntax -->
    <h2>{{firstName+ " " + lastName}}</h2>  // Kevin Durant
    <! Method - - - >
    <h2>{{getFullName()}}</h2>              // Kevin Durant
    <! -- Calculate attributes -->
    <h2>{{fullName}}</h2>                   // Kevin Durant
	<! -- no need to add () -->
  </div>
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
  <script>
    const app = new Vue({
      el:"#app".data: {firstName:"Kevin".lastName:"Durant"
      },
      computed: {
        fullName:function(){
          return this.firstName + "" + this.lastName
        }
      },
      methods: {
        getFullName(){
          return this.firstName + "" + this.lastName
        }
      },
    })
  </script>
Copy the code

3-2. Complex operations

  <div id="app">
    <h2>{{totalPrice}}</h2>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
  <script>
    const app = new Vue({
      el:"#app".data: {books:[
          {id:110.name:"JavaScript from the Ground up".price:1},
          {id:111.name:"Java from entry to abandonment".price:2},
          {id:112.name:"Code art".price:3},
          {id:113.name:"Complete Code".price:4}},],computed: {
        totalPrice(){
          let result= 0;
          for (let i = 0; i < this.books.length; i++) {
            result += this.books[i].price;
          }
          return result
        }
      }
    })
  </script>
Copy the code

3-3, cache

Methods and computed seem to do what we do, so why have a computational property? Cause: The calculated property is cached. If it is used multiple times, the calculated property is called only once. Methods are used once and called once, so evaluating properties is relatively better.

3-4. Calculate the setter for the property

Computed properties only have getters by default, but setters can be provided if desired

computed: { 
  fullName: { 
    // getter 
   get: function () { 
     return this.firstName + ' ' + this.lastName 
   },
   // setter 
   set: function (newValue) { 
     var names = newValue.split(' ') 
     this.firstName = names[0] 
     this.lastName = names[names.length - 1]}}}Copy the code

4. Event monitoring

4-1. Introduction to V-ON

project Value
role Bind event listeners
abbreviations @
expected Function, Inline Statement, Object
parameter event

4-2. V-on parameters

When defining a method from methods for @click to call, you need to be aware of parameter issues:

  • ① If the method does not require additional arguments, the () after the method may not be added. Note, however, that if the method itself has an argument, the native event argument is passed in by default
  • If you need to pass in an event, you can pass in an event via $event.
  <div id="app">
    <! -- Event was not added -->
    <button @click="btnClick">Button 1</button> <! -- Event did not pass parameters -->
    <button @click="btnClick()">Button 2</button> <! -- Event did not pass parameters -->
    
    <! The event calls the method to pass the argument. The parentheses are omitted when writing the function, but the function itself needs to pass an argument.
    <button @click="btnClick2(123)">Button 3</button> <! - $123 - >
    <button @click="btnClick2()">Button 4</button> <! -- undefined -->
    <button @click="btnClick2">Button 5</button> <! -- [object MouseEvent] -->
    
    <! Call event (event);
    <button @click="btnClick3($event,123)">Button (6)</button>  <! -- [object MouseEvent]123 -->
  </div>
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
  <script>
    const app = new Vue({
      el:"#app".methods: {btnClick(){
          console.log("Event did not pass parameters");
        },
        btnClick2(value){
          console.log(value);
        },
        btnClick3(event,value){
          console.log(event+value); }}})</script>
Copy the code

4-3, V-ON modifier

The modifier role
.stop Call event. StopPropagation (). To prevent a bubble
.prevent Calls to the event. The preventDefault (). Blocking default behavior
. Or keyCode. KeyAlias The callback is triggered only if the event is triggered from a particular key.
.native Listen for native events on the component root element.
.once Only trigger once
<div id="app">
  <! --1.. stop modifier -->
  <! Stop -->
  <div @click="divClick">
    aaaaaaa  <! -- click aaa to display div -->
    <button @click.stop="btnClick">Button 1</button> <! -- The BTN div bubbles when the button is clicked -->
  </div>
  <! Stop -->
  <div @click="divClick">
    aaaaaaa  <! -- click aaa to display div -->
    <button @click.stop="btnClick">Button 2</button> <! -- Click the button to display BTN -->
  </div>

  <! --2. Use of prevent modifier -->
  <! -- Not used to prevent -->
  <form action="http://www.baidu.com">
    <input type="submit" value="Submit" @click="submitClick"> <! Submit is displayed when you click submit, but quickly jumps to another page -->
  </form>
  <!-- 使用.prevent -->
  <form action="http://www.baidu.com">
    <input type="submit" value="Submit" @click.prevent="submitClick"> <! -- "Submit" is displayed when you click submit, no jump to another page -->
  </form>

  <! --3. Listen for a key cap on a keyboard -->
  <input type="text" @keyup.enter="keyUp"> <! -- Listen for the enter key -->

  <! -- use of the.. once modifier -->
  <button @click.once="btn2Click">Button 3</button> <! -- call once -->
</div>

<script src=".. /js/vue.js"></script>
<script>
  const app = new Vue({
    el: '#app'.data: {
      message: 'Hello.'
    },
    methods: {
      btnClick() {
        console.log("btn");
      },
      divClick() {
        console.log("div");
      },
      submitClick() {
        console.log('submit');
      },
      keyUp() {
        console.log('keyUp');
      },
      btn2Click() {
        console.log('Call once'); }}})</script>
Copy the code

5. Conditions and loops

5-1. Conditional rendering

V-if, V-else -if, and V-else are similar to JavaScript conditional statements like if, else, and else if. Vue’s conditional directives can render or destroy elements or components in the DOM based on the value of an expression

When the condition after v-if is false, the corresponding element and its child elements are not rendered, i.e., no corresponding tags appear in the DOM at all.

<div id="app">
  <p v-if="score>=90">good</p>
  <p v-else-if="score>=80">good</p>
  <p v-else-if="score>=60">Pass the</p>
  <p v-else>Don't pass the</p>
</div>
<script src=".. /js/vue.js"></script>
<script>
  const app = new Vue({
    el: '#app'.data: {
      score: 99}})</script>
Copy the code

5-2, V-if vs V-show

V-if When the condition is false, there is no corresponding element in the DOM at all. V-show When the condition is false, it simply sets the display attribute of the element to None.

Use v-show when you need to slice frequently between show and hide. Use V-if when there is only one switch

5-3, V-for instruction

(1) Go through the number group

(1) Directly traverse item in Arry (2) include index (item,index) in Arry

<div id="app">
  <! --1. No index value (subscript value) is used during traversal -->
  <ul>
    <li v-for="item in names">{{item}}</li>
  </ul>

  <! Select * from index ();
  <ul>
    <li v-for="(item, index) in names">{{index+1}}.{{item}}</li>
  </ul>
</div>

<script src=".. /js/vue.js"></script>
<script>
  const app = new Vue({
    el: '#app'.data: {
      names: ['Durant'.'Kobe'.'Irving'.'Curry']}})</script>
Copy the code

(2) The traversal number group of vue.js

In general, we write the traversal number group in JS code as follows:

let books = [1.2.3];
for (let i = 0; i < books.length; i++) {
  console.log(books[i]); / / 1 2 3
}
Copy the code

There are two simple ways to write it: for(let me in/of books)

// 1. in
for(let i in books){
  console.log(i); / / 0 1 2
  conlose.log(books[i]); / / 1 2 3
  // I is the index value
}
// 2. of
for(let i of books){
  console.log(i); / / 1 2 3
  // I is an array element
  // Write I as item to make it easier to recognize
}
Copy the code

(3) Traverse the object

Number of values obtained:

  • If you just get a value while walking through an object, you get a value
  • If you get two values, you get value, key: (value, key)
  • If we get three values, we get value, key, index.
  • Note: value, key, and index are only code names, even if (key,index,value) is written, the information is (attribute value, attribute name,index number), i.e. key is the attribute value,index is the attribute name, and value is the index number.
<div id="app">
  <! --1. If only one value is obtained, then a value is obtained -->
  <ul>
    <li v-for="item in info">{{item}}</li>
  </ul>


  <! (value, key) -->
  <ul>
    <li v-for="(value, key) in info">{{value}}-{{key}}</li>
  </ul>


  <! Value, key, index (value, key, index) -->
  <ul>
    <li v-for="(value, key, index) in info">{{value}}-{{key}}-{{index}}</li>
  </ul>
</div>

<script src=".. /js/vue.js"></script>
<script>
  const app = new Vue({
    el: '#app'.data: {
      info: {
        name: 'why'.age: 18.height: 1.88}}})</script>
Copy the code

It is recommended that we add a key attribute to the corresponding element or component when using V-for.

A later article will cover the functions of keys in more detail

5-4. Detect array updates

Because Vue is responsive, when data changes, Vue automatically detects data changes and the view updates accordingly. Vue includes a set of methods to watch arrays compile, and using them to change arrays also triggers view updates. The following methods can be used to be responsive

methods role
push() Append data to the end of the array
pop() Deletes the last data in the array
shift() Deletes the first element of the array
unshift() Add elements to the front of the array
splice() Delete elements, insert elements, replace elements
sort() The sorting
reverse() Flip the array

1. Splice ()

// splice deletes elements/inserts elements/replaces elements
// The first argument is the index number, which represents the starting position
var arr = ['a'.'b'.'c'];
// Delete element: The second argument is passed how many elements you want to delete (if not, delete all subsequent elements)
arr.splice(1.1); // ['a','c']
// Insert element: The second argument is passed 0, followed by the element to be inserted
arr.splice(1.0.'d'); // ['a','b','d','c']
// Replace elements: The second argument, indicating how many elements we want to replace, is followed by the previous element
arr.splice(1.1.'d'); // ['a','d','c']
arr.splice(1.1.'d'.'f'); // ['a','d','f','c']
[1] insert 'd','f',' d','f',' d','f',' d','f',' d','f
Copy the code

(2) the sort ()

When.sort() is used alone, there are no arguments. Judge the size of the units digit, you can order from the smallest to the largest; But when the value is multiple digits, it does something different. It compares the first digit, then the second digit… So in the following case the order is 1,13,4,7,77.

var arr1 = [1.4.7.3];
arr1.sort();
console.log(arr1); / /,3,4,7 [1]
var arr2 = [13.1.7.4.77];
arr2.sort();
console.log(arr2); / /,13,4,7,77 [1]
Copy the code

To sort the order from smallest to largest, there are templates like the following:

Arr. Sort (function(a,b){return a-b; / / ascending});

Arr. Sort (function(a,b){return b-a; / / descending});

Note: The parentheses of sort enclose the entire function, so remember to end with a semicolon

var arr1 = [13.1.7.4.77];
arr1.sort(function(a,b){
	returnA - b;/ / ascending
});
console.log(arr1); / /,4,7,13,77 [1]
var arr2 = [13.1.7.4.77];
arr2.sort(function(a,b){
	returnB - a;/ / descending
});
console.log(arr2); / /,13,7,4,1 [77]
Copy the code

6. Form binding

6-1. Basic use of V-Model

The V-model directive is used in Vue to implement bi-directional binding between form elements and data

<div id="app">
  <input type="text" v-model="message">
  {{message}}
</div>

<script src=".. /js/vue.js"></script>
<script>
  const app = new Vue({
    el: '#app'.data: {
      message: 'Hello.'}})</script>
Copy the code

When we input content in the input box, because the V-Model in the input is bound to Message, the input content will be transmitted to Message in real time, and message will change. When a message changes, the DOM changes in response because we use Mustache syntax above to insert the value of a message into the DOM.

Therefore, two-way binding is achieved through v-Model.

Of course, we can also use the V-Model for textarea elements

6-2. V-model principle

The V-Model is a syntactic sugar that essentially contains two operations:

  1. V-bind binds a value attribute
  2. The V-on directive binds the input event to the current element
<input type="text" v-model="message"> {{message}}
Copy the code

Is equal to:

<input type="text" :value="message" @input="message = $event.target.value">>{{message}}
Copy the code

6-3. Other types

(1) the radio

Radio, put the selected things into the information.

In this case, the chosen sex is incorporated into the data

<div id="app">
  <label for="male">
    <input type="radio" id="male" value="Male" v-model="sex">male</label>
  <label for="female">
    <input type="radio" id="female" value="Female" v-model="sex">female</label>
  <h2>The gender you have selected is: {{sex}}</h2>
</div>
<script src=".. /js/vue.js"></script>
<script>
  const app = new Vue({
    el: '#app'.data: {
      sex: ' '}})</script>
Copy the code

V-model is bound to the same variable sex, so it can be mutually exclusive. (This function is equivalent to setting name=”sex” for both radios)

(2) the checkbox

Check boxes are classified into two types: single check box and multiple check boxes. (1) Single check box:

  • V-model is a Boolean value.
  • In this case, the input value does not affect the V-model value.

(2) Multiple check boxes:

  • When multiple checkboxes are selected, the property in the corresponding data is an array because more than one check box can be selected.
  • When one of them is selected, the value of the input is added to the array.
<div id="app">
  <! --1. Checkbox
  <label for="agree">
    <input type="checkbox" id="agree" v-model="isAgree">Agree to a deal</label>
  <h2>Your choice is: {{isAgree}}</h2>
  <button :disabled=! "" isAgree">The next step</button>

  <!--2.checkbox多选框-->
  <input type="checkbox" value="Basketball" v-model="hobbies">basketball<input type="checkbox" value="Football" v-model="hobbies">football<input type="checkbox" value="Table tennis" v-model="hobbies">Table tennis<input type="checkbox" value="Badminton" v-model="hobbies">badminton<h2>Your hobbies are: {{hobbies}}</h2>
</div>

<script src=".. /js/vue.js"></script>
<script>
  const app = new Vue({
    el: '#app'.data: {
      isAgree: false./ / radio buttons
      hobbies: []     // Multi-select box,}})</script>
Copy the code

(3) the select

Uncommon (1) Single option: Only one value can be selected.

  • The V-model binds to a value.
  • When we select one of the options, we assign its corresponding value to mySelect

(2) Multiple selection: Multiple values can be selected. multiple

  • The V-Model binds to an array.
  • When multiple values are selected, the value corresponding to the selected option is added to the array mySelects
  • Multi – select to use CRTL + mouse click
<div id="app">
  <! --1. Choose a -->
  <select name="abc" v-model="fruit">
    <option value=The word "apple">apple</option>
    <option value="Banana">banana</option>
    <option value="Durian">durian</option>
    <option value="Grapes">grapes</option>
  </select>
  <h2>Your choice of fruit is: {{fruit}}</h2>

  <! --2. Select multiple -->
  <select name="abc" v-model="fruits" multiple>
    <option value=The word "apple">apple</option>
    <option value="Banana">banana</option>
    <option value="Durian">durian</option>
    <option value="Grapes">grapes</option>
  </select>
  <h2>Your fruit of choice is {{fruits}}</h2>
</div>

<script src=".. /js/vue.js"></script>
<script>
  const app = new Vue({
    el: '#app'.data: {
      fruit: 'banana'.fruits: []}})</script>
Copy the code

6-4. Value binding

It’s just assigning value dynamically. v-bind:value=””

const app = new Vue({
    el: '#app'.data: {
      num1: 1.num2: 0
    },
    // When num1 and num2 change, the corresponding function is called
    watch: {num1(newvalue){
        console.log(num1 changed);this.num2 = newvalue * 10; // num2 changes, num2(){}
      },
      num2(newvalue){
        console.log(num2 changed); }}Copy the code

6-5. Modifiers

  • Lazy decorator:

By default, v-Model synchronizes input field data in input events by default. In other words, the data in the corresponding data will be automatically changed once the data is changed. The lazy modifier allows data to be updated only if it loses focus or hits enter

  • The number modifier:

By default, whether we enter letters or numbers in the input field is treated as a string. But if we want to deal with numeric types, it’s better to treat the content as a number. The number modifier automatically converts what is entered in the input field to a number type

  • Trim modifier:

If you enter content that has a lot of whitespace at the beginning and end, and you want to remove it, the trim modifier filters the whitespace on the left and right sides of the content

7. Filters

Can be used for some common text formatting. Filters can be used in two places: double curly brace interpolation and V-bind expressions

<div id='app'>{{123 | show}} / / RMB 123.00</div>
<script>
const app = new Vue({
  el:'#app';
  filters:{
    show(price){
      return A '$'+price.toFixed(2)}}})</script>
Copy the code

8, Monitor watch

Listen for changes in the property of a variable. The function name is the property name. Two are newValue, oldValue

8-1 Many ways to write watch

watch:{
    el: function(newThat old){
         console.log(1)},el(newThat old){
         console.log(2)},// Directly observe changes in EL values to perform side effects
    el: {
         immediate: true.handle(new, old){
            console.log(3)},deep: true,},// Write it as an object to facilitate the configuration of multiple parameters
}
Copy the code

Watch can be configured with a flush in addition to immediate and deep. See watchEffect, a fascinating new feature in the Vue Composition API in this article

Stop listening

There is a special API $watch in vue, which is the same as the watch function in Vue Option. It can register the function of watch listener. Of course, its execution function returns a stop function by default, which can be used to cancel the listener

Two, componentized development

1. Know the components

Vue componentization idea

As much as possible, break the page up into small, reusable components. This makes our code easier to organize and manage, and also more extensible.

2. Componentization basis

2-1. Register components

(1) Basic steps of registration

The use of components is divided into three steps: ① Create a component constructor: vue.extend () ② register a component: Vue.component() ③ Use a component. Used within the scope of Vue instances

(2) Initial experience of componentization

<div id="app">
  <! --3. Use components -->
  <my-cpn></my-cpn>
  <div>
    <my-cpn></my-cpn>
  </div>
</div>
<script src=".. /js/vue.js"></script>
<script>
  // 1. Create a component constructor object
  const cpnC = Vue.extend({
    template: ` < div > < h2 > I am a title < / h2 > < p > I'm content, ha ha ha ha < / p > < p > I'm content, ha ha ha ha < / p > < / div > `
  })

  // 2. Register components
  Vue.component('my-cpn', cpnC)

  const app = new Vue({
    el: '#app'.data: {
      message: 'Hello.'}})</script>
Copy the code

(3) Global and local components

Global components, meaning they can be used under multiple Vue instances registered outside of new Vue

<div id="app">
  <cpn></cpn>  
</div>
<div id="app2">
  <cpn></cpn>// It can be used globally, but cannot be used locally because it is not registered</div>
<script src=".. /js/vue.js"></script>
<script>
  // 1. Create a component constructor
  const cpnC = Vue.extend({
    template: '
       

I am the title

I am the content, ha ha ha ha ah

'
}) // 2. Register components // global component, which means it can be used under multiple instances of Vue // Vue.component('cpn', cpnC) const app = new Vue({ el: '#app'.// select * from the local component components: { cpn: cpnC // CPN Specifies the label name of the component used in cpnC}}const app2 = new Vue({ el: '#app2' })
</script> Copy the code

(4) Parent and child components

If component A is registered with component B, component A is A child component of component B. Child components can only be used within the parent component, and child components cannot be used in the instance or elsewhere unless the child component is registered with the instance or globally.

<div id="app">
  <cpn2></cpn2>
  <! When cpn1 is registered only in cpn2, it can only be called in cpn2. It can only be used in cpn2 unless it is registered in vue instance or globally.
  <cpn1></cpn1>
</div>

<script src=".. /js/vue.js"></script>
<script>// 1. Create the first component constructor (child component) const cpnC1 = vue.extend ({template: '<div>
        <h2>I'm heading one</h2>
        <p>I am content, hahaha</p>
      </div>}) // 2. Create a second component constructor (parent component) const cpnC2 = vue.extend ({template: '<div>
        <h2>I'm heading 2</h2>
        <p>I am content, hehe hehe</p>
        <cpn1></cpn1>
      </div>Const app = new Vue({el: '#app', components: {cpn2: cpnC1}}) const app = new Vue({el: '#app', components: {cpn2: cpnC2 } })</script>
Copy the code

(5) Register component syntax sugar

The call to vue.extend () is omitted, and an object can be used instead.

<div id="app">
  <cpn1></cpn1>
  <cpn2></cpn2>
</div>

<script src=".. /js/vue.js"></script>
<script>
  // 1. Syntax sugar for global component registration
  // 1. Create a component constructor
  // const cpn1 = Vue.extend()
  // 2. Register components
  Vue.component('cpn1', {
    template: '
       

I'm heading 1

I'm content, hahaha

'
}) // 2. Register the syntax sugar of the local component const app = new Vue({ el: '#app'.data: { message: 'Hello.' }, components: { 'cpn2': { template: '

I'm heading 2

I'm content, hehe hehe

'
}}})
</script> Copy the code

(6) separate writing method of template

If you want to use a script tag, you can use a text/x-template tag.

<div id="app">
  <cpn></cpn>
</div>
<! --1.script tag, note: the type must be text/x-template-->
<script type="text/x-template" id="cpn">
<div>
  <h2>I am heading</h2>
  <p>I am content, hahaha</p>
</div>
</script>
<script src=".. /js/vue.js"></script>
<script>
  // 1. Register a global component
  Vue.component('cpn', {
    template: '#cpn'
  })
  const app = new Vue({
    el: '#app'
  })
</script>
Copy the code

The template tags:

<! - 2. The template tags - >
<template id="cpn">
  <div>
    <h2>I am heading</h2>
    <p>I am content, hehe hehe</p>
  </div>
</template>
Copy the code

(7) Component cannot access data of Vue instance data

A component is an encapsulation of a single functional module that has its own HTML template and should also have its own property data.

The data attribute must be a function that returns an object containing data

<div id="app">
  <cpn></cpn>
</div>
<template id="cpn">
  <div>
    <h2>{{title}}</h2>
  </div>
</template>
<script src=".. /js/vue.js"></script>
<script>
  // 1. Register a global component
  Vue.component('cpn', {
    template: '#cpn'.// Data is a function that returns an object that holds data
    data() {
      return {
        title: 'abc'}}})const app = new Vue({
    el: '#app'.data: {
      message: 'Hello.',}})</script>
Copy the code

(8) Two ways that component data returns objects

(1) The returned object is defined in data. (Information is not shared.) (2) The returned object is defined externally. (Information sharing)

The first way:

<div id="app">
  <cpn></cpn>
  <cpn></cpn>
  <cpn></cpn>
</div>
<template id="cpn">
  <div>
    <h2>Current count: {{counter}}</h2>
    <button @click="increment">+</button>
    <button @click="decrement">-</button>
  </div>
</template>
<script src=".. /js/vue.js"></script>
<script>
Vue.component('cpn', {
    template: '#cpn'.data() {
      return {
        counter: 0}},methods: {
      increment() {
        this.counter++
      },
      decrement() {
        this.counter--
      }
    }
  })
  const app = new Vue({
    el: '#app',})</script>
Copy the code

Clicking on any module only changes the value of count for the current component. Each object has its own memory address. Three calls to the component’s data return three objects with different memory addresses (the same content, but different addresses). So information is not shared.

The second way is:

<script>
const obj = {
    counter: 0
  }
  Vue.component('cpn', {
    template: '#cpn'.data() {
      return obj
    },
    methods: {
      increment() {
        this.counter++
      },
      decrement() {
        this.counter--
      }
    }
  })
</script>
Copy the code

Clicking on any module changes the value of count. Because obj is defined first, obj has a memory address, and when the component’s data is called three times, it returns obJ with the same memory address. So that leads to information sharing.

2-2. Data transmission

The parent component passes data to the child component through functions and the child component sends messages to the parent component through eventsIn real development, the communication between a Vue instance and a child is the same as the communication between a parent and a child.

(1) The parent passes props to the child

Use the option props in the child component to declare the data that needs to be received from the parent.

There are two ways to value props:

Method 1: string array, the string in the array is the name of the pass.

Method 2: object, object can be set when the type of transfer, can also set the default value.

① Array form

String array :(not used)

<div id="app">
  <! When calling a child component that needs data from the parent, you must v-bind the binding property -->
  <cpn :cmessage="message" :cmovies="movies"></cpn>
</div>

<template id="cpn">
  <div>
    <p>{{cmovies}}</p>
    <h2>{{cmessage}}</h2>
  </div>
</template>

<script src=".. /js/vue.js"></script>
<script>
  // Props
  const cpn = {
    template: '#cpn'.props: ['cmovies'.'cmessage']}const app = new Vue({
    el: '#app'.data: {
      message: 'Hello.'.movies: ['the sea king'.One Piece.Haier Brothers]},components: {
      cpn
    }
  })
</script>
Copy the code
② Object form

The supported data types are: String, Number, Boolean, Array, Object, Date, Function, and Symbol

<div id="app">
  <! When calling a child component that needs data from the parent, you must v-bind the binding property -->
  <cpn :cmessage="message" :cmovies="movies"></cpn>
</div>

<template id="cpn">
  <div>
    <p>{{cmovies}}</p>
    <h2>{{cmessage}}</h2>
  </div>
</template>

<script src=".. /js/vue.js"></script>
<script>
  // Props
  const cpn = {
    template: '#cpn'.props: {
      // 1. Type restriction
      // cmovies: Array,
      // cmessage: String,
      // 2. Provide some default values as well as mandatory values
      cmessage: {
        type: String.// Data type
        default: 'aaaaaaaa'./ / the default value
        required: true        // true means that the cmessage property must be called when the component is called
      },
      When the type is an object or array, the default value must be a function
      cmovies: {
        type: Array.default() {
          return[]}}}}const app = new Vue({
    el: '#app'.data: {
      message: 'Hello.'.movies: ['the sea king'.One Piece.Haier Brothers]},components: {
      cpn
    }
  })
</script>
Copy the code
③ Points of attention for hump identification:

When we declare variables in props using a hump nomenclature (cMessage), the v-bind attribute name cannot be humped and needs to be changed when calling the child component and passing the parent component data. CMessage is converted to C-message

<div id="app">
  <! -->
  <cpn :cMessage="message"></cpn>
  <! -->
  <cpn :c-message="message"></cpn>
</div>

<template id="cpn">
  <div>
    <h2>{{cMessage}}</h2>
  </div>
</template>

<script src=".. /js/vue.js"></script>
<script>
  const cpn = {
    template: '#cpn'.props: {
      cMessage: {
        type: String.default: 'very good'}}}const app = new Vue({
    el: '#app'.data: {
      message: 'Hello.'
    },
    components: {
      cpn
    }
  })
</script>
Copy the code

(2) The child passes to the parent

The child component passes data or events to the parent component using custom events.

Custom event flow: In the child component, emit the event via $emit(‘ event name ‘, parameter). Emit means emit. In the parent component, v-on is used to listen for child component events. @event name =’ Event of parent component ‘

<! Parent component template -->
<div id="app">
  <cpn @item-click="cpnClick"></cpn>
</div>

<! -- Subcomponent template -->
<template id="cpn">
  <div>
    <button v-for="item in categories"
            @click="btnClick(item)">
      {{item.name}}
    </button>
  </div>
</template>

<script src=".. /js/vue.js"></script>
<script>

  // 1. Child components
  const cpn = {
    template: '#cpn'.data() {
      return {
        / / class
        categories: [{id: 'aaa'.name: 'Top Recommendations'},
          {id: 'bbb'.name: 'Mobile Digital'},
          {id: 'ccc'.name: 'Home Appliances'},
          {id: 'ddd'.name: 'Computer Office'}}},],methods: {
      btnClick(item) {
        // Launch event: custom event
        this.$emit('item-click', item); 
        // item-click is the binding event name of the parent component @item-click= ""}}}// 2. Parent component
  const app = new Vue({
    el: '#app'.components: {
      cpn
    },
    methods: {
      cpnClick(item) {
        console.log('cpnClick', item); }}})</script>
Copy the code

(3) Parent-child component access

Parent component accessing child component: Use children or children or children or refs (Reference reference) Child component accessing parent component: Use parent to access root component: Use parent to access root component: Use parent to access root component: Use root to access root component

The most common is refs

Children gets a collection of subcomponents, an array that must be accessed by an index value. Children’s weakness: When there are too many child components and we need to get one of them, we are often unsure of its index value and may even change.

Refs is a key that defines the REF attribute for each child component and then calls it using refs to access a specific child component without error as the number of locations changes.

<div id="app">
  <cpn></cpn>
  <cpn></cpn>
  <cpn ref="aaa"></cpn>
  <button @click="btnClick">button</button>
</div>

<template id="cpn">
  <div>I'm a child component</div>
</template>
<script src=".. /js/vue.js"></script>
<script>
  const app = new Vue({
    el: '#app'.data: {
      message: 'Hello.'
    },
    methods: {
      btnClick() {
        // 1.$children
        console.log(this.$children);
        for (let c of this.$children) {
           console.log(c.name);
        }
        console.log(this.$children[1].name);

        // 2.$refs => object type, default is an empty object
        console.log(this.$refs.aaa.name); }},components: {
      cpn: {
        template: '#cpn'.data() {
          return {
            name: 'I'm the name of the child component'}}},}})</script>
Copy the code

Parent:

  • Although in Vue development we are allowed to access parent components through parent, try not to do so in real development.
  • The child component should avoid direct access to the parent component’s data because it is too coupled.
  • If we put a child component inside another component, it is likely that the parent does not have corresponding properties, often causing problems.
  • It would be even harder to change the state of the parent component directly with $parent, which would make the state of the parent component erratic, which would be very difficult for me to debug and maintain.

(4) Non-parent-child component communication

3. Advanced componentization

3-1, slot slot

Component slots are also designed to make the components we package more extensible. Let the user decide what some of the content inside the component actually shows.

(1) Compile scope

Everything in the parent component template is compiled in the parent scope; Everything in the subcomponent template is compiled in the subscope.

(2) Basic use of slot

Use the label slot in the child component. Use the child component directly in the parent component and use the desired label internally.

<! 2. The default value of the slot <slot>button</slot> 3. If multiple values are put into the component at the same time for replacement, they are used as replacement elements together -->

<div id="app">
  <cpn></cpn> <! - button - >
  <cpn><i>Ha ha ha</i></cpn> <! -- Ho ho ho -->
  <cpn>
    <i>Ha ha ha</i>           <! Div p-->
    <div>I'm a div element</div>
    <p>I'm a p element</p>
  </cpn>
  <cpn></cpn>
</div>
<template id="cpn">
  <div>
    <h2>I am a component</h2>
    <p>I'm a component, hahaha</p>
    <slot><button>button</button></slot> <! -- default is button -->
  </div>
</template>

<script src=".. /js/vue.js"></script>
<script>
  const app = new Vue({
    el: '#app'.data: {
      message: 'Hello.'
    },
    components: {
      cpn: {
        template: '#cpn'}}})</script>
Copy the code

(3) Named slot

When there are multiple slots and you want to replace the contents of a slot, simply give the slot element a name attribute. When replacing the slot element, you can use the V-slot directive on a template tag and supply the name(which can also be a dynamic parameter) as a parameter to the V-slot. Abbreviation # name

<div id="app">
  <template v-slot="center"><span>The title</span></template>
  <template v-slot="left"><button>return</button></template>
</div>

<template id="cpn">
  <div>
    <slot name="left"><span>On the left</span></slot>
    <slot name="center"><span>In the middle</span></slot>
    <slot name="right"><span>On the right</span></slot>
  </div>
</template>

<script src=".. /js/vue.js"></script>
<script>
  const app = new Vue({
    el: '#app'.data: {
      message: 'Hello.'
    },
    components: {
      cpn: {
        template: '#cpn'}}})</script>
Copy the code

(4) Slot Scope slot

The parent component replaces the label of the slot, but the content is provided by the child component. The core is to get data from the child component and use it in the parent component. We can bind user as an attribute of the element

<span> 
   <slot v-bind:user="user"> {{ user.lastName }} 
   </slot> 
</span>
Copy the code

Attributes bound to

elements are called slot prop. Now in parent scope, we can define the name of our supplied slot prop using v-slot with a value:

<current-user>
  <template v-slot:default="slotProps">
    {{ slotProps.user.firstName }}
  </template>
</current-user>
Copy the code

In this example, we chose to name the object that contains all the slotProps slotProps, but you can use any name you like.

4. Component lifecycle

Here is a brief introduction to the parent-child component lifecycle creation sequence, and I will go into more detail on vue source code analysis in a later article

When a parent component contains a child component, its lifecycle is created in the following order:

Parent beforeCreate-> Parent created-> parent beforeMount-> child beforeCreate-> child created-> child beforeMount-> Child Mounted -> parent Mounted

5. Modular development

CommonJS, AMD, CMD, and ES6 Modules

5-1, CommonJS

Use Node, Node will learn, learn Node to write the article will be introduced and in this supplementary link

Module. exports = {} export let {} = require(‘./… js’)

5-2, Modules for ES6

Type =”module” in the import js file

<script src="aaa.js" type="module"></script>
<script src="mmm.js" type="module"></script>
Copy the code

Export (export), inport(import)

Export Method 1:

var flag= true;
function sum(num1,num2){
  return num1 + num2
}
class Person {
  run() {
	console.log('On the run'); }}export {
  flag,
  sum,
  Person
}
Copy the code

Export method two :(first out when defining)

export var num1 = 1000;
// Export function/class:
export function mul(num1, num2) {
    return num1 * num2
}
export class Person {
    run() {
        console.log('On the run'); }}Copy the code

In some cases, a module contains a function that we do not want to name and let the importer name it himself, using Export Default

Note: Export default cannot exist in one module at the same time.

// export default
export default const address = 'Beijing'
// Export the function
export default function(argument) {
  console.log(argument);
}

// Import is written differently than usual
import addr from "./aaa.js"; // addr is self-named, no longer need to add {}
Copy the code

Import:

// Partial import
import {flag,sum} from "./aaa.js";
// all imports are unified
import * as bbb from './aaa.js'  // the name that BBB named for itself
console.log(bbb.flag);           // Invoke the imported flag
console.log(bbb.sum(10.20));     // Call imported sum()
Copy the code

Third, the vue – the router

1. Know routes

Routing is the activity of transferring information from a source address to a destination address over an interconnected network – Wikipedia. Routing determines the path a packet takes from its source to its destination.

There is a very important concept in routing called routing table, which is essentially a mapping table that determines the direction of packets.

2. Vue-router is used basically

2-1. Route jump rules

(1) URL hash

The hash of the URL is the anchor point (#). We can change the href by assigning location.hash directly, but the page does not refresh.

(2) History of ES5

pushState

Jump back. The jump instruction is: history.back()

replaceState

Replace, cannot jump.

go

History.back () is equivalent to history.go(-1). History.forward () is equivalent to history.go(1).

2-2. Install routes

NPM install vue-router –save CLI install: select vue-router yes CLI install will automatically configure for us, if it is webpack install, we need to configure ourselves. The configuration can be as follows:

src/router/index.js

// Configure routing information
import Vue from 'vue'
import VueRouter from 'vue-router'
Use Vue. Use (plug-in) to install the plug-in
Vue.use(VueRouter)
// Configure the mapping between routes and components (mapping table)
const routes = [
]
// create the VueRouter object
const router = new VueRouter({
  routes
})
// 3. Pass the Router object to the Vue instance
export default router
Copy the code

main.js

import Vue from 'vue'
import App from './App'
import router from './router'  // Import a route to import a folder, the index file will be imported by default

Vue.config.productionTip = false

new Vue({
  el: '#app',
  router,  // Import a route
  render: h= > h(App)
})
Copy the code

2-3. Use routes

src/router/index.js

// Configure routing information
import Vue from 'vue'
import VueRouter from 'vue-router'

import Home from '.. /components/Home'  // Import components
import About from '.. /components/About' // Import components

Use Vue. Use (plug-in) to install the plug-in
Vue.use(VueRouter)
// Configure the mapping between routes and components
const routes = [
  {
    // The default route path
    path: ' '.redirect: '/home'  // redirect
  },
  {
    path: '/home'.component: Home
  },
  {
    path: '/about'.component: About
  }
]
// create the VueRouter object
const router = new VueRouter({
  routes,
  mode:'history'  // mode: the default hash value is' #/home '. If you use ES5 history, there is no #
})
// 3. Pass the Router object to the Vue instance
export default router
Copy the code

main.js

import Vue from 'vue'
import App from './App'
import router from './router'  // Import a route to import a folder, the index file will be imported by default

Vue.config.productionTip = false

new Vue({
  el: '#app',
  router,  // Import a route
  render: h= > h(App)
})
Copy the code

App.vue

<template>
  <div id="app">
    <router-link to="/home">Home page</router-link>
    <router-link to="/about">about</router-link>
    <router-view></router-view> <! -- Component will be replaced with router-view -->
  </div>
</template>
Copy the code

Router-link: this label is a built-in component of vue-router, which is rendered as an A label by default. Router-view: this label dynamically renders different components based on the current path. The rest of the page, such as the title/navigation at the top, or some copyright information at the bottom, is at the same level as the router-View. During route switching, only the components mounted by the router-View are switched. Other contents remain unchanged

(1) the router – the link

Router-link: This tag is a component already built into vue-Router and is rendered as an A tag by default. Properties:

  • To: Indicates the jump path.
  • Tag: You can specify what tag router-link will render to, such as a button tag, tag=”button”
  • Replace: The default jump is pushState. To replaceState, add the replace property directly.
  • ④ Ctive -class: When the router-link route matches successfully, the system automatically sets a router-link-active class for the current element. You can change the default name of the active-class.

This class is used when highlighting navigation menus or tabbars at the bottom.

However, if you have more than one router-link, you need to modify it several times, so there is an easy way to write it: SRC /router/index.js

const router = new VueRouter({
  routes,
  mode:'history'.linkActiveClass:'active' // If the route is successfully matched, the default class name is active
})

export default router
Copy the code

(2) Another way to jump

A router-link link is a router-link link. A router-link link is a router-link link

<template>
  <div id="app">
    <button @click="homeClick">Home page</button>
    <button @click="aboutClick">about</button>
    <router-view></router-view>
  </div>
</template>
<script>
export default {
  name: 'App'.methods: {
    homeClick() {
      // Modify the vue-router in code
      // this.$router.push('/home')
      this.$router.replace('/home') // Router is the router defined in index.js (Vuerouter object)
    },
    aboutClick() {
      // this.$router.push('/about') // push=>pushState
      this.$router.replace('/about') // replace=>replaceState}}}</script>
Copy the code

2-4. Dynamic routing

In some cases, the path of a page may be indeterminate. For example, when we enter the user interface, we want the following path: /user/aaaa or /user/ BBBB (in addition to /user, the user ID is followed by the user ID). We can also obtain information by routing. Path in index.js:

  {
    path: '/user/:id'.// id useId obtained from app. vue
    component: User
  }
Copy the code

App.vue

<router-link :to="'/user/'+userId">The user</router-link>
<script>
  export default {
  name: 'App'.data() {
    return {
      userId: 'zhangsan'}}}</script>
Copy the code

/ User /zhangsan = / User /zhangsan = user.vue = / User /zhangsan = User

<template>
  <div>
    <h2>{{userId}}</h2>  <! -- Get information from computer -->
    <h2>{{$route.params.id}}</h2>  <! -->
  </div>
</template>

<script>
  export default {
    name: "User".computed: {
      userId() {
        return this.$route.params.id 
        // The route is not the same as the "alternative route" router
        // Route is the active route of routes in the router
        // id is the ID of path: '/user/:id' in the active route}}}</script>
Copy the code

2-5. Lazy route loading

Javascript packages can become very large when packaged to build applications, affecting page loads. It would be much more efficient if we could split the components corresponding to different routes into different code blocks and then load the components only when the routes are accessed.

The main function of route lazy loading is to pack the components corresponding to the route into JS code blocks one by one. The components are loaded only when the route is accessed. Previously: index.js

import Vue from 'vue'
import VueRouter from 'vue-router'

import Home from '.. /components/Home'  // Import components
import About from '.. /components/About' // Import components

Vue.use(VueRouter)

const routes = [
  {
    // The default route path
    path: ' '.redirect: '/home'
  },
  {
    path: '/home'.component: Home
  },
  {
    path: '/about'.component: About
  }
]
Copy the code

Route lazy loading:

import Vue from 'vue'
import VueRouter from 'vue-router'

const Home = () = > import('.. /components/Home')  // Dynamically import components
const About = () = > import('.. /components/About') // Dynamically import components

Vue.use(VueRouter)

const routes = [
  {
    // The default route path
    path: ' '.redirect: '/home'
  },
  {
    path: '/home'.component: Home
  },
  {
    path: '/about'.component: About
  }
]
Copy the code

3, Vue-router nested routine by

There are two more paths in the component home that correspond to two child components.

1. Create the corresponding sub-components (news. vue, message. vue) and configure the corresponding sub-routes in the route mapping:

import Vue from 'vue'
import VueRouter from 'vue-router'

const Home = () = > import('.. /components/Home') 
const News = () = > import('.. /components/News') // Dynamically import the child component News
const Message = () = > import('.. /components/Message') // Dynamically import the child component Message
const About = () = > import('.. /components/About')

Vue.use(VueRouter)

const routes = [
  {
    // The default route path
    path: ' '.redirect: '/home'
  },
  {
    path: '/home'.component: Home,
    children:[
    {
       path:' '.redirect: News
    },
    {
       path:'news'.// Don't add /
       component: News
     },
     {
       path:'message'.// Don't add /
       component: Message
     }
    ]
  },
  {
    path: '/about'.component: About
  }
]
Copy the code

2. Use router-link and router-view tags inside the parent of the two child components. Home.vue

<template>
  <div>
    <router-link to="/home/news">news</router-link>
    <router-link to="/home/message">The message</router-link>
    <router-view></router-view>
  </div>
</template>

<script>
  export default {
    name: "Home"
  }
</script>
Copy the code

4. Vue-router parameter transmission

URL: Protocol :// host: port/path? Scheme ://host:port/path? query#fragment

There are two main types of passing parameters: Params and Query

4-1 types of Params:

Set the route format to /router/: ID

How it is passed: Follow path with the corresponding value

The path is /router/123, /router/ ABC

See 2-4. Dynamic Routing

Alternative to router-link (see 2-3(2))

<template>
  <div>
    <button @click="userClick">The user</button>
  </div>
</template>
<script>
export default {
  name: 'App'.data(){
    return {
      userId: 'zhangsan'}},methods: {userClick(){
      this.$route.push('/user'+this.userId)
    }
  }
</script>
Copy the code

4-2. Query type:

The route format is /router, which is the common configuration

Pass method: The object uses the Query key as the pass method

Route: /router? id=123, /router? id=abc

Index.js (don’t set it like params, just set it normally)

  {
    path: '/profile'.component: Profile
  }
Copy the code

App.vue

<template>
  <div>
    <router-link :to="{path:'/profile',query:{name:'wu',age:20}}">my</router-link>
    <router-view></router-view>
  </div>
</template>
Copy the code

Profile.vue

<template>
  <div>
    <h2>{{$route.query}}</h2>      <! -- {name:wu,age:20} -->
    <h2>{{$route.query.name}}</h2> <! -- wu -->
    <h2>{{$route.query.age}}</h2>  <! -- -- -- > 20
  </div>
</template>
Copy the code

The url is… /profile? name=wu&&age=20

Another way to switch to a router without router-link

<template>
  <div>
    <button @click="profileClick">my</button>
  </div>
</template>
<script>
export default {
  name: 'App'.methods: {profileClick(){
      this.$route.push({
        path: '/profile'.qurey: {name: 'wu'.age: 20}}}})</script>
Copy the code

There is a difference between a route and a router

Router is an instance of VueRouter and can be navigated to different urls using the $router.push/replace method

$route is the route to which the current router jumps (route is the active route on routes in the router). You can obtain name, path, query, and params

6. Vue-router navigation guard

How do you change the title of a web page in a SPA application? Page titles are displayed using the title tag, but SPA has only one fixed HTML and the title does not change when switching between pages. The navigational guard solves this problem.

What is a navigation guard?

  1. Vue-router provides a navigational guard that listens for incoming and outgoing routes.
  2. Vue-router provides beforeEach and afterEach hook functions that fire before and after a route is about to change.
  3. Both the front guard and the rear hook are global guards
  4. Exclusive route guard beforeEnter, the parameter is the same as beforeEach.
  5. The guards within the component beforeRouteEnter (called before rendering the corresponding route of the component), beforeRouteUpdate (called when the current route changes but the component is being re-used), beforeRouteLeave (called before navigating away from the corresponding route of the component)

Change the page title: index.js

const routes = [
  {
    path: '/home'.component: Home,
    meta: {         // Meta metadata (data describing data)
      title: 'home'}}, {path: '/about'.component: About,meta: {title: 'about'}},
  {path: '/user/:id'.component: User,meta: {title: 'users'}},
  {path: '/profile'.component: Profile,meta: {title: 'archives'}}]// Guard
router.beforeEach((to, from, next) = > {
  // Jump from from to to
  document.title = to.matched[0].meta.title  
  // If the route is nested, it must be called meta only
  // console.log(to); // Active routing
  next()  // beforeEach Must write, jump page
})
Copy the code

Three parameters of the navigation hook:

  • ① To: Route object of the destination to be entered.
  • ② From: Indicates the route object that the current navigation is about to leave.
  • ③ Next: Call this method before going to the next hook. Next (‘/ path ‘) specify a path

Rear hook:

// add a hook.
router.afterEach((to, from) = > {
  // console.log('----');
})
Copy the code

Route exclusive guard:

  {
    path: '/home'.component: Home,
    meta: {         // Meta metadata (data describing data)
      title: 'home'
    },
    beforeEnter:(to,from,next) = > {
      // ...
      next()
    }
  }
Copy the code

7, keep alive

Keep-alive is a component built into Vue that can preserve the state of contained components or avoid re-rendering. Router-view is also a component. If it is wrapped directly in keep-alive, all view components matched by the path will be cached.

The activated and deactivated functions can be used only when keep-alive exists. Activated and deactivated app.vue

  <keep-alive>
    <router-view></router-view>
  </keep-alive>
Copy the code

Home.vue

  export default {
    name: "Home".activated(){
      console.log('Home activated')},deactivated(){
      console.log('Home deactivated')}}Copy the code

Home Activated is printed when our page is at Home, and Home deactivated is printed when the page is away from Home. (This is, of course, in the presence of keep-alive)

After keep-alive is called, components are not frequently created and destroyed. It will leave it in state or avoid re-rendering. Without keep-alive, components are created when called and destroyed when switched.

Test: App. Vue

  <keep-alive>
    <router-view></router-view>
  </keep-alive>
Copy the code

Home.vue

  export default {
    name: "Home".created(){
      console.log('Home created')},destroyed(){
      console.log('Home destroyed')}}Copy the code

Keep – the attribute of the alive

Include is a string or regular expression. Only matching components will be cached. Exclude is a string or regular expression

App.vue

  <keep-alive exclude="Home,About"> <! --Home and About are created and destroyed frequently -->
  <! -- Home/About is the component name -->
    <router-view></router-view>
  </keep-alive>
Copy the code

8. Create an alias

When you need to fetch files from multiple outer folders,.. /.. This is a taboo in development, and if you move the location of the file, you may need to change the call path code. So it’s very convenient to have individual names.

webpack.base.conf.js

module.exports = {
  resolve: {
    alias: {
      The '@': resolve('src'),  // SRC folder for the current project (layer 1)
      'assets': resolve('src/assets'), 
      'components': resolve('src/components'),
      'views': resolve('src/views'),}}}Copy the code

Call: there are two cases: ① call in HTML tag (image reference) ② call in import ① HTML tag (add ~)

<img slot="item-icon" src="~assets/img/tabbar/home.svg" alt="">
<! -- Assets are SRC /assets, but to use an alias within an HTML tag, add ~ -->
Copy the code

② Call in import

import TabBar from 'components/tabbar/TabBar'
// component is SRC /component
Copy the code

9, Promise (ES6)

Promise is a solution to asynchronous programming.

When do we deal with asynchronous events? A very common scenario would be a network request. We encapsulate a function for a network request, and since we don’t get results immediately, we often pass in another function that calls back the data when the request succeeds. However, when the network request is very complex, callback hell (multiple callback functions) can occur.

The normal way of writing callback hell is, under normal circumstances, there’s nothing wrong, it works and it gets the result we want. However, such code is ugly and not easy to maintain.

9-1. The structure of Promise

// Promise takes a function (resolve,reject)=>{}
// This function takes two arguments: resolve and reject. These are functions themselves.
// reject reject when not needed
new Promise((resolve,reject) = > {
  // Asynchronous events
  setTimeout(() = > {
    // Call resolve when the request succeeds
    resolve()
    Reject is called when the request fails
    reject()
  }, 1000)
}).then(() = > {
  // 100 lines of processing code when the request succeeds
  // ...
  // Another asynchronous event, and a Promise
  return new Promise((resolve) = >{}) Reject (reject
}).catch(() = > {
  // The processing code when the request fails
  // ...
})
Copy the code

SetTimeout: setTimeout: setTimeout

setTimeout(() = > {
  console.log('Hello World');
  console.log('Hello World');
  console.log('Hello World');
  
  setTimeout(() = > {
    console.log('Hello Vuejs');
    console.log('Hello Vuejs');
    console.log('Hello Vuejs');
    
    setTimeout(() = > {
      console.log('Hello Python');
      console.log('Hello Python');
      console.log('Hello Python');
    }, 1000)},1000)},1000)
Copy the code

Make a Promise

// chain programming
new Promise((resolve, reject) = > {  Reject (reject
  // The first asynchronous event
  setTimeout(() = > {
      resolve()
    }, 1000)
}).then(() = > {
  // The first asynchronous event handler code
  console.log('Hello World');
  console.log('Hello World');
  console.log('Hello World');
  // The second asynchronous event
  return new Promise((resolve) = > {  Reject (reject
    setTimeout(() = > {
      resolve()
    }, 1000)
  })
}).then(() = > {
  // The code for the second asynchronous event handler
  console.log('Hello Vuejs');
  console.log('Hello Vuejs');
  console.log('Hello Vuejs');
  // The third asynchronous event
  return new Promise((resolve) = > {  Reject (reject
     setTimeout(() = > {
       resolve()
    },1000)
  })
}).then(() = > {
  // The third asynchronous event handler code
  console.log('Hello Python');
  console.log('Hello Python');
  console.log('Hello Python');
})
Copy the code

Note: The second then() is followed by the first then() and the third then() is followed by the second then(). Instead of following Promise()

9-2. Three states of Promise

9-3. Chain programming of Promise

Network request to AAA -> processed to AAA111 -> processed to AAA111222 -> Rejected to AAA111222Error -> Processed to AAA111222ERROR444. So there is only one asynchronous operation in the whole process.

General chain programming:

  new Promise(resolve= > {
    setTimeout(() = > {
      resolve('aaa')},1000)
  }).then(data= > {
    console.log(data);  // => aaa
    // 2. Perform the first processing on the result
    return new Promise(resolve= > {
      resovle(data + '111')
    })
  }).then(data= > {
    console.log(data);  // => aaa111
    return new Promise(resolve= > {
      resovle(data + '222')
    })
  }).then(data= > {
    console.log(data);  // => aaa111222
    return new Promise(reject= > {
      reject(data + 'error')
    })
  }).then(data= >{
    console.log(data);  // There is no output here and it will not be executed
    return new Promise(resolve= > {
      resovle(data + '333')
    })
  }).catch(data= > {
    console.log(data);  // => aaa111222error
    return new Promise(resolve= > {
      resovle(data + '444')
    })
  }).then(data= > {
    console.log(data);  // => aaa111222error444
  })
Copy the code

New Promise(resolve => resolve(result))

  • ①Promise.resovle() : Wraps the data as a Promise object and internally calls the resolve() function
  • ②Promise.reject() : Wraps the data as a Promise object and calls the Reject () function internally
  new Promise(resolve= > {
    setTimeout(() = > {
      resolve('aaa')},1000)
  }).then(data= > {
    console.log(data);  // => aaa
    // 2. Perform the first processing on the result
    return Promise.resovle(data + '111')   // Short for promise. resolve
  }).then(data= > {
    console.log(data);  // => aaa111
    return Promise.resovle(data + '222')
  }).then(data= > {
    console.log(data);  // => aaa111222
    return Promise.reject(data + 'error')  // Promise.reject
  }).then(data= >{
    console.log(data);  // There is no output here and it will not be executed
    return Promise.resovle(data + '333')
  }).catch(data= > {
    console.log(data);  // => aaa111222error
    return Promise.resovle(data + '444')
  }).then(data= > {
    console.log(data);  // => aaa111222error444
  })
Copy the code

Resolve If we want the data wrapped directly as promise.resolve, then we can return the data directly in then

  new Promise(resolve= > {
    setTimeout(() = > {
      resolve('aaa')},1000)
  }).then(data= > {
    console.log(data);  // => aaa
    // 2. Perform the first processing on the result
    return data + '111'   // Short for promise. resolve
  }).then(data= > {
    console.log(data);  // => aaa111
    return data + '222'
  }).then(data= > {
    console.log(data);  // => aaa111222
    throw data + 'error'  // Promise.reject
  }).then(data= >{
    console.log(data);  // There is no output here and it will not be executed
    return data + '333'
  }).catch(data= > {
    console.log(data);  // => aaa111222error
    return data + '444'
  }).then(data= > {
    console.log(data);  // => aaa111222error444
  })
Copy the code

9-4. Promise’s All

A request requires both requests to complete before it can proceed:

Promise.all([]) // Array type, because multiple requests are to be placed

  Promise.all([
    new Promise((resolve, reject) = > {
      setTimeout(() = > {
        resolve({name: 'why'.age: 18})},2000)}),new Promise((resolve, reject) = > {
      setTimeout(() = > {
        resolve({name: 'kobe'.age: 19})},1000)
    })
  ]).then(results= > {  // Call only when both requests are complete
    console.log(results);
  })
Copy the code

Display after two seconds:

Five, Vuex details

1. Know Vuex

Vuex is a state management mode developed specifically for vue.js applications. You can simply think of it as storing all the variables that need to be shared by multiple components in one object. This object is then placed in the top-level Vue instance and made available to other components. Vuex is responsive.

Information shared between multiple interfaces can be placed in Vuex, such as user login status, user name, profile picture, location information, and so on. Such as the collection of goods, items in the shopping cart and so on. All of this state information can be stored and managed in a single place, and it’s responsive

2. Basic use of Vuex

Install Vuex: NPM install Vuex –save

Create a folder under SRC: store

To build the index. Js

import Vue from 'vue'
import Vuex from 'vuex'

// Install the plug-in
Vue.use(Vuex)

const store = new Vuex.Store({
  state{},
  mutations{},
  actions{},
  getters{},
  modules: {}})/ / export
export default store
Copy the code

Main.js reference (mounted to vue instance)

This way, in other Vue components, we can get the store object as this.$store

import Vue from 'vue'
import App from './App'
import store from './store'  / / import store

Vue.config.productionTip = false

new Vue({
  el: '#app',
  store,  / / import store
  render: h= > h(App)
})
Copy the code

2-1 legend of Vuex status management

2-2. Small cases

index.js

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)

const store = new Vuex.Store({
  state{
    count = 1000
  },
  mutations{
    increment(state){  / / call the state
      state.count++
    },
    decrement(state){
      state.count--
    }
  }
})

export default store
Copy the code

Mount to the Vue

import Vue from 'vue'
import App from './App'
import store from './store'  / / import store

Vue.config.productionTip = false

new Vue({
  el: '#app',
  store,  / / import store
  render: h= > h(App)
})
Copy the code

Using vuex

<template>
  <div id='app'>
    <h2>{{$store.state.count}}</h2>
    <button @click="add">+</button>
    <button @click="sub">-</button>
  </div>
</template>
<script>
  export default{
    name: 'App'.methods: {add(){
        this.$store.commit('increment')  // Reference increment method by commit(mutation)
      },
      sub(){
        this.$store.commit('decrement')}}}</script>
Copy the code

3. Core of Vuex

3-1, the State

3-2, Getters

Analogous to computed properties

Basic use: Getters is used to get some state variation from the store.

As arguments: Need to pass arguments: Getters cannot pass arguments by default. If you want to pass arguments, you have to make getters return another function

  state:{
    student: [{name:'durant'.age:35}, {name:'curry'.age:30}},getters: {more20stu(state){    // Basic usage
      return state.students.filter(s= > s.age > 20)},more20stuNumber(state,getters){   // getters as a parameter
      return getters.more20stu.length
    },
    moreAgeStu(state) {  // How to pass arguments: return a function
      return age= > {
        return state.students.filter(s= > s.age > age)
      }
    }
  }
Copy the code

Reference:

<template>
  <div>
    <h2>{{$store.getters.more20stu}}</h2>
    <h2>{{$store.getters.more20stuNumber}}</h2>
    <h2>{{$store.getters.moreAgeStu(32)}}</h2>
  </div>
</template>
Copy the code

3, Mutation (status update)

(1) Basic use

The only way to update the store state of Vuex is to commit Mutation

  mutations{
    increment(state){  // The first argument must be state
      state.count++
    },
    decrement(state){
      state.count--
    }
  }
Copy the code

It must be called with commit

    methods:{
      add(){
        this.$store.commit('increment')  // Reference increment method by commit(mutation)
      },
      sub(){
        this.$store.commit('decrement')}}Copy the code

(2) Pass parameters

Event name (state, payload) Payload. It can be a parameter or an object. When multiple parameters need to be passed, you can pass them in an object.

  mutations{
    incrementCount(state,counter){  // The first argument must be state
      state.count += counter
    }
  }
Copy the code

call

    methods:{
      addCounter(counter){
        this.$store.commit('increment',counter)
      }
    }
Copy the code

(3) Submission style

  • ① Common: commit(‘ event name ‘, parameter)
  • ② Commit ({type:’ event name ‘, parameter}) object
  methods:{
      addCounter(counter){
        this.$store.commit({
          type:'increment',
          counter
        })
      }
    }
Copy the code
  mutations{
    incrementCount(state,payload){  // Payload is an object. Payload is counter
      state.count += payload.counter
    }
  }
Copy the code

(4) Response formula

The state in Vuex’s store is responsive, and the Vue component updates automatically when the data in the state changes. Vuex’s reactive rule: The required properties are initialized in store in advance.

  state:{
    info: {name:'durant'.number:7.height:2.11
    }
  },
  mutations{
    change(state){
      state.info.name = 'curry' / / response type
      state.info['address'] = 'Brooklyn'  // Non-responsive, but info adds address:' Brooklyn '
      Vue.set(state.info,'address'.'Washington') / / response type
      delete state.info.number  // Non-responsive, but info deletes number:7
      Vue.delete(state.info,'number') / / response type
      // The second argument to vue. set and vue. delete can only be string or number}}Copy the code
<template>
  <div>
    <h2>{{$store.state.info}}</h2>
    <button @click='change'>change<button>
  </div>
</template>
<script>
  export default{
    name: 'App'.methods: {change(){
        this.$store.commit('change')}}}</script>
Copy the code

(5) Constant type

In mutation, we defined many event types (that is, method names within them).

As our project grew, there were more and more methods in Vuex managed Mutation, and there were too many methods. Users needed to spend a lot of experience to remember these methods, even switching back and forth between multiple files to check method names, and even writing errors might occur if it was not copied.

The official recommendation is to replace the Mutation event type with constants. We can place these constants in a single file for easy management and visibility of all event types throughout the app.

New mutations -type. Js

export const INCREMENT = 'increment'
export const DECREMENT = 'decrement'
Copy the code

index.js

import Vue from 'vue'
import Vuex from 'vuex'

import {INCREMENT,DECREMENT} from "./mutations-types"  // Import a constant type

Vue.use(Vuex)

const store = new Vuex.Store({
  state{
    count = 1000
  },
  mutations{
    [INCREMENT](state){  // [constant](){}
      state.count++
    },
    [DECREMENT](state){
      state.count--
    }
  }
})

export default store
Copy the code

Using vuex

<template>
  <div id='app'>
    <h2>{{$store.state.count}}</h2>
    <button @click="add">+</button>
    <button @click="sub">-</button>
  </div>
</template>
<script>
  import {INCREMENT,DECREMENT} from "./mutations-types"  // Import a constant type
  
  export default{
    name: 'App'.methods: {add(){
        this.$store.commit(INCREMENT)  // No longer a string
      },
      sub(){
        this.$store.commit(DECREMENT)
      }
    }
  }
</script>
Copy the code

(6) Only synchronous operation

Vuex requires that the methods in our Mutation must be synchronous methods.

The main reason is that devTools can help us capture mutation snapshots when we use devTools. However, if the operation is asynchronous, DevTools will not do a good job of tracking when the operation is completed.

3-4, the Action

Action is similar to Mutation, but is used instead of Mutation to perform asynchronous operations.

The first argument, context, is an object that has the same methods and properties as the Store object. You can also pass payload.

Call: is dispatch.We can use promises when we execute some code when our asynchronous operation or network request succeeds or fails. Put asynchronous operations or network requests in promises, butThen () and catch() follow dispatch.

3-5, the Module

Vuex allows us to divide the store into modules, and each Module has its own state, mutations, actions, getters, etc. But modules should be two at most.

4. Store’s project structure and organization chart