Start using Vue

  1. The introduction of vue. Js

    Website: vuejs.org

    Development version: includes full warning and debug modes

    Production version: Removed warning, smaller size

  2. When vue.js is introduced, we are given a constructor called vue

  3. In JS, new Vue()

  4. New Vue() returns a Vue instance object, which we follow with a variable

  5. const vm = new Vue()

  6. Pass a configuration object {} — > const VM = new Vue({})

el

Type: string

Full name: Element

What it does: Configures the control element that represents the area to be controlled by the Vue. The value is a CSS selector

  <! -- The area controlled by Vue is called template -->
  <div id="app"></div>
Copy the code
  const vm = new Vue({
    el: '#app' // Control the element whose id is app
  })
Copy the code

$mount

  • The function of el is the same as that of EL, both are configuration control elements, you can use either, or two
      <div id="app"></div>
    Copy the code
      const vm = new Vue({})
      vm.$mount('#app');
    Copy the code
  • Q: How is it different from el?

    A: There is no difference in nature, $mount is manual mount, in the project sometimes there is a delay to mount, such as sometimes before the mount some other operations, such as judgment, etc. (however, this is rarely done, less than deng went home, emMMmm)

data

  • Type: Object
  • Function: Store the data to be used, the data is responsive
      const vm = new Vue({
        el: '#app'.data: {
          'mrDeng': 'Graceful and charming'}})Copy the code

Interpolation expression

  • Use method: {{}}

  • The data in vUE can be filled into interpolation expressions such as:

      <div id="app">{{ mrDeng }}</div>
    Copy the code
      const vm = new Vue({
        el: '#app'.data: {
          mrDeng: 'Brother Deng: Graceful and charming.'}})Copy the code
  • In addition to filling in data, you can also directly fill in data values (numbers, strings, booleans, undefined, NULL, arrays, objects), such as:

      <div id="app">{{5201314}} {{' graceful, graceful '}} {{true}} {{[' xu-ming deng ', 'liu', 'Wang Xiaobao]}} {{{name:' xu-ming deng, age: 80, height: '140cm', weight: '100kg'} }}</div>
    Copy the code
  • Note: When writing object type values directly in interpolation, do not join three {} together. This will cause an error, such as:

      <div id="app">
        <! -- That's no good -->{{{name: 'xu-ming deng, age: 80, height: 140 cm, weight:' 100 kg '}}}</div>
    Copy the code
  • You can also write expressions in interpolation, such as:

      <div id="app">
        <! -- Operation expression -->
        {{ 'you' + 'me' }}
        {{ 10 - 5 }}
        {{ 100 * 7 }}
        {{ 1000 / 12 }}
        <! -- Logical expression -->{{ liu || li }} {{ deng && liu }} {{ ! wang }}<! -- ternary expression -->{{1 + 1 === 3? 'Deng Xuming' : 'Normal'}}<! Function calls can also be used as expressions. -->
      </div>
    Copy the code
  • Can I fill in anything else? No, No, the following are not acceptable:

      <div id="app">
        <! This is a statement that cannot be written in an interpolation -->
        {{ var Deng = 'shuaige'; console.log(deng) }}
        <! -- Process control can't either -->{{if (Deng. Looks = = = 'shuai') {the console. The log (' impossible ')}}}</div>
    Copy the code
  • Remember: In interpolation, you can write: data, JS data, expressions, and nothing else.

  • Note that whenever data is used in the interpolation, it must be declared in data, otherwise an error will be reported

      <! MrCheng () {mrCheng () {mrCheng ();
      <div id="app">
        {{ mrCheng }}
      </div>
    Copy the code
      const vm = new Vue({
        el: '#app'.data: {
          mrDeng: 'Brother Deng: Graceful and charming.'}})Copy the code
  • Another possibility is to use undeclared data and not report an error:

      <! -- No error now, why? -->
      <! Not found in scope -->
      <! -- not found in prototype chain, undefined -->
      <! -- undefined is the basic type of js, so there is no error -->
      <div id="app">
        {{ mrDeng.wife }}
      </div>
    Copy the code
      const vm = new Vue({
        el: '#app'.data: {
          mrDeng: {
            name: 'Deng Xuming'.age: 80.height: '140cm'.weight: '100kg'}}})Copy the code

The response formula of VUE is -1

  • The data changes and the page is re-rendered

  • How do I change the data? so easy

  <div id="app">
    {{ mrDeng }}
  </div>
Copy the code
  const vm = new Vue({
    el: '#app'.data: {
      mrDeng: 'Brother Deng: Graceful and charming.'}}); vm.mrDeng ='Hands like catkins and skin like fat'; // Witness the magic moment, the page changes
Copy the code
  • Q: Why does data appear directly in a VM instance object?

A: When a VUE instance is created, vUE proxies members of data to the vue instance in order to be responsive, monitor data changes, and perform certain listening functions (how? Think about it, hint: Object.defineProperty, try implementing it)

  • Q: What else is in an instance besides data?

To prevent name collisions. Because the data in data will be proxy to VUE, if the data name written by ourselves conflicts with the attribute in VUE, the attribute inside VUE will be overwritten, so VUE will add $or _ before the attribute member name. If $is added, it means that we can use it. If _ is added, Is a method or property that vue uses internally and that we don’t need to call

  • The changed data must be existing data, otherwise the page cannot be rerendered because it cannot listen, as in:
  <! -- The page will not be re-rendered even if the data is changed -->
  <div id="app">
    {{ mrDeng.wife }} 
  </div>
Copy the code
  const vm = new Vue({
    el: '#app'.data: {
      mrDeng: {
        name: 'Deng Xuming'.age: 80.height: '140cm'.weight: '100kg'
      }
    }
  })

  vm.mrDeng.wife = 'liu';
Copy the code
  • The changed data must already be rendered, otherwise the page will not be rerendered for performance reasons, as in:
  <! -- The page will not be re-rendered even if the data is changed -->
  <div id="app">
    {{ mrDeng.wife }} 
  </div>
Copy the code
  const vm = new Vue({
    el: '#app'.data: {
      msg: 'Brother Deng: Graceful and charming.'.mrDeng: {
        name: 'Deng Xuming'.age: 80.height: '140cm'.weight: '100kg'
      }
    }
  })

  vm.mrDeng.wife = 'liu';
  vm.msg = 'Elder Brother Deng: Hands like gentlest, skin like fat';
Copy the code
  • Will the page be rerendered immediately after changing the data?

Vue updates the DOM asynchronously. As long as it listens for changes, an asynchronous queue is opened. If a data is changed multiple times, it is pushed to the queue only once, avoiding unnecessary calculations and DOM manipulation.

After the synchronous execution stack completes, the asynchronous queue is executed

<div id="app">{{ msg }}</div>
Copy the code
const vm = new Vue({
  el: '#app'.data: {
    msg: 'very'
  }
})
vm.msg = 'Chinese Fir is super beautiful';
console.log(vm.msg); // The data has been changed
console.log(vm.$el.innerHTML); / / shanshan. The page has not yet been re-rendered
Copy the code

vm.$el

  • The value is the element controlled by Vue (or the element mounted by Vue)

vm.$nextTick & Vue.nextTick

  • How do I see the values on the rendered page after changing the data?

A: With vm.$nextTick or vue. nextTick, vm.$nextTick is executed immediately after the page is re-rendered and the DOM is updated

<div id="app">{{ msg }}</div>
Copy the code
const vm = new Vue({
  el: '#app'.data: {
    msg: 'very'
  }
})
vm.msg = 'Chinese Fir is super beautiful';
console.log(vm.msg); // The data has been changed
// 1. Use vm.$nextTick
vm.$nextTick(() = > {
  console.log(vm.$el.innerHTML); // Shanshan is super beautiful
})
// 2. Use vue.nexttick
Vue.nextTick(() = > {
  console.log(vm.$el.innerHTML); // Shanshan is super beautiful
})
Copy the code
  • Vm. nextTick and vue. nextTick can also be used as promises
<div id="app">{{ msg }}</div>
Copy the code
const vm = new Vue({
  el: '#app'.data: {
    msg: 'very'
  }
})
vm.msg = 'Chinese Fir is super beautiful';
// 1. Use vm.$nextTick
vm.$nextTick().then(() = > {
  console.log(vm.$el.innerHTML); // Shanshan is super beautiful
})
// 2. Use vue.nexttick
Vue.nextTick().then(() = > {
  console.log(vm.$el.innerHTML); // Shanshan is super beautiful
})
Copy the code
  • What is the difference between vm.$nextTick and vue. nextTick?

The this of vue. nextTick internal function points to the window

  Vue.nextTick(function () {
    console.log(this); // window
  })
Copy the code

The this of the vm.$nextTick internal function points to the Vue instance object

  vm.$nextTick(function () {
    console.log(this); / / vm instances
  })
Copy the code
  • Curious how nextTick works?
  • Asynchronous tasks are divided into macro tasks and micro tasks.
  • Macro tasks are slow (e.g. SetTimeout, etc.) and micro tasks are fast (e.g. Promise.then(), etc.)
  • Microtasks first, macros second (eventloop)
      // Console print order: promise > timeout
      setTimeout(() = > {
        console.log('timeout');
      }, 0)  
      Promise.resolve().then(() = > {
        console.log('promise');
      })
    Copy the code
  • In the nextTick implementation source code, it will determine whether microtasks are supported first, and then execute macro tasks if they are not
      if(typeof Promise! = ='undefined') {
        Micro / / task
        // First look to see if there are promises in the browser
        // Promise cannot be implemented in IE
        const p = Promise.resolve();
    
      } else if(typeofMutationObserver ! = ='undefined') {
        Micro / / task
        // Mutation observation
        // Listen for text changes in the document. If the text changes, a callback is executed
        // Vue creates a dummy node, and then lets the dummy node change slightly to execute the corresponding function
      } else if(typeofsetImmediate ! = ='undefined') {
        / / macro task
        // Only available in IE
      } else {
        / / macro task
        // If none of the above can be done, setTimeout is called
      }
    Copy the code
  • Macro tasks that have been used by VUE
    • MessageChannel MessageChannel macro task

The response formula of VUE is -2

  • Besides undeclared and unrendered data, what other data changes do not render the page?

    1. When setting an array item directly using an index:

    <! The array still displays 3 items even after the 4th item is added to the array.
    <! -- Cough, a family of three, there is a fourth person can not show it to everyone ~ >
    <div id="app">{{ list }}</div>
    Copy the code
    const vm = new Vue({
      el: '#app'
      data: {
        dengFamily: ['Deng Ge'.'liu'.'Wang Xiaobao']
      }
    })
    vm.dengFamily[3] = Sister Hammer; // Not responsive
    Copy the code

    2. Change the length of array:

    <! Change the length of the array, the array still displays 1 item.
    <div id="app">{{ list }}</div>
    Copy the code
    const vm = new Vue({
      el: '#app'
      data: {
        dengWife: ['liu']
      }
    })
    vm.dengWife.length = 0; // Not responsive
    Copy the code

    3. Add or delete objects:

    <! -- Height or that height, daughter-in-law also only one, don't wishful thinking -->
    <div id="app">{{ deng }}</div>
    Copy the code
    const vm = new Vue({
      el: '#app'
      data: {
        deng: {
          wife: 'liu'.son: 'Wang Xiaobao'.weight: '100kg'.height: '140cm'.age: 60
        }
      }
    })
    vm.deng.secondWife = Sister Hammer; // Not responsive
    delete vm.deng.height; // Not responsive
    Copy the code
  • Q: How do I update arrays and objects in response?

    Push, pop, shift, unshift, splice, sort, reverse 2. $set/Vue. Set; $set; Vue. Set

    Vue. Set (object, propertyName, value) Vue. Set (object, propertyName, value)

    Vue. Delete (object, target) Vue. Delete (whose value to delete, which value to delete) Vue.

    <! From then on, the family of three lived a happy life.
    <div id="app">{{ list }}</div>
    Copy the code
    const vm = new Vue({
      el: '#app'
      data: {
        dengFamily: ['Deng Ge'.'liu'.'Wang Xiaobao']}})// Use the array variation method
    vm.dengFamily.push(Sister Hammer);
    / / use the vm. $set
    vm.$set(vm.dengFamily, 3.Sister Hammer);
    
    Copy the code
    <! -- Deng Elder Brother's daughter-in-law more up ~ >
    <div id="app">{{ list }}</div>
    Copy the code
    const vm = new Vue({
      el: '#app'
      data: {
        dengWife: ['liu']}})// To change the length, use the array splice method
    vm.dengWife.splice(100); 
    Copy the code

    Vm.$set/Vue. Set Delete using the vm.$delete/ vue. delete method

    <div id="app">{{ deng }}</div>
    Copy the code
    const vm = new Vue({
      el: '#app'
      data: {
        deng: {
          wife: 'liu'.son: 'Wang Xiaobao'.weight: '100kg'.height: '140cm'.age: 60}}})/ / add
    vm.$set(vm.deng, 'secondWife'.Sister Hammer);
    / / delete
    vm.$delete(vm.deng, 'height')
    Copy the code
  • Conclusion:

    It is enough to change the array using the mutate method. It is enough to change the object using vm.$set and vm

  • Problem solved, but why?

    DefineProperty, let’s talk about it next class

Extension _ Anatomy of Vue responsive principles

const data = {
  name: 'shanshan'.age: 18.shan: {
    name: 'shanshan'.age: 18.obj: {}},arr: [1.2.3]}const arrayProto = Array.prototype;
const arrayMethods = Object.create(arrayProto);
['push'.'pop'.'shift'.'unshift' ,'sort'.'splice'.'reverse'].forEach(method= > {
  arrayMethods[method] = function () {
    arrayProto[method].call(this. arguments); render(); }})function defineReactive (data, key, value) {
  observer(value);
  Object.defineProperty(data, key, {
    get () {
      return value;
    },
    set (newVal) {
      if(value === newVal) {
        return; } value = newVal; render(); }})}function observer (data) {
  if(Array.isArray(data)) {
    data.__proto__ = arrayMethods;
    return;
  }

  if(typeof data === 'object') {
    for(let key in data) {
      defineReactive(data, key, data[key])
    }
  }
}

function render () {
  console.log('Page rendered');
}

function $set (data, key, value) {
  if(Array.isArray(data)) {
    data.splice(key, 1, value);
    return value;
  }
  defineReactive(data, key, value);
  render();
  return value;
}

function $delete(data, key) {
  if(Array.isArray(data)) {
    data.splice(key, 1);
    return;
  }
  delete data[key];
  render();
}

observer(data);
Copy the code

Disadvantages of using Object.defineProperty to implement responsiveness

  1. It’s natural to recurse
  2. Cannot listen for index changes that do not exist in the array
  3. Can’t listen for array length changes
  4. The object cannot be added or deleted

Vue related commands

  • A feature with special meaning and function
  • Instructions are prefixed with a V – to indicate that they are special features provided by Vue
  • Directives can use data directly from data

v-pre

  • Skip the compilation of this element and its children. You can use it to display the original Mustache tag. Skipping a large number of nodes without instructions speeds up compilation.
    <! -- will not compile
    <span v-pre>{{ msg }}</span>
    Copy the code

v-cloak

  • This instruction remains on the element until the associated instance is finished compiling

  • Can solve the flicker problem

  • Used with CSS rules such as [V-cloak] {display: None}, this instruction can hide uncompiled Mustache tags until the instance is ready

    [v-cloak] {
      display: none;
    }
    Copy the code
    <! -- {{message}} will not be displayed until compilation ends -->
    <div v-cloak>
      {{ message }}
    </div>
    Copy the code

v-once

  • Only render elements once. On subsequent re-rendering, the element and all its children are treated as static and skipped. This can be used to optimize update performance
    <! -- Single element -->
    <span v-once>{{msg}}</span>
    <! -- Has child elements -->
    <div v-once>
      <h1>comment</h1>
      <p>{{msg}}</p>
    </div>
    Copy the code

v-text

  • Update the textContent of the element
    <span v-text="msg"></span>
    <! -- Same as below -->
    <span>{{msg}}</span>
    Copy the code

v-text VS Mustache

  • While V-text replaces all text in the element, Mustache replaces only himself without empting the element’s content
    <! <span> <span> -->
    <span v-text="msg">----</span>
    <! -- Rendered as: <span>---- Shanshan the most beautiful ----</span> -->
    <span>----{{msg}}----</span>
    Copy the code
  • V-text priority higher than {{}}

textContent VS innerText

  1. When text substitution is set, all children of the specified node are also replaced.
  2. TextContent gets the contents of all elements, including<script><style> Element, whereas innerText does not.
  3. InnerText is influenced by CSS styles and does not return the text of the hidden element, whereas textContent does.
  4. Because the innerText is affected by CSS styles, it triggers reflow, but the textContent does not.
  5. InnerText is not a standards-specified API, but is introduced by IE, making it more IE friendly. TextContent, though standard, is only supported in IE8+ and older browsers, and both are available in the latest browsers.
  6. To sum up, Vue uses textContent from a performance perspective.

Test the innerText and textContent performance

<ul class="list">
  <li>1</li>
  <! -- omitted 998
  <li>1000</li>
</ul>
Copy the code
const oList = document.getElementById("list");

console.time("innerText");
for(let i = 0; i < oList.childElementCount; i++){
  ul.children[i].innerText="innerText";
}
console.timeEnd("innerText");

console.time("textContent");
for(let i = 0; i < oList.childElementCount; i++){
  ul.children[i].textContent="innerText";
}
console.timeEnd("textContent");
Copy the code

v-html

  • Updates the innerHTML of the element
  • Pay attention to: Content is inserted as normal HTML and will not be compiled as a Vue template
  • Dynamically rendering arbitrary HTML on a website is very dangerous because it is prone to XSS attacks. Use V-HTML only for trusted content, never for user-submitted content.
    <input type="text" />
    <button>Click on the</button>
    <div id="app">
      <div v-html="msg"></div>
    </div>
    Copy the code
    const vm = new Vue({
      el: '#app'.data: {
        msg: 'hello world'}})const oInput = document.getElementsByTagName('input') [0];
    const oButton = document.getElementsByTagName('button') [0];
    let msg = null;
    oButton.onclick = function () {
      vm.msg = oInput.value;
    }
    Copy the code

Conditions apply colours to a drawing

v-if

  • Used to conditionally render a piece of content. This content will only be rendered if the expression of the directive returns truthy.

Switching between multiple elements

  • Because v-if is an instruction, it must be added to one element, but what if you want to switch multiple elements? Now you can put one<template>The element is treated as an invisible wrap element and v-if is applied to it. The final render result will not contain<template>The element
    <template v-if="ok">
      <h1>Title</h1>
      <p>Paragraph 1</p>
      <p>Paragraph 2</p>
    </template>
    Copy the code

v-else

  • Add “else block” for V-if or V-else -if.
  • Pay attention to: The previous sibling element must have v-if or V-else -if
    <div v-if="Math. The random () > 0.5">shanshan</div>
    <div v-else>You can't see Shanshan</div>
    Copy the code

v-else-if

  • “Else if block” for V-if. You can call it chained.
  • Pay attention to: The previous sibling element must have v-if or V-else -if
    <div v-if="type === 'A'">
      A
    </div>
    <div v-else-if="type === 'B'">
      B
    </div>
    <div v-else-if="type === 'C'">
      C
    </div>
    <div v-else>
      Not A/B/C
    </div>
    Copy the code

v-show

  • Toggles the element’s display CSS property based on the expression’s true or false value.
    <h1 v-show="ok">Hello!</h1>
    Copy the code

v-if VS v-show

  1. V-if is lazy and does nothing if the condition is false during the initial rendering, until the condition is true for the first time and the conditional block is rendered. With V-show, elements are always rendered regardless of initial conditions and are simply switched based on CSS.
  2. V-if has a higher switching overhead, V-show has a higher initial rendering overhead, v-show is better if you need to switch very frequently, and v-if is better if conditions change very little at run time
  3. V – show does not support<template>The element
  4. V-show does not support V-else/V-else -if

V – the bind command

  • Dynamically bind one or more features

  • : Indicates the passed parameter

    <! -- Bind a property -->
    <img v-bind:src="imageSrc">
    
    <! -- Dynamic feature name (2.6.0+) -->
    <button v-bind:[key] ="value"></button>
    
    <! - for - >
    <img :src="imageSrc">
    
    <! -- Dynamic feature name abbreviation (2.6.0+) -->
    <button :[key] ="value"></button>
    
    <! Inline string concatenation -->
    <img :src="'/path/to/images/' + fileName">
    Copy the code
  • With no arguments, you can bind to an object that contains key-value pairs. Note that the class and style bindings do not support arrays and objects at this time.

    <! -- Bind an object with attributes -->
    <div v-bind="{ id: someProp, 'other-attr': otherProp }"></div>
    Copy the code
  • Because string concatenation is cumbersome and error-prone, Vue has enhanced it when binding class or style features to allow expressions to be arrays or objects in addition to strings.

    • The binding class
      • Object syntax

        <div v-bind:class="{ red: isRed }"></div>
        Copy the code

        The syntax above indicates that the existence of the active class depends on whether the data attribute isActive is true or false.

      • Array syntax We can apply a class list by passing an array to V-bind :class

        <div v-bind:class="[classA, classB]"></div>
        Copy the code
      • In array syntax you can always switch classes using ternary expressions

        <div v-bind:class="[isActive ? activeClass : '', errorClass]"></div>
        Copy the code
      • You can use object syntax in array syntax

          <div v-bind:class="[classA, { classB: isB, classC: isC }]">
          <div v-bind:class="classA" class="red">
        Copy the code
      • V-bind: Classes can coexist with regular classes

          <div v-bind:class="classA" class="red">
        Copy the code
    • The binding style
      • Using object syntax looks a lot like CSS, but it’s actually a JavaScript object and the CSS property names can be camelCase or kebab-case but if you’re using a kebab-case, you’re going to put it in quotes
        <div v-bind:style="{ fontSize: size + 'px' }"></div>
        Copy the code
        data: {
          size: 30
        }
        Copy the code

        You can also bind a style object directly to make the template clearer:

        <div v-bind:style="styleObject"></div>
        Copy the code
        data: {
          styleObject: {
            fontSize: '13px'}}Copy the code
      • Using array syntax Array syntax allows you to apply multiple style objects to the same element
        <div v-bind:style="[styleObjectA, styleObjectB]"></div>
        Copy the code
      • Automatically prefix binding style. CSS properties that require a browser engine prefix, such as transform, vue.js, will automatically detect and add the corresponding prefix.
      • Multiple Values Since 2.3.0 you can provide an array of multiple values for a property in the style binding, often used to provide multiple prefixed values:
        <div v-bind:style="{ display: ['-webkit-box', '-ms-flexbox', 'flex'] }"></div>
        Copy the code

        This only renders the last value in the array that is supported by the browser. In this case, if the browser supports flexbox without the browser prefix, only display: flex will be rendered.

  • Abbreviations: :

  • Modifier: Modifier is a special suffix specified by the period. Used to indicate that an instruction should be bound in a particular way.

    • .camel converts uppercase letters to lowercase letters due to the binding feature, such as:

      <! < SVG viewbox="0 0 100 100"></ SVG > -->
      <svg :viewBox="viewBox"></svg>
      Copy the code

      Therefore, Vue provides the V-bind modifier Camel, which allows the v-bind attribute names to be humped when using DOM templates, such as the viewBox attribute of SVG

      <svg :view-box.camel="viewBox"></svg>
      Copy the code
    • .prop is used to bind DOM properties.

      <div v-bind:text-content.prop="text"></div>
      Copy the code
    • Sync will explain the components

V – on command

  • The V-ON directive listens for DOM events and runs some JavaScript code when triggered

  • The event type is specified by the parameter

    <div id="app">
      <button v-on:click="counter += 1">Click on add 1</button>
      <p>The button was clicked {{counter}} times</p>
    </div>
    Copy the code
    const vm = new Vue({
      el: 'app'.data: {
        counter: 0}})Copy the code
  • But much of the event-handling logic is very complex, so it’s not feasible to write JavaScript code directly into v-ON instructions. So V-ON can also receive a method name that needs to be called.

    <div id="app">
      <! -- 'addCounter' is the name of the method defined below -->
      <button v-on:click="addCounter">Click on add 1</button>
      <p>The button was clicked {{counter}} times</p>
    </div>
    Copy the code
    const vm = new Vue({
      el: '#app'.data: {
        counter: 0
      },
      // Define methods in the methods object
      methods: {
        addCounter: function (e) {
          // This refers to the current Vue instance in the method
          this.counter += 1;E is a native DOM eventCosnole. Log (e. arget); }}})Copy the code
  • Methods also delegate directly to Vue instance objects, so they can be run directly:

      vm.addCounter();
    Copy the code
  • In addition to binding directly to a method, you can also call a method in an inline JavaScript statement:

    <div id="app">
      <button v-on:click="addCounter(5)">Click on add 5</button>
      <p>The button was clicked {{counter}} times</p>
    </div>
    Copy the code
    new Vue({
      el: '#app'.data: {
        counter: 0
      },
      methods: {
        addCounter: function (num) {
          this.counter += 5; }}})Copy the code
  • When you use event objects in associative sentences, you can use the special variable $event:

    <div id="app">
     <button v-on:click="addCounter(5, $event)">Click on add 5</button>
     <p>The button was clicked {{counter}} times</p>
    </div>
    Copy the code
    new Vue({
      el: '#app'.methods: {
        addCounter: function (num, e) {
          this.counter += 5;
          cosnole.log(e.target);        
        }
      }
    })
    Copy the code
  • Dynamic events can be bound. Vue version requires 2.6.0+

    <div v-on:[event] ="handleClick">Click, it pops up 1</div>  
    Copy the code
    const vm = new Vue({
      el: '#app'.data: {
        event: 'click'
      },
      methods: {
        handleClick () {
          alert(1); }}})Copy the code
  • It is possible to bind an object without arguments. Vue version requires 2.4.0+.

    • {event name: event execution function}
    • Function pass-arguments & modifiers are not supported using this method
    <div v-on="{ mousedown: doThis, mouseup: doThat }"></div>
    Copy the code
  • Short for the V-ON command: @

Why listen for events in HTML?

  1. A glance at an HTML template makes it easy to locate the corresponding method in JavaScript code.
  2. Because you don’t have to manually bind events in JavaScript, your ViewModel code can be very logical and completely decoupled from DOM, making it easier to test
  3. When a ViewModel is destroyed, all event handlers are automatically removed. Don’t you have to worry about cleaning them up

Modifier of the V-ON instruction

Event modifier

.stop

  • Call event.stop to stop the event from bubbling
    <! Button -->
    <div id="app">
      <div @click="alert('div')">
        <button @click.stop="alert('button')">Click on the</button>
      </div>
    </div>
    Copy the code
    const vm = new Vue({
      el: '#app'.methods: {
        alert(str){ alert(str); }}})Copy the code

.prevent

  • Call event.preventDefault() to prevent the default event
    <! -- The page will not reload after clicking submit button -->
    <div id="app">
      <form v-on:submit.prevent="onSubmit">
        <input type="submit">
      </form>
      <! -- can also have only modifiers -->
      <form v-on:submit.prevent>
        <input type="submit">
      </form>
    </div>
    Copy the code
    const vm = new Vue({
      el: '#app'.methods: {
        onSubmit() { console.log('submit'); }}})Copy the code

.capture

  • Event capture mode
    <! Insert div into button -->
    <div id="app">
      <div @click.capture="alert('div')">
        <button @click="alert('button')">Click on the</button>
      </div>
    </div>
    Copy the code
    const vm = new Vue({
      el: '#app'.methods: {
        alert(str) { alert(str) }
      }
    })  
    Copy the code

.self

  • The callback is fired only if the event is fired from the listener bound element itself

    <! -- Click button, only popup button -->
    <div id="app">
      <div id="app">
        <div :style="{ backgroundColor: 'red' }" 
        @click.self="alert('div')">
          <button @click="alert('button')">Click on the</button>
        </div>
      </div>
    </div>
    Copy the code
    const vm = new Vue({
      el: '#app'.methods: {
        alert(str) { alert(str) }
      }
    })
    Copy the code

.once

  • Only one callback is triggered

  • 2.1.4 new

    Click the button button twice to pop up the button once<div id="app">
      <button @click.once="alert('button')">Click on the</button>
    </div>
    Copy the code
    const vm = new Vue({
      el: '#app'.methods: {
        alert(str) { alert(str) }
      }
    })
    Copy the code

.passive

  • Set Passive in addEventListener
  • It can improve the performance of the mobile terminal
  • 2.3.0 new

According to the passive?

  • Even if an empty function is executed when the touch event is triggered, the page freezes. Because the browser doesn’t know whether the listener will block the default event, the browser waits until the function is complete before deciding whether to scroll the page. Passive listener, which allows the developer to tell the browser that the listener will not block the default behavior, so that the browser can scroll through the page with confidence. This can greatly improve the performance of mobile pages, as it is estimated that only 20% of touch events block the default event.
  • .passive tells the browser that you do not want to block the event’s default behavior

Pay attention to

  1. When using modifiers, order is important. The corresponding code is generated in the same order. As a result,

V-on :click.self. Self will block all clicks on the default event v-on:click.self. Prevent will block only clicks on the element itself. Do not use.passive with.prevent, as.prevent will be ignored and the browser may show you a warning.

Key modifier

When listening for keyboard events, we often need to check for detailed keystrokes. Vue allows you to add key modifiers for V-Ons when listening for keyboard events

<! -- call 'vm.submit()' only if 'key' is' Enter '-->
<input v-on:keyup.enter="submit">
Copy the code

You can directly convert any valid keyname exposed by keyboardevent. key to kebab-case as a modifier.

<input v-on:keyup.page-down="onPageDown">
Copy the code

In the example above, the handler is only called when $Event. key equals PageDown.

The key code

Using the keyCode feature is also allowed:

<! The return key triggers the execution of the Submit function
<input v-on:keyup.13="submit">
Copy the code

Note: keyCode’s event usage is deprecated and may not be supported by the latest browsers.

To support older browsers if necessary, Vue provides aliases for most commonly used keycodes:

  • .Enter (Enter)
  • .tab
  • .delete (capture the delete and backspace keys)
  • .esc
  • .space (space bar)
  • .up (arrow key up)
  • .down (arrow down key)
  • .left (arrow left key)
  • .right (right arrow)

In addition to using the key aliases provided by Vue, you can also customize key aliases:

// Global configuration
// You can use 'V-on :keyup.f1'
Vue.config.keyCodes.f1 = 112
Copy the code
Vue.config.keyCodes = {
  v: 86.f1: 112.// Small hump is not available
  mediaPlayPause: 179.// Instead, they are delimited by short lines and enclosed in double quotation marks
  "media-play-pause": 179.up: [38.87]}Copy the code
<input type="text" @keyup.media-play-pause="method">
Copy the code

System modifier key

You can use the following modifier to implement a listener that fires a mouse or keyboard event only when the corresponding key is pressed. The modifier key differs from a regular key in that it must be in the pressed state when the keyup event is triggered. In other words, keyup.ctrl can only be triggered when CTRL is held down and other keys are released. Releasing the CTRL alone will not trigger the event. If you want this behavior, use keyCode: keyup.17 for CTRL instead.

  • .ctrl
  • .alt
  • .shift
  • .meta On the Mac keyboard, meta corresponds to the Command key (⌘). The Windows keyboard meta corresponds to the Windows logo key (⊞). On the Sun OS keyboard, meta corresponds to a solid gem key (◆). On other specific keyboards, notably those on MIT and Lisp machines, and on subsequent products such as the Knight keyboard and space-Cadet keyboard, meta is marked as “meta”. On the Symbolics keyboard, meta is marked as “meta” or “meta”
<! -- Alt + C -->
<input @keyup.alt.67="clear">

<! -- Ctrl + Click -->
<div @click.ctrl="doSomething">Do something</div>
Copy the code

Exact modifier

  • Allows you to control events triggered by the exact combination of system modifiers.
  • 2.5.0 +
<! -- Trigger even when Alt or Shift is pressed together -->
<button @click.ctrl="onClick">A</button>

<! -- Triggered only when Ctrl is pressed -->
<button @click.ctrl.exact="onCtrlClick">A</button>

<! -- triggered when no system modifier is pressed -->
<button @click.exact="onClick">A</button>
Copy the code

Mouse button modifier

  • The execution function is processed only when a particular mouse button is clicked
  • 2.2.0 +
  • .left
  • .right
  • .middle

The list of rendering

Render elements multiple times based on the data using the V-for directive.

Use arrays in V-for

Parameters: items: source data array item: array element alias index: Optional, index has access to all attributes of the parent scope

<ul id="app">
  <li v-for="(person, index) in persons">
    {{ index }}---{{ person.name }}---{{ person.age }}
  </li>
</ul>
Copy the code
const vm = new Vue({
  el: '#app'.data: {
    persons: [{name: 'very'.age: 18 },
      { name: 'Si Tong Brother'.age: 20 },
      { name: 'as elder brother'.age: 22 },
      { name: 'Deng Ge'.age: 88},]}})Copy the code

We can use of instead of in as a separator because it is closer to the iterator syntax:

<div v-for="item of items"></div>
Copy the code

Use objects in V-for

Usage: (value, key, index) in Object Parameter: value: Object value key: optional, key name index: optional, index

<ul id="app">
  <li v-for="(value, key, index) in shan">
    {{ value }}
  </li>
</ul>
Copy the code
const vm = new Vue({
  el: '#app'.data: {
    shan: {
      name: 'the Chinese fir.age: 18.height: '163cm'}}})Copy the code

Use numbers in V-for

N in num Parameter: n: a number, starting from 1

<div>
  <span v-for="n in num">{{ n }} </span>
</div>
Copy the code
const vm = new Vue({
  el: '#app'.data: {
    num: 10}})Copy the code

Use strings in v-for

Usage: STR in string Parameter: STR: string, each in the source data string

<div>
  <span v-for="str in string">{{ str }} </span>
</div>
Copy the code
const vm = new Vue({
  el: '#app'.data: {
    string: 'shanshan'}})Copy the code

Loop through a section of content that contains multiple elements

You can use the Template element to loop through a section of content that contains multiple elements

<ul id="app">
  <template v-for="person in persons">
    <li>{{ item.msg }}</li>
    <li>Ha ha</li>
  </template>
</ul>
Copy the code
const vm = new Vue({
  el: '#app'.data: {
    persons: ['shan'.'jc'.'cst'.'deng']}})Copy the code

About the key

When Vue updates a list of elements rendered using V-for, it defaults to an “update in place” policy. If the order of data items is changed, Vue will not move DOM elements to match the order of data items, but simply reuse each element here:

<ul id="app">
  <li v-for="(person, index) in persons">
    {{ person }}
    <input type="text" />
    <button @click="handleClick(index)">Move down</button>
  </li>
</ul>
Copy the code
const vm = new Vue({
  el: '#app'.data: {
    persons: ['shan'.'jc'.'cst'.'deng']},methods: {
    handleClick (index) {
      const deleteItem = this.persons.splice(index, 1);
      this.persons.splice(index + 1.0. deleteItem); }}})Copy the code

In the “reuse in place” strategy, when the button is clicked, the input field does not move down with the text because the input field is not bound to the data, so vuejs uses the rendered DOM by default, whereas the text is bound to the data, so the text is re-rendered. This approach is the default list rendering strategy in VUE because it is efficient.

This default mode is effective, but at more of time, we don’t need to deal with this, so, in order to give the Vue a prompt, so that it can track the status of each node, thus reuse and reordering existing elements, we need to provide a unique key characteristics for each item, the Vue will rearrange the elements based on the key changes, It also removes elements where the key does not exist.

How to use key

Expected value: number | string with the same parent child element must have a unique key, repeat the key causes rendering errors, the key should be the only.

<ul id="app">
  <li v-for="(person, index) in persons" :key="person">
    {{ person }}
  </li>
</ul>
Copy the code
const vm = new Vue({
  el: '#app'.data: {
    persons: ['very'.'Si Tong Brother'.'as elder brother'.'Deng Ge']}})Copy the code

It is not recommended to use the array index as the key, for example:

<li v-for="(person, index) in persons" :key="index">
  {{ person }}
</li>
Copy the code

When the array is changed, the page is re-rendered and Vue decides whether to move the element based on the key value. For example, when the page is re-rendered, the element with key “Shanshan” is

  • Shanshan
  • , and before the page is re-rendered, the element with key “Shanshan” is

  • Shanshan
  • , then Vue moves the Li element instead of re-creating an element. When using the array index as the key values, page rendering, the key of the element value will be assigned again, we’ll inversion array, for example, before the reverse: element | | key values

    • | : – : |

    < li > shanshan < / li > | | 0 < li > think red elder brother < / li > | 1 | < li > as elder brother < / li > | 2 | < li > Deng Ge < / li > | 3 | after the reverse: element | | key values

    • | : – : |

    < li > Deng Ge < / li > | | 0 < li > as elder brother < / li > | 1 | < li > think red elder brother < / li > | 2 | < li > shanshan < / li > | 3 | Vue comparison before and after rendering has the same key elements, found that there is a change, will be recycled into an element, If it is worthwhile to use the index as the key, all elements will be regenerated at this point.

    So how is key unique?

    When collaborating with the background, each piece of data returned has an ID value, which is unique and can be used as a key by ID.

    Key is not only owned by V-for, it forces the element to be replaced instead of reusing it:

    <ul id="app">
      <button @click="show = ! show">{{ show ? 'Show' : 'hide '}</button>
      <input type="text" v-if="show" key="a" />
      <input type="text" v-else key="b" />
    </ul>
    Copy the code
    const vm = new Vue({
      el: '#app'.data: {
        show: true}})Copy the code

    V-for and v-if are used together

    Never use v-if and V-for on the same element. When Vue processes instructions, V-for takes precedence over V-if, so this template:

    <ul>
      <li
        v-for="user in users"
        v-if="user.isActive"
        :key="user.id"
      >
        {{ user.name }}
      </li>
    </ul>
    Copy the code

    The following operation will be performed:

    this.users.map(function (user) {
      if (user.isActive) {
        return user.name
      }
    })
    Copy the code

    So even if we render elements for only a small number of users, we have to traverse the entire list every time we re-render, regardless of whether the active users have changed. Therefore, the following two scenarios can be handled as follows:

    1. To filter items in a list.
    <ul id="app">
      <li
        v-for="user in users"
        v-if="user.isActive"
        :key="user.id"
      >
        {{ user.name }}
      </li>
    </ul>
    Copy the code
    const vm = new Vue({
      el: '#app'.data: {
        users: [{name: 'shan'.isActive: true.id: 1},
          { name: 'jc'.isActive: false.id: 2},
          { name: 'cst'.isActive: false.id: 3},
          { name: 'deng'.isActive: true.id: 4},]}})Copy the code

    You can update the above code to:

    <! Get a new array from the original array. Render the new array.
    <ul>
      <li
        v-for="user in activeUsers"
        :key="user.id"
      >
        {{ user.name }}
      </li>
    </ul>
    Copy the code
    const vm = new Vue({
      el: '#app'.data: {
        users: [{name: 'shan'.isActive: true.id: 1},
          { name: 'jc'.isActive: false.id: 2},
          { name: 'cst'.isActive: false.id: 3},
          { name: 'deng'.isActive: true.id: 4},].activeUsers: []
      }
    })
    vm.activeUsers = vm.users.filter(user= > user.isActive);
    Copy the code

    This method is for demonstration only, after learning the calculated properties, you will use the calculated properties to do.

    1. To avoid rendering lists that should be hidden
    <ul>
      <li
        v-for="user in users"
        v-if="shouldShowUsers"
        :key="user.id"
      >
        {{ user.name }}
      </li>
    </ul>
    Copy the code
    const vm = new Vue({
      el: '#app'.data: {
        users: [{name: 'shan'.isActive: true.id: 1},
          { name: 'jc'.isActive: false.id: 2},
          { name: 'cst'.isActive: false.id: 3},
          { name: 'deng'.isActive: true.id: 4},].shouldShowUsers: false}})Copy the code

    The HTML section can be replaced with:

    <ul v-if="shouldShowUsers">
      <li
        v-for="user in users"
        :key="user.id"
      >
        {{ user.name }}
      </li>
    </ul>
    Copy the code

    By putting v-if on the outer element, we no longer check shouldShowUsers for every user in the list. Instead, we only check it once and don’t do v-for if shouldShowUsers is no.

    Exercise _ Imitation Taobao commodity screening

    The CSS file is in the folder, and the required data is copied:

    goodsList: [
      {
        title: 'with'.typeList: ['all'.'knitwear'.'Woolen coat'.'T shirt'.'Down jacket'.'cotton-padded clothes'.'who the clothes'.'trench coat'].id: 1}, {title: 'trousers'.typeList: ['all'.'Jeans'.'Little Feet/Pencil Pants'.'Casual pants' ,'Leggings'.'Harlan pants'].id: 2}, {title: 'skirt'.typeList: ['all'.'Dress'.'Skirt'.'Long Sleeve dress'.'Medium length Dress'].id: 3,}]Copy the code

    Practice _todoList

    Copy the CSS file to the folder

    V – model instruction

    You can create two-way data binding on form elements. That is, data updates element updates, and element updates data.

    Essentially v-models are syntactic sugar

    The element type attribute The event
    Input type = text, textarea value input
    Input (checkbox), input (radio) checked change
    select value change

    input

    Type = “text text boxes

    <div id="app">
      <input v-model="message">
      <p>Message is: {{Message}}</p>
    </div>
    Copy the code
    const vm = new Vue({
      el: '#app'.data:; {
        message: ' '}})Copy the code

    Type = checkbox check box

    Single check box

    Bind to Boolean, v-model=”Boolean”

    <div id="app">
      <input 
        type="checkbox" 
        id="checkbox" 
        v-model="checked"
      />
      <label for="checkbox">{{ checked }}</label>
    </div>
    Copy the code
    const vm = new Vue({
      el: '#app'.data: {
        checked: true}})Copy the code

    Multiple check boxes

    Bound to the same Array, the value in the V-model =”Array” Array is the value of the selected input box

    <div id="app">
      <input type="checkbox" id="cheng" value="A brother" v-model="checkedNames">
      <label for="cheng">As a brother</label>
    
      <input type="checkbox" id="deng" value="Deng Ge" v-model="checkedNames">
      <label for="deng">Deng Ge</label>
      
      <input type="checkbox" id="tong" value="Si Tong Brother" v-model="checkedNames">
      <label for="tong">Think red elder brother</label>
      <br>
      <span>The selected people are: {{checkedNames}}</span>
    </div>
    Copy the code
    const vm = new Vue({
      el: '#app'.data: {
        checkedNames: []}})Copy the code

    Type = radio radio

    The bound data is synchronized with the value

    <div id="app">
      <input type="radio" id="cheng" value="A brother" v-model="picked">
      <label for="cheng">As a brother</label>
      <input type="radio" id="deng" value="Deng Ge" v-model="picked">
      <label for="deng">Deng Ge</label>
      <input type="radio" id="tong" value="Si Tong Brother" v-model="picked">
      <label for="deng">Think red elder brother</label>
      <br>
      <span>Selected person: {{picked}}</span>
    </div>
    Copy the code
    const vm = new Vue({
      el: '#app'.data: {
        picked: ' '}})Copy the code

    textarea

    <div id="app">
      <p >Multi-line text: {{message}}</p>
      <textarea v-model="message" placeholder="Add text"></textarea>
    </div>
    Copy the code
    const vm = new Vue({
      el: '#app'.data: {
        message: ' '}})Copy the code

    select

    The matched value is the Chinese character in option

    The radio

    <div id="app">
      <select v-model="selected">
        <option>A</option>
        <option>B</option>
        <option>C</option>
      </select>
      <span>Select: {{selected === 'please select'? '' : selected }}</span>
    </div>
    Copy the code
    const vm = new Vue({
      el: '#app'.data: {
        selected: 'Please select'}})Copy the code

    Note: If the initial value of the V-model expression does not match any of the options, the

    <div id="app">
      <select v-model="selected">
        <option :disabled="selected">Please select a</option>
        <option>A</option>
        <option>B</option>
        <option>C</option>
      </select>
      <span>Select: {{selected === 'please select'? '' : selected }}</span>
    </div>
    Copy the code

    multi-select

    Bind to an array

    <div id="app">
      <select v-model="selected" multiple>
        <option>A</option>
        <option>B</option>
        <option>C</option>
      </select>
      <span>Select: {{selected}}</span>
    </div>
    Copy the code
    const vm = new Vue({
      el: '#app'.data: {
        selected: []}})Copy the code

    The modifier

    .lazy

    By default, v-Model synchronizes the value of the input box with the data after each input event is triggered. To change to using change event synchronization, add the lazy modifier:

    <! Update "change" instead of "input" -->
    <input v-model.lazy="msg" >
    Copy the code

    .number

    Automatically converts user input values to numeric types:

    <input v-model.number="age" type="number">
    Copy the code

    .trim

    Automatically filter the first and last whitespace characters entered by the user:

    <input v-model.trim="msg">
    Copy the code

    Exercise _ Simple calculator

    Exercise _ questionnaire

    questionList: [
      {
        type: 'short'.title: May I have your name, please '.chooseList: null.answer: ' '.id: 0
      },
      {
        type: 'single'.title: What's your gender, please '.chooseList: [
          'male'.'woman'.'secret',].answer: ' '.id: 1}, {type: 'multiple'.title: '3. Please select your hobbies: '.chooseList: [
          'read'.'swimming'.'running'.'Go to the movies'.'Listen to music',].answer: [].id: 2}, {type: 'long'.title: 4. Please introduce yourself:.chooseList: null.answer: ' '.id: 3,},]Copy the code

    Calculate attribute

    Sometimes we put too much logic into templates, which makes them too heavy and difficult to maintain. Such as:

    <div id="app">
      {{ message.split('').reverse().join('') }}
    </div>
    Copy the code

    In this case, it takes a while to realize that we want to display the flipped string of the variable Message, and it gets even more troublesome when we want to use the flipped string multiple times in the template. Therefore, whenever we deal with complex logic, we should use computed properties.

    Basic usage

    Calculated properties are properties in the Vue configuration object and can be used as follows:

    <div id="app">
      <! The value of the calculated property can be used directly, just like data.
      {{ someComputed }}
    </div>
    Copy the code
    const vm = new Vue({
      el: '#app'.computed: {
        // Returns the value of the calculated property
        someComputed () {
          return 'some values'}}})Copy the code

    For example, if we want to get the inverted string of a string, we can do this using the computed property:

    <div id="app">
      <p>Original string: "{{MSG}}"</p>
      <p>"{{reversedMsg}}"</p>
    </div>
    Copy the code
    const vm = new Vue({
      el: '#app'.data: {
        msg: 'Hello'
      },
      computed: {
        reversedMsg: function () {
          return this.msg.split(' ').reverse().join(' '); }}})Copy the code

    As you can see, the value of reversedMsg depends on the value of MSG, so when we change the value of MSG, the value of reversedMsg also changes.

    Evaluate properties vs methods

    In fact, the above functions can also be achieved by using methods, such as:

    <div id="app">
      <p>Original string: "{{MSG}}"</p>
      <p>ReversedMsg ()}}</p>
    </div>
    Copy the code
    const vm = new Vue({
      el: '#app'.data: {
        msg: 'Hello'
      },
      methods: {
        reversedMsg: function () {
          return this.msg.split(' ').reverse().join(' '); }}})Copy the code

    While calling a method in an expression can achieve the same effect, there is a fundamental difference between using computed properties and using methods. When using methods, each time the page is re-rendered, the corresponding method is re-executed, as in:

    <div id="app">
      <p>{{ name }}</p>
      <p>{{ reversedMsg() }}</p>
    </div>
    Copy the code
    const vm = new Vue({
      el: '#app'.data: {
        msg: 'Hello'.name: 'shanshan'
      },
      methods: {
        reversedMsg: function () {
          console.log('Method executed');
          return this.msg.split(' ').reverse().join(' ');
        }
      }
    })
    vm.name = 'duyi';  
    Copy the code

    In the example above, we can see that once the value of name is changed, the page will be re-rendered. At this point, the console prints out a string that means the reversedMsg function has been executed, but we don’t need the method to execute because the changed data has nothing to do with the function. If the logic inside the function is complex, it can be a drain on performance.

    However, there will be no such phenomenon by using the calculated attribute, such as:

    const vm = new Vue({
      el: '#app'.data: {
        msg: 'Hello'.name: 'shanshan'
      },
      computed: {
        reversedMsg: function () {
          console.log('Calculation performed');
          return this.msg.split(' ').reverse().join(' ');
        }
      }
    })
    vm.name = 'duyi';  
    Copy the code

    You can see at this point that when the data name is reassigned, the evaluated property is not executed. Therefore, the essential difference between a computed property and a method is that the computed property is cached based on reactive dependencies. The value of the computed property remains in the cache as long as the data on which it depends does not change. Each access to the computed property immediately returns the cached result, rather than executing the function again. Methods, on the other hand, will always execute the function again every time a re-render is triggered.

    So why cache?

    Let’s say we have A calculation property, A, that needs to iterate over A huge array and do A huge calculation. Then we need to use this calculation property A, and if there is no cache, we will execute A’s function again, and the performance cost becomes very high.

    Computing attributes in depth

    The calculated property can be written as an object in addition to a function. The object has two properties, getter&setter, which are functions, written as follows: getter&setter

    const vm = new Vue({
      el: '#app'.computed: {
        fullName: {
          getter () {
            // Some code
          },
          setter () {
            // Some code}}}})Copy the code

    Getter read

    Earlier, we wrote the calculated property directly as a function, called the getter function. That is, by default, computed properties only have getters. This, of the getter, is automatically bound as a Vue instance.

    When will it be implemented?

    When we get a calculated property, we execute the get function.

    const vm = new Vue({
      el: '#app'.data: {
        msg: 'Hello'
      },
      computed: {
        reversedMsg: {
          getter () {
            return this.msg.split(' ').reverse().join(' '); }}}})Copy the code

    Setter to set

    Optional, the set function is executed when reassigning a calculated property. Parameter: the value to be reset. The this of the setter is automatically bound to a Vue instance.

    const vm = new Vue({
      el: '#app'.data: {
        msg: 'Hello'.firstStr: ' '
      },
      computed: {
        reversedMsg: {
          getter () {
            return this.msg.split(' ').reverse().join(' ');
          },
          setter (newVal) {
            this.firstStr = newVal[0]; }}}})Copy the code

    Note that the computed property does not change even if a value is assigned to it. Again, the computed property is recalculated only if the dependent reactive property changes.

    Exercise _ Name filtering

    personArr: [
      { 
        name: 'wang Hong Kong'.src: 'https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=4005587090, & FM = 26 & gp = 0. 2408158268 JPG'.des: 'Poor cervical spine'.sex: 'm'.id: '056482' 
      },
      { 
        name: 'Emily'.src: 'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1571915784984&di=a0056fd06188e87b922c60878e5ce6e2&i mgtype=0&src=http%3A%2F%2Fpic.51yuansu.com%2Fpic3%2Fcover%2F03%2F79%2F64%2F5c05df1faf3b7_610.jpg'.des: 'Who am I?'.sex: 'f'.id: '157894' 
      },
      { 
        name: 'Liu Xiuying'.src: 'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1571915803971&di=47dc968f55b16a461de3e8f25bdf8600&i mgtype=0&src=http%3A%2F%2Fimg.duoziwang.com%2F2016%2F11%2F27%2F190426198344.jpg'.des: 'I'm pretty good looking'.sex: 'f'.id: '2849245' 
      },
      { 
        name: 'Jinlei Liu'.src: 'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1571915748758&di=5be825da4d37bcc21959946c101d5609&i mgtype=0&src=http%3A%2F%2Fb-ssl.duitang.com%2Fuploads%2Fitem%2F201707%2F19%2F20170719211350_4PnBt.jpeg'.des: 'You've never seen a strange face'.sex: 'm'.id: '348515' 
      },
      { 
        name: 'Liu Fei'.src: 'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1571915762633&di=49517ca62ecddb638cdfb2158a64e39a&i mgtype=0&src=http%3A%2F%2Fb-ssl.duitang.com%2Fuploads%2Fitem%2F201702%2F05%2F20170205222154_WLdJS.jpeg'.des: 'Rind liu'.sex: 'm'.id: '478454'}].Copy the code

    Exercise _ Choose all goods

    courseList: [
      {
        poster: 'https://img.alicdn.com/bao/uploaded/i1/TB1VtAgdlWD3KVjSZFs3KIqkpXa_040950.jpg_80x80.jpg'.title: 'An in-depth Analysis of Duyi Education CSS3'.price: 1299.cart: 1.id: 0
      },
      {
        poster: 'https://img.alicdn.com/bao/uploaded/i7/TB1_VJecBWD3KVjSZKPagip7FXa_045814.jpg_80x80.jpg'.title: 'Duyi Education Mobile Terminal Development Course'.price: 1148.cart: 1.id: 1595402664708
      },
      {
        poster: 'https://img.alicdn.com/bao/uploaded/i2/TB1J.Q4cQxz61VjSZFto7uDSVXa_010347.jpg_80x80.jpg'.title: 'Duyi Education 2019 HTMLCSS Zero Basic Entry Guide'.price: 1.cart: 1.id: 1596305473062
      },
      {
        poster: 'https://img.alicdn.com/bao/uploaded/i2/TB1bHwlaCWD3KVjSZSgVbgCxVXa_032434.jpg_80x80.jpg'.title: Duyi Education Web Front-end Development JavaScriptJs class.price: 1.cart: 1.id: 1595413512182
      },
      {
        poster: 'https://img.alicdn.com/bao/uploaded/i2/TB1MJd3g4z1gK0jSZSgnHevwpXa_014447.jpg_80x80.jpg'.title: 'Web Front-end Development Senior Engineer Full Stage class '.price: 12798.cart: 1.id: 1596302161181
      },
      {
        poster: 'https://img.alicdn.com/bao/uploaded/i6/TB1xPeAbwaH3KVjSZFpjaLhKpXa_105848.jpg_80x80.jpg'.title: Java Zero Basics to Mastery (Collections, generics, etc.).price: 1.cart: 1.id: 1596300025301,},]Copy the code

    The listener

    Listen for properties, respond to changes in data (data&computed), and execute functions immediately when the data changes.

    Value types

    Function types

    Ex. :

    const vm = new Vue({
      el: '#app'.data: {
        msg: 'Hello, hello, I'm Shan Shan',},watch: {
        msg () {
          console.log('MSG value changed ~'); }}})// Change the MSG value
    vm.msg = 'hello~~~~'; // This will print 'MSG value changed' in the console
    Copy the code

    The listener function takes two arguments, the first being newVal(the changed data) and the second oldVal(the value before assigning the new value). As in the code above, change the listener Watch as follows:

    watch: { msg (newVal,oldVal) { conosle.log(newVal, oldVal); }}// Change the MSG value
    vm.msg = 'hello~~~~'; // It will print 'hello, hello, I am Shanshan hello~~~~' in the console
    Copy the code

    String type

    Value is the name of the method that is executed when the data being listened for changes.

    const vm = new Vue({
      el: '#app'
      data: {
        msg: 'very'
      },
      watch: {
        msg: 'msgChange'
      },
      methods: {
        msgChange () {
          console.log('MSG has changed');
        }
      }
    })
    vm.msg = 'hello'; // The msgChange function will be executed and the console will print 'MSG has changed'
    Copy the code

    Object type

    When written as an object type, options can be provided.

    handler

    A necessity. Handler A callback function that is executed when the data being listened for changes. Handler’s value type is function/string, which, when written as a string, is the name of a method.

    const vm = new Vue({
      el: '#app'
      data: {
        msg: 'very'
      },
      watch: {
        msg: {
          handler () {
            console.log('MSG has changed');
          }
        }
      }
    })
    vm.msg = 'hello'; // The callback will execute and the console will print 'MSG has changed'
    Copy the code

    deep

    By default, a listener listener listens for reference changes only, and it can only be listened for when an object is assigned a value. Use the deep option to detect changes in the object’s internal values. Set deep to true, and the object will be listened to no matter how deep it is nested.

    const vm = new Vue({
      el: '#app'
      data: {
        personObj: {
          name: 'Deng Xuming'.age: 88}},watch: {
        personObj: {
          handler () {
            console.log('Object's value has changed'); },deep: true   // Enable deep listening
        }
      }
    })
    vm.obj.name = 'Old Deng Head'; // The callback function is executed and the console prints' The value of the object has changed '
    Copy the code

    Note that the performance overhead is high when the object has a large number of properties. You can listen for one of the properties of the object, which will be discussed later.

    immediate

    With the immediate option, the callback will be invoked immediately after the listening starts. Rather than waiting for the listening data to change.

    const vm = new Vue({
      el: '#app'
      data: {
        msg: 'very'
      },
      watch: {
        msg: {
          handler () {
            console.log('Callback function executed');
          },
          immediate: true}}})// If MSG is not changed at this time, the console will print 'callback function executed'
    Copy the code

    An array type

    You can write many different value types in an array. Such as:

    const vm = new Vue({
      el: '#app'
      data: {
        msg: 'very'
      },
      watch: {
        msg: [
          'msgChange'.function () {},
          {
            handler () {},
            deep: true.immediate: true}]}})Copy the code

    Key type

    Normal object key value

    All the above are normal object keys and will not be described here.

    The value is a string key

    When the key type is a string, you can implement a listening for one of the properties of the object, for example:

    const vm = new Vue({
      el: '#app'
      data: {
        personObj: {
          name: 'Deng Xuming'.age: 88}},watch: {
        'personObj.name' () {
          console.log('Object's value has changed');
        }
      }
    })
    vm.obj.name = 'Old Deng Head'; // The callback function is executed and the console prints' The value of the object has changed '
    Copy the code

    vm.$watch

    The Vue instance will call $watch at instantiation time, iterating through each property of the Watch object. We can also use vm.$watch for listening, which is the same as the watch options section, but slightly different. The following is how to use it.

    1. Listen for changes to some data
    // 1. Three parameters, one of which is the monitored data; The second argument is the callback function executed when data changes; Three parameter optional, is the set option object
    vm.$watch(
      'msg'.function () {
        // I've been up to something
      }, 
      {
        deep: Boolean.immediate: Boolean})// 2. Two parameters, one of which is the monitored data; The handler attribute is required and is the callback function executed when data changes. Other attributes are optional.
    vm.$watch(
      'msg', 
      {
        handler () {
          // I've been up to something
        },
        deep: Boolean.immediate: Boolean})Copy the code
    1. Listen for changes to properties of an object
    vm.$watch('obj.name'./** and */ above)
    Copy the code
    1. The first parameter can be written as a function type when the listening data is initially uncertain and obtained from multiple data
    vm.$watch(function () {
      This function is called every time the expression 'this.a + this.b' yields a different result
      // This is like listening on an undefined computed property
      return this.a + this.b;
    }, /** The same parameter as above */)
    Copy the code

    When the listener function executes, it returns an unlistener function to stop firing the callback:

    const unwatch = vm.$watch('msg'.function () {});
    unwatch(); // The MSG data listening will be cancelled after execution
    Copy the code

    When using unwatch, it is important to note that with the immediate option, you cannot cancel listening on the first callback.

    const unwatch = vm.$watch('msg'.function () {
        // Did something
        unwatch();  // An error will be reported}, {immediate: true}})Copy the code

    If you still want to use an unlistening function inside a callback, check its availability first:

    var unwatch = vm.$watch('msg'.function () {
        // Did something
        if(unwatch) {
          unwatch();  
        }
      },{
        immediate: true}})Copy the code

    Listener vs compute properties

    1. Both can observe and respond to changes in data on Vue instances.

    2. Watch excels at situations where one piece of data affects multiple pieces of data. Computational properties are good at dealing with scenarios where multiple data affects one data.

    3. Asynchrony can be performed in listeners, but not in computed properties, for example:

    Using listeners:

    var vm = new Vue({
      el: '#app'.data: {
        question: ' ',},watch: {
        question () {
          setTimeout(() = > {
            alert(this.question);
          }, 1000)}}})Copy the code

    Exercise _ Imitation baidu search association

    Url: sp0.baidu.com/5a1Fazu8AA5…

    Request method: JSONP

    Send parameters:

    1. Wd: string, search text
    2. Cb: a string, the name of the callback function

    Result :(in JSON format)

    {
      q: String.p: Boolean.s: Array   // Search the association list
    }
    Copy the code

    vue-resource

    Implementing asynchronous loading in Vue requires using the VUe-Resource library to send Ajax.

    The introduction of vue – the resource

    <script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
    Copy the code

    Note that vue-resource depends on vUE, so vUE is introduced first and then vue-resource.

    With the introduction of vue-resource, a $HTTP method is mounted globally on vUE, and there are a number of methods on the VM.$HTTP method, one for each HTTP request type.

    Vue-resource uses promises, so the return value of the method in $HTTP is a Promise.

    Request method

    A POST request

    For submitting data

    Common data formats:

    • Form submission: multipart/form-data. Older websites use form submission to get data. Nowadays, most websites use Ajax instead of form submission, but form submission still exists.
    • File upload: Application/JSON, which is now used in most cases


    $http.post(url, [body], [options]) $http.post(url, [body], [options])

    • Url: Required, request destination URL
    • Body: Data sent as the body of the request, which is not required
    • Options: data sent as the body of the request, not required
    this.$http.post('https://developer.duyiedu.com/vue/setUserInfo', {
        name: this.name,
        mail: this.mail
      })
      .then(res= > {
        console.log(res);
      })
      .catch(error= > {
        console.log(error);
      })
    Copy the code

    A GET request

    To get the data

    $http.get(url, [options])

    this.$http.get('https://developer.duyiedu.com/vue/getUserInfo')
      .then(res= > {
        console.log(res);
      })
      .catch(error= > {
        console.log(error);
      })
    Copy the code

    Pass in a get request:

    this.$http.get('https://developer.duyiedu.com/vue/getUserInfo', {params: {
        id: 'xxx'
      }
    })
      .then(res= > {
        console.log(res);
      })
      .catch(error= > {
        console.log(error);
      })
    Copy the code

    PUT request

    $http.put(url, [body], [config]);

    PATCH request

    $http.patch(url, [body], [config]);

    The DELETE request

    $http.delete(url, [config])

    A HEAD request

    $http.head(url, [config])

    The json request

    With the exception of JSONP, these six API names are standard HTTP methods. $http.jsonp(url, [options]);

    this.$http.jsonp('https://developer.duyiedu.com/vue/jsonp').then(res= > {
      this.msg = res.bodyText;
    });
    
    
    this.$http.jsonp('https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su', {
      params: {
        wd: 'nn',},jsonp: 'cd'.//jsonp is callback by default
    })
      .then(res= > {
        console.log(res);
      })
    Copy the code

    Options Parameter Description

    parameter type describe
    url String Request target URL
    body Object, FormData, string Data sent as the body of the request
    headers Object The header object sent as the request header
    params Object Parameter object as a URL parameter
    method String HTTP methods (e.g. GET, POST,…)
    responseType String Sets the type of data to return
    timeout Number Modify the request callback function before the request is sent
    credentials Boolean Whether credentials for cross-site requests need to be presented
    emulateHTTP Boolean Whether to set the X-HTTP-method-Override header and send the PUT, PATCH, and DELETE requests in traditional POST mode.
    emulateJSON Boolean Set the request body type to Application/X-www-form-urlencoded
    before function(request) Modify the request callback function before the request is sent
    uploadProgress function(event) A callback function that handles upload progress
    downloadProgress function(event) A callback function that handles the download progress

    The response object

    The response object obtained by a request is handled with the following properties and methods:

    attribute

    attribute type describe
    url String The URL source of the response
    body Object, Blob, string Response body data
    headers Header Request header object
    ok Boolean This value is true when the HTTP response code is between 200 and 299
    status Number The HTTP response code
    statusText String HTTP Response Status

    methods

    methods describe
    text() Returns the response body as a string
    json() Returns the response body as a formatted JSON object
    blob() Returns the response body as a binary Blob object

    Take json() as an example:

    this.$http.get('https://developer.duyiedu.com/vue/getUserInfo')
      .then(res= > {
        return res.json();
      })
      .then(res= > {
        console.log(res);
      })
    Copy the code

    The last word

    Unfortunately, Vue officially no longer maintains this library, so… Let’s learn some more ୧[* ಡ ▽ ಡ *]୨

    Axios

    Axios is an HTTP library based on promises

    Browser support: Chrome, Firefox, Safari, Opera, Edge, IE8+

    The introduction of

    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
    Copy the code

    API

    • axios(config)
    • axios(url, [config])

    Config Configuration object

    The most common configurations are:

    axios({
      method: 'get'.// post, get, put....
      baseURL: ' '.// The requested domain name, base address
      url: ' '.// The requested path
      params: {}, // The request parameters are concatenated to the URL
      data: {}, // The request parameters are placed in the request body
      headers: {}, // Set the request header, such as token
      timeout: 1000.// Set the request timeout period, in ms
    })
    Copy the code

    Methods the alias

    Aliases are provided for all supported request methods for convenience.

    • axios.request(config)
    • axios.get(url, [config])
    • axios.post(url, [data], [config]])
    • axios.delete(url, [config])
    • axios.head(url, [config])
    • axios.put(url, [data], [config])
    • axios.patch(url, [data], [config]])
    • axios.options(url, [config])

    Configure default Values

    You can specify configuration defaults that will be used on individual requests

    Global configuration

    axios.defaults.baseURL = 'https://developer.duyiedu.com/vue';
    axios.defaults.timeout = 1000;
    Copy the code

    In real projects, global configuration is rarely used.

    The instance configuration

    You can create a new AXIOS instance using a custom configuration

    const instance = axios.create({
      baseURL: 'https://developer.duyiedu.com/vue'.timeout: 1000,
    })
    
    instance.get('/getUserInfo').then(res= > {
      // ...
    })
    Copy the code

    Request configuration

    const instance = axios.create();
    instance.get('/getUserInfo', {
      timeout: 5000
    })
    Copy the code

    Configuration priority

    Global < instance < request

    concurrent

    Multiple requests are made simultaneously and the return values are handled uniformly

    • axios.all(iterable)
    • axios.spread(callback)
    axios.all([
      axios.get('/a'),
      axios.get('/b')
    ]).then(axios.spread((aRes, bRes) = > {
      console.log(aRes, bRes);
    }))
    Copy the code

    The interceptor

    Interceptors do some processing before the request is initiated or after the response comes back.

    Request interceptor

    axios.interceptors.request.use(config= > {
      // What to do before sending the request
      return config;
    })
    Copy the code

    Response interceptor

    axios.interceptors.response.use(response= > {
      // What to do with the response data
      return response;
    })
    Copy the code

    Remove interceptors

    const myInterceptor = axios.interceptors.request.use(config= > {});
    axios.interceptors.request.eject(myInterceptor);
    Copy the code

    Add interceptors for axios instances

    const instance = axios.create();
    instance.interceptors.request.use(config= > {});
    Copy the code

    Cancel the request

    Used to cancel an ongoing HTTP request

    const source = axios.CancelToken;
    const source = CancelToken.source();
    
    axios.get('/getUserInfo', {
      cancelToken: source.token
    }).then(res= > {
      console.log(res);
    }).catch(error= > {
      if(axios.isCancel(error)) {
        // Cancel the request
        console.log(error.message);
      } else {
        // Processing error}})// Cancel request parameter optional
    source.cancel('Cancel request');
    Copy the code

    Error handling

    Request/response is the context of an error, indicating that the request has been sent/received in response to an error. If the response has no value, an error occurred during the request. In an error, if the request has no value, it indicates that the request has not been sent, such as canceling the request.

    axios.get('/user/12345')
      .catch(function (error) {
        // The error can be either a request error or a response error
        if (error.response) {
          // Response error
        } else if (error.request) {
          // Request error
        } else {
          console.log('Error', error.message);
        }
        console.log(error.config);
      });
    Copy the code

    In the actual development process, general unified add error handling in the interceptor Errors in the request interceptor, when be request failed to perform, but note: after the request, the request of interceptor will not perform error function, and because the request will not throw an exception, axios on the separate treatment. More often than not, we handle errors in response interceptors.

    const instance = axios.create({});
    instance.interceptors.request(config= >{},error= > {
      return Promise.reject(error);
    })
    
    instance.interceptors.response(response= >{},error= > {
      return Promise.reject(error);
    })
    Copy the code

    Axios preview

    When an AXIos request is not a simple request, the browser prechecks and sends an OPTIONS request. Request to the server asking if cross-domain is allowed. If the cross-domain behavior of the request in precheck is allowed in the response, the browser makes the actual request. Otherwise 405 will be reported.

    The template options

    About el

    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 instance of an HTML element.

    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.

    template

    A string template is used as the identity of the Vue instance. The template replaces the mounted elements, and the contents of the mounted elements are ignored.

    <div id="app"></div>
    Copy the code
    const vm = new Vue({
      el: '#app'.template: ` 
          
    xxx
    `
    ,})Copy the code

    Vue initialization to mount process

    Vue life cycle

    Each Vue instance goes through a series of initialization procedures when it is created, such as setting up data listeners, compiling templates, mounting the instance to the DOM, and updating the DOM as the data changes. Functions called lifecycle hooks are also run along the way, giving users the opportunity to add their own code at different stages.

    Life cycle diagram

    Lifecycle hook

    All lifecycle hooks automatically bind this context to the instance, so you can access data and perform operations on properties and methods

    beforeCreate

    After instance initialization, data Observer and Event/Watcher events are called before configuration.

    <div id="app">
      <div @click="handleClick">Click on the event</div>
    </div>
    Copy the code
    const vm = new Vue({
      el: '#app'.data: {
        msg: 'hellow world',
      },
      beforeCreate () {
        console.log(this.msg);   // undefined
        console.log(this.handleClick);  // undefined
        console.log('-----beforeCreate-----'); 
      },
      methods: {
        handleClick () {
          console.log(handleClick); }},watch: {
        msg: {
          handler () {
            console.log('Listen for MSG value'); 
          },
          immediate: true,}}})Copy the code

    Print order:

    undefined
    undefined-----beforeCreate----- listens to the value of MSGCopy the code

    created

    Called immediately after the instance is created.

    In this step, the instance completes the configuration of data Observer, property and method operations, and Watch/Event event callbacks.

    If you want to call a method in methods or manipulate data in data the first time, you can do so in this hook. Note that the mount phase has not yet started when this hook is executed, and the $EL attribute is not currently visible.

    At this point, you can make a data request and assign the requested value to the data in data.

    <div id="app">
      <div @click="handleClick">Click on the event</div>
    </div>
    Copy the code
    const vm = new Vue({
      el: '#app'.data: {
        msg: 'hellow world',
      },
      created () {
        console.log(this.msg);  // hello world
        console.log(this.handleClick);  // function () {... }
        console.log(this.$el);  // undefined
        console.log('----------created-------');
      },
      methods: {
        handleClick () {
          console.log(handleClick); }},watch: {
        msg: {
          handler () {
            console.log('Listen for MSG value'); 
          },
          immediate: true,}}})Copy the code

    Print order:

    ƒ Hellow world ƒ handleClick () {console.log(handleClick); }
    undefined
    ----------created-------
    Copy the code

    beforeMount

    Called before the mount begins, when the template has been compiled, except that the generated template has not replaced the element corresponding to el.

    In this hook function, you can get the initial state of the template.

    At this point, you can get vm.$el, just the old template

    const vm = new Vue({
      el: '#app',
      beforeMount () {
        console.log(this.$el); }})Copy the code

    mounted

    El is replaced by the newly created vm.$el, which is called after being mounted to the instance.

    The vm.$el in this hook function is the new template.

    After executing the hook function, the instance is fully created.

    If you want to manipulate a DOM node on the page in the first place, you can do so in this hook function

    const vm = new Vue({
      el: '#app',
      mounted () {
        console.log(this.$el); }})Copy the code

    beforeUpdate

    Called when data is updated and occurs before the virtual DOM is patched. At this point the data has been updated, but the DOM has not been updated

    <div id="app">
      {{ msg }}
    </div>
    Copy the code
    const vm = new Vue({
      el: '#app'.data: {
        msg: 'hellow world',
      },
      beforeUpdate () {
        console.log(this.msg);
        console.log(this.$el);
      },
      methods: {
        handleClick () {
          console.log('handleClick'); }}})this.msg = 'xxx';
    Copy the code

    updated

    This hook function is executed after a data change causes the DOM to be re-rendered.

    The data is now synchronized with the DOM.

    beforeDestroy

    Called before instance destruction. At this step, the instance is still fully available.

    In this hook function, the timer can be cleared.

    <div id="app">
      {{ msg }}
    </div>
    Copy the code
    const vm = new Vue({
      el: '#app'.data: {
        msg: 'hellow world'.timer: 0,
      },
      created () {
        this.timer = setInterval(() = > {
          console.log('xxx');
        }, 500)
      },
      beforeDestroy () {
        clearInterval(this.timer); }})Copy the code