A comprehensive summary of Vue2 basic usage

The installation

<! -- Development environment version, including helpful command line warnings -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<! -- Production environment version, optimized size and speed -->
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
Copy the code

The basic instance

<div id="app">
  {{ message }}
</div>
Copy the code

Each Vue application starts by creating a new Vue instance with the Vue function:

var app = new Vue({
  el: '#app'.data: {
    message: 'Hello Vue! '}})Copy the code

A Vue application consists of a root Vue instance created through New Vue, and an optional nested, reusable component tree.

Data and Methods

When a Vue instance is created, it adds all the properties in the data object to the Vue’s responsive system. When the values of these properties change, the view generates a “response,” that is, the match is updated to the new value.

When this data changes, the view is rerendered. Note that properties are reactive only if they already exist in data when the instance is created.

The only exception here is the use of Object.freeze(), which prevents changes to existing properties, meaning that the response system can no longer track the changes.

var obj = {
  foo: 'bar'
}

Object.freeze(obj)

new Vue({
  el: '#app'.data: obj
})
Copy the code

In addition to data properties, the Vue instance exposes some useful instance properties and methods. They are prefixed with $to distinguish them from user-defined property. Such as:

var data = { a: 1 }
var vm = new Vue({
  el: '#example'.data: data
})

vm.$data === data // => true
vm.$el === document.getElementById('example') // => true
Copy the code

Instance lifecycle hooks

Each Vue instance goes through a series of initialization procedures when it is created — for example, you need to set up data listeners, compile templates, mount the instance to the DOM, update the DOM when the data changes, and so on. Functions called lifecycle hooks are also run along the way, giving users the opportunity to add their own code at different stages.

Do not == use arrow functions == on option property or callbacks, such as created: () => console.log(this.a) or vm.$watch(‘a’, newValue => this.myMethod()). Because the arrow function does not have this, this will be looked up as a variable in the upper lexical scope until it is found, often resulting in an Uncaught TypeError.

Template syntax

Vue.js uses htML-based template syntax that allows developers to declaratively bind DOM to the data of the underlying Vue instance. All vue.js templates are valid HTML, so they can be parsed by standards-compliant browsers and HTML parsers.

On the underlying implementation, Vue compiles templates into virtual DOM rendering functions. Combined with a responsive system, Vue can intelligently calculate how many components need to be rerendered and minimize DOM operations.

If you are familiar with the virtual DOM and prefer the raw power of JavaScript, you can also write the render function without templates, using the optional JSX syntax.

The interpolation

The most common form of data binding is text interpolation using “Mustache” syntax (double braces) :

<span>Message: {{ msg }}</span>
Copy the code

The Mustache tag will be replaced with the value of the MSG property on the corresponding data object. Whenever the MSG property on the bound data object changes, the content at the interpolation is updated.

By using the V-once instruction, you can also perform a one-time interpolation so that when the data changes, the contents of the interpolation are not updated. But be aware that this affects other data bindings on this node:

<span v-once>This will not change: {{MSG}}</span>
Copy the code

Raw HTML

Double braces interpret the data as plain text, not HTML code. To output real HTML, use the V-HTML directive:

<p>Using mustaches: {{ rawHtml }}</p>
<p>Using v-html directive: <span v-html="rawHtml"></span></p>
Copy the code

The span content will be replaced with the property value ==rawHtml==, which is directly HTML — ignoring the data binding in parsing the property value. Note that you cannot use V-HTML to compound local templates, because Vue is not a string-based templating engine. Conversely, for user interfaces (UIs), components are better suited as reusable and composable basic units.

Arbitrary HTML rendered dynamically on a site can be very dangerous because it can easily lead to XSS attacks. Try to use HTML interpolation only for trusted content, never for user-supplied content.

Attribute

Mustache syntax doesn’t work on HTML attributes, so you should use the V-bind directive:

<div v-bind:id="dynamicId"></div>
Copy the code

For Boolean attributes (which simply exist means the value is true), V-bind works slightly differently, in this case:

<button v-bind:disabled="isButtonDisabled">Button</button>
Copy the code

If isButtonDisabled is null, undefined, or false, the disabled attribute is not even included in the rendered

Using JavaScript expressions

JavaScript expressions are parsed as JavaScript in the data scope of the owning Vue instance. One limitation is that each binding can only contain a single expression, so some of the examples below won’t work.

<! - right - >
{{ ok ? 'YES' : 'NO' }}

{{ message.split('').reverse().join('') }}

<div v-bind:id="'list-' + id"></div>

<! This is a statement, not an expression
{{ var a = 1 }}

<! -- Flow control will not work either, please use ternary expression -->
{{ if (ok) { return message } }}
Copy the code

instruction

parameter

Some instructions can receive a “parameter,” represented by a colon after the instruction name. For example, the V-bind directive can be used to update HTML attributes in a responsive manner:

<a v-bind:href="url">.</a>
Copy the code

Here the href is the argument, telling the V-bind directive to bind the element’s href attribute to the value of the expression URL.

Another example is the V-ON directive, which listens for DOM events:

<a v-on:click="doSomething">.</a>
Copy the code

The dynamic parameters

As of 2.6.0, it is possible to use JavaScript expressions enclosed in square brackets as arguments to an instruction:

<! Note that there are some constraints on how parameter expressions can be written. -->
<a v-bind:[attributeName] ="url">.</a>
Copy the code

The attributeName is evaluated dynamically as a JavaScript expression, and the resulting value is used as the final parameter. For example, if your Vue instance has a data property attributeName with a value of “href”, this binding will be equivalent to v-bind:href.

Similarly, you can bind handlers to a dynamic event name using dynamic parameters.

Constraints on the values of dynamic parameters

Dynamic arguments are expected to evaluate to a string, null in exceptional cases. This special null value can be explicitly used to remove the binding. Any other value that is not a string will trigger a warning.

Constraints on dynamic parameter expressions

Dynamic parameter expressions have some syntactic constraints because certain characters, such as Spaces and quotes, are invalid in HTML attribute names. Such as:

<! -- This triggers a compile warning -->
<a v-bind:['foo'+bar] ="value">.</a>
Copy the code

Workarounds are to use expressions without Spaces or quotes, or to substitute such complex expressions with computed attributes.

When using templates in the DOM (writing templates directly in an HTML file), you also need to avoid using uppercase characters for key names, because browsers force all attribute names to lowercase:

<! -- This code is converted to 'V-bind :[someattr]' when using templates in the DOM. The code will not work unless there is a property named "someattr" in the instance. -->
<a v-bind:[someAttr] ="value">.</a>
Copy the code

The modifier

The modifier is a half-full stop. A specified special suffix used to indicate that an instruction should be bound in a particular way. For example, the.prevent modifier tells the V-ON directive to call event.preventDefault() for triggered events:

<form v-on:submit.prevent="onSubmit">.</form>
Copy the code

Evaluate properties and listeners

Calculate attribute

Based on example

<div id="example">
  <p>Original message: "{{ message }}"</p>
  <p>Computed reversed message: "{{ reversedMessage }}"</p>
</div>
Copy the code
var vm = new Vue({
  el: '#example'.data: {
    message: 'Hello'
  },
  computed: {
    // Calculates the getter for the property
    reversedMessage: function () {
      // 'this' points to the VM instance
      return this.message.split(' ').reverse().join(' ')}}})Copy the code

Results:

Original message: “Hello”

Computed reversed message: “olleH”

Here we declare a calculated property reversedMessage. The function we provide will be used as the getter for the property Vm. reversedMessage:

// The value of vm.reversedMessage always depends on the value of vm.message.
console.log(vm.reversedMessage) // => 'olleH'
vm.message = 'Goodbye'
console.log(vm.reversedMessage) // => 'eybdooG'
Copy the code

You can bind computed properties in a template just as you can bind normal properties. Vue knows that VM. reversedMessage depends on VM. message, so when vM. message changes, all bindings that depend on VM. reversedMessage are updated. And the best part is that we’ve created this dependency declaratively: Getters that evaluate properties are side effectless, making it easier to test and understand.

Calculate the property cache vs method

We can achieve the same effect by calling methods in expressions:

<p>Reversed message: "{{ reversedMessage() }}"</p>
Copy the code
// In the component
methods: {
  reversedMessage: function () {
    return this.message.split(' ').reverse().join(' ')}}Copy the code

We can define the same function as a method rather than a calculated property. The end result is exactly the same. The difference, however, is that computed attributes are cached based on their reactive dependencies. They are reevaluated only when the associated reactive dependencies change. This means that as long as the Message has not changed, multiple visits to the reversedMessage computed property will immediately return the previous computed result without having to execute the function again.

This also means that the following computed attributes will not be updated because date.now () is not a reactive dependency:

computed: {
  now: function () {
    return Date.now()
  }
}
Copy the code

Compute properties vs. listen properties

Vue provides a more general way to observe and respond to changes in data on Vue instances: listening properties. It’s easy to abuse Watch when you have some data that needs to change with other data. However, it is often better to use computed properties rather than imperative Watch callbacks. Consider this example:

<div id="demo">{{ fullName }}</div>
Copy the code
var vm = new Vue({
  el: '#demo'.data: {
    firstName: 'Foo'.lastName: 'Bar'.fullName: 'Foo Bar'
  },
  watch: {
    firstName: function (val) {
      this.fullName = val + ' ' + this.lastName
    },
    lastName: function (val) {
      this.fullName = this.firstName + ' ' + val
    }
  }
})
Copy the code

The code above is imperative and repetitive. Compare this to the version of the calculated property:

var vm = new Vue({
  el: '#demo'.data: {
    firstName: 'Foo'.lastName: 'Bar'
  },
  computed: {
    fullName: function () {
      return this.firstName + ' ' + this.lastName
    }
  }
})
Copy the code

Evaluate the setter for the property

By default, you only have getters for computed properties, but you can also provide a setter if needed:

// ...
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

When vm.fullName = ‘John Doe’ is now run again, the setter will be called and vm.firstName and vm.lastName will be updated accordingly.

The listener

While computing properties is more appropriate in most cases, sometimes a custom listener is required. That’s why Vue provides a more generic way to respond to changes in data with the Watch option. This approach is most useful when asynchronous or expensive operations need to be performed when data changes. Such as:

<div id="watch-example">
  <p>
    Ask a yes/no question:
    <input v-model="question">
  </p>
  <p>{{ answer }}</p>
</div>
Copy the code
<! Because the AJAX library and common tool ecosystem is already quite rich, the Vue core code is not duplicated.
<! Provide these features to keep things lean. This also gives you the freedom to choose the tools you're more familiar with. -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js"></script>
<script>
var watchExampleVM = new Vue({
  el: '#watch-example'.data: {
    question: ' '.answer: 'I cannot give you an answer until you ask a question! '
  },
  watch: {
    // If 'question' changes, the function is run
    question: function (newQuestion, oldQuestion) {
      this.answer = 'Waiting for you to stop typing... '
      this.debouncedGetAnswer()
    }
  },
  created: function () {
    // '_. Debounce' is a function that limits the frequency of operations through Lodash.
    // In this case, we want to limit the frequency of access to yesNo. WTF/API
    // The AJAX request is not sent until the user has entered. Want to learn more about
    // '_. Debounce' functions (and their relatives' _. Throttle '),
    // Please refer to https://lodash.com/docs#debounce
    this.debouncedGetAnswer = _.debounce(this.getAnswer, 500)},methods: {
    getAnswer: function () {
      if (this.question.indexOf('? ') = = = -1) {
        this.answer = 'Questions usually contain a question mark. ; -) '
        return
      }
      this.answer = 'Thinking... '
      var vm = this
      axios.get('https://yesno.wtf/api')
        .then(function (response) {
          vm.answer = _.capitalize(response.data.answer)
        })
        .catch(function (error) {
          vm.answer = 'Error! Could not reach the API. ' + error
        })
    }
  }
})
</script>
Copy the code

In this example, using the Watch option allows us to perform an asynchronous operation (accessing an API), limit how often we perform that operation, and set the intermediate state until we get the final result. These are all things you can’t do with computed properties.

In addition to the Watch option, you can also use the imperative VM.$watch API.

Class is bound to Style

Class lists and inline styles for manipulating elements are a common requirement for data binding. Because they are attributes, we can handle them with V-bind: we just need to evaluate the string result with the expression. However, string concatenation is cumbersome and error-prone. Therefore, vue.js makes special enhancements when v-bind is used for class and style. The result of an expression can be an object or an array in addition to a string.

Binding HTML Class

Object syntax

We can pass v-bind:class an object to dynamically switch classes:

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

The syntax above indicates that the existence of the active class will depend on the truthiness of the data property isActive.

You can dynamically switch between classes by passing in more fields in the object. In addition, the V-bind :class directive can coexist with ordinary class attributes. When the following template is available:

<div class="static" v-bind:class="{ active: isActive, 'text-danger': hasError }"></div>
Copy the code

And the following data:

data: {
  isActive: true.hasError: false
}
Copy the code

The result is rendered as:

<div class="static active"></div>
Copy the code

When isActive or hasError changes, the class list is updated accordingly. For example, if hasError is true, the class list changes to “static Active text- Danger “.

Bound data objects do not have to be defined inline in the template:

<div v-bind:class="classObject"></div>
Copy the code
data: {
  classObject: {
    active: true.'text-danger': false}}Copy the code

The rendered result is the same as above. We can also bind a computed property of the return object here. This is a common and powerful pattern:

<div v-bind:class="classObject"></div>
Copy the code
data: {
  isActive: true.error: null
},
computed: {
  classObject: function () {
    return {
      active: this.isActive && !this.error,
      'text-danger': this.error && this.error.type === 'fatal'}}}Copy the code

Array syntax

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

<div v-bind:class="[activeClass, errorClass]"></div>
Copy the code
data: {
  activeClass: 'active'.errorClass: 'text-danger'
}
Copy the code

Apply colours to a drawing as follows:

<div class="active text-danger"></div>
Copy the code

If you also want to switch classes in a list based on criteria, you can use a ternary expression:

<div v-bind:class="[isActive ? activeClass : '', errorClass]"></div>
Copy the code

Writing this will always add errorClass, but only activeClass if isActive is truthy.

Truthy is not true

In JavaScript, truthy refers to a converted value that is true in the context of a Boolean value. All values are true unless they are defined as false (that is, true except false, 0, “”, NULL, undefined, and NaN).

However, this is a bit cumbersome when there are multiple conditional classes. So you can also use object syntax in array syntax:

<div v-bind:class="[{ active: isActive }, errorClass]"></div>
Copy the code

Used on components

When class Property is used on a custom component, the classes are added to the root element of the component. Classes that already exist on this element will not be overwritten.

For example, if you declare this component:

Vue.component('my-component', {
  template: '<p class="foo bar">Hi</p>'
})
Copy the code

Then add some classes when you use it:

<my-component class="baz boo"></my-component>
Copy the code

The HTML will be rendered as:

<p class="foo bar baz boo">Hi</p>
Copy the code

The same applies to classes with data binding:

<my-component v-bind:class="{ active: isActive }"></my-component>
Copy the code

When isActive is truthy, the HTML will be rendered as:

<p class="foo bar active">Hi</p>
Copy the code

Bind inline styles

Object syntax

The v-bind:style object syntax is straightforward — it looks a lot like CSS, but it’s actually a JavaScript object. CSS property names can be camelCase or kebab-case delimited (remember to use quotes) :

<div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
Copy the code
data: {
  activeColor: 'red'.fontSize: 30
}
Copy the code

It is usually better to bind directly to a style object, which makes the template clearer:

<div v-bind:style="styleObject"></div>
Copy the code
data: {
  styleObject: {
    color: 'red'.fontSize: '13px'}}Copy the code

Similarly, object syntax is often used in conjunction with computed properties that return objects.

Array syntax

V-bind :style array syntax allows multiple style objects to be applied to the same element:

<div v-bind:style="[baseStyles, overridingStyles]"></div>
Copy the code

Automatically add prefixes with multiple values

When V-bind :style uses CSS properties that require a browser engine prefix, such as transform, vue.js will automatically detect and add the corresponding prefix.

– WebKit – (Google, Safari, the new Opera browser, and almost every browser on iOS (including Firefox on iOS); In short, all webKit-based browsers)

-moz- (火狐浏览器)<br>
-o- (旧版Opera浏览器)<br>
-ms- (IE浏览器 和 Edge浏览器)
Copy the code

Since 2.3.0 you can provide an array of values for property in the style binding. This is often used to provide multiple prefixed values, such as:

<div :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.

Conditions apply colours to a drawing

v-if

The V-if directive is used to conditionally render a piece of content. This content will only be rendered if the expression of the directive returns truthy.

<h1 v-if="awesome">Vue is awesome!</h1>
Copy the code

You can also add an “else block” with v-else:

<h1 v-if="awesome">Vue is awesome!</h1>
<h1 v-else>Oh no 😢</h1>
Copy the code

in<template>Elementv-ifConditional rendering grouping

Because v-if is an instruction, it must be added to an element. But what if you want to switch between multiple elements? You can treat a

<template v-if="ok">
  <h1>Title</h1>
  <p>Paragraph 1</p>
  <p>Paragraph 2</p>
</template>
Copy the code

v-else

You can use the V-else directive to represent the “else block” of v-if:

<div v-if="Math. The random () > 0.5">
  Now you see me
</div>
<div v-else>
  Now you don't
</div>
Copy the code

The V-else element must be immediately followed by an element with v-if or v-else-if, otherwise it will not be recognized.

v-else-if

2.1.0 new

V-else -if, as the name suggests, acts as an “else-if block” for V-if and can be used continuously:

<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

Similarly to v-else, v-else-if must also be followed by an element with v-if or V-else -if.

Manage reusable elements with keys

Vue renders elements as efficiently as possible, often reusing existing elements rather than rendering them from scratch. This has other benefits besides making Vue very fast. For example, if you allow users to switch between different login methods:

<template v-if="loginType === 'username'">
  <label>Username</label>
  <input placeholder="Enter your username">
</template>
<template v-else>
  <label>Email</label>
  <input placeholder="Enter your email address">
</template>
Copy the code

Switching loginType in the code above will not clear what the user has entered. Because both templates use the same element, the will not be replaced — just its placeholder.

This is not always practical, so Vue provides a way to say “These two elements are completely separate, don’t reuse them”. Simply add a key attribute with a unique value:

<template v-if="loginType === 'username'">
  <label>Username</label>
  <input placeholder="Enter your username" key="username-input">
</template>
<template v-else>
  <label>Email</label>
  <input placeholder="Enter your email address" key="email-input">
</template>
Copy the code

v-show

Another option for displaying elements by conditions is the V-show directive. The usage is roughly the same:

<h1 v-show="ok">Hello!</h1>
Copy the code

The difference is that elements with v-show are always rendered and remain in the DOM. V-show simply toggles the element’s CSS property display.

Note that v-show does not support

v-if vs v-show

V-if is “true” conditional rendering because it ensures that event listeners and subcomponents within the conditional block are properly destroyed and rebuilt during the switch.

V-if is also lazy: if the condition is false during initial rendering, nothing is done — the conditional block is not rendered until the condition is true for the first time.

V-show, by contrast, is much simpler — elements are always rendered regardless of initial conditions and simply switch based on CSS.

In general, V-if has a higher switching overhead, while V-show has a higher initial rendering overhead. Therefore, if you need to switch ++ very frequently, use v-show; It is better to use V-if if the condition ++ rarely changes ++ at run time.

It is not recommended to use both V-if and V-for.

When v-if is used with V-for, v-for has a higher priority than V-if. Consult the list rendering guide for details.

The list of rendering

withv-forCorresponds an array to a set of elements

We can use the V-for directive to render a list based on an array. The V-for directive requires a special syntax of the form item in Items, where items are the source data array and item is the alias of the array element being iterated over.

<ul id="example-1">
  <li v-for="item in items" :key="item.message">
    {{ item.message }}
  </li>
</ul>
Copy the code
var example1 = new Vue({
  el: '#example-1'.data: {
    items: [{message: 'Foo' },
      { message: 'Bar'}]}})Copy the code

Results:

  • Foo
  • Bar

In the V-for block, we can access all of the parent scope’s properties. V-for also supports an optional second parameter, the index of the current item.

<ul id="example-2">
  <li v-for="(item, index) in items">
    {{ parentMessage }} - {{ index }} - {{ item.message }}
  </li>
</ul>
Copy the code
var example2 = new Vue({
  el: '#example-2'.data: {
    parentMessage: 'Parent'.items: [{message: 'Foo' },
      { message: 'Bar'}]}})Copy the code

Results:

  • Parent – 0 – Foo
  • Parent – 1 – Bar

You can also use of instead of in as a separator, since it is closer to the syntax of a JavaScript iterator:

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

inv-forUse object in

You can also iterate over an object’s property with v-for.

<ul id="v-for-object" class="demo">
  <li v-for="value in object">
    {{ value }}
  </li>
</ul>
Copy the code
new Vue({
  el: '#v-for-object'.data: {
    object: {
      title: 'How to do lists in Vue'.author: 'Jane Doe'.publishedAt: '2016-04-10'}}})Copy the code
  • How to do lists in Vue
  • Jane Doe
  • 2016-04-10

You can also supply the second parameter as the property name:

<div v-for="(value, name) in object">
  {{ name }}: {{ value }}
</div>
Copy the code
title: How to do lists in Vue
author: Jane Doe
publishedAt: 2016-04-10


<div v-for="(value, name, index) in object">
  {{ index }}. {{ name }}: {{ value }}
</div>
Copy the code
0. title: How to do lists in Vue
1. author: Jane Doe
2. publishedAt: 2016-04-10

Maintaining state

When Vue is updating a list of elements rendered using V-for, it defaults to the “update in place” policy. If the order of data items is changed, Vue does not move DOM elements to match the order of data items, but instead updates each element in place and ensures that they are rendered correctly at each index location. Vue 1.x track-by=”$index”

This default mode is efficient, but ++ only works for list rendering outputs that don’t depend on child component state or temporary DOM state (for example, form input values).

To give Vue a hint that it can track the identity of each node to reuse and reorder existing elements, you need to provide a unique key attribute for each item:

<div v-for="item in items" v-bind:key="item.id">
  <! - content - >
</div>
Copy the code

It is recommended to provide key attributes whenever possible with V-for, unless traversing the output DOM content is simple or you deliberately rely on default behavior for performance gains.

Because it is a general mechanism for Vue to identify nodes, key is not specifically associated with V-for. As we will see later in the guide, it has other uses as well.

Do not use non-primitive values such as objects or arrays as v-for keys. Use a string or numeric value.

Array update detection

Change the way

Vue wraps around the array change methods being listened for, so they will also trigger view updates. These covered methods include:

  • push()
  • pop()
  • shift()
  • unshift()
  • splice()
  • sort()
  • reverse()

You can open the console and then try calling the change method on the Items array from the previous example. Such as

example1.items.push({ message: 'Baz'}).Copy the code

Replace the array

Changing methods, as the name suggests, changes the original array from which they were called. In contrast, there are non-changing methods, such as filter(), concat(), and slice(). They do not alter the original array, but always return a new one. When using the non-change method, we can replace the old array with the new one:

example1.items = example1.items.filter(function (item) {
  return item.message.match(/Foo/)})Copy the code

You might think that this would cause Vue to discard the existing DOM and re-render the entire list. Fortunately, this is not the case. Vue implements some clever heuristics to maximize the reuse of DOM elements, so it is very efficient to replace an array with one containing the same elements.

Matters needing attention

Due to JavaScript limitations, Vue cannot detect array and object changes. However, there are ways to circumvent these limitations and make them responsive.

  1. For objects:

    Vue cannot detect the addition or removal of property. So property must exist on the Data object for Vue to convert it to reactive.

    var vm = new Vue({
      data: {a:1}})// 'vm.a' is reactive
    
    vm.b = 2
    // 'vm.b' is non-responsive
    Copy the code

    Vue does not allow dynamic root-level responsive properties to be added to already created instances. However, you can add responsive properties to nested objects using the vue.set (Object, propertyName, value) method. For example, for:

    Vue.set(vm.someObject, 'b'.2)
    Copy the code

    You can also use the vm.$set instance method, which is also an alias for the global vue. set method:

    this.$set(this.someObject,'b'.2)
    Copy the code

    Sometimes you may need to assign multiple new properties to existing objects, such as object.assign () or _.extend(). However, new properties that are thus added to the object do not trigger updates. In this case, you should create a new object with the property of the original object and the property of the object to be mixed in.

    // Replace 'object. assign(this.someObject, {a: 1, b: 2})'
    this.someObject = Object.assign({}, this.someObject, { a: 1.b: 2 })
    Copy the code
  2. For arrays:

    Vue cannot detect changes to the following arrays:

    When you set an array item directly using an index, e.g. Vm. items[indexOfItem] = newValue When you change the length of the array, e.g. Vm. items. Length = newLength for example:

    var vm = new Vue({
      data: {
        items: ['a'.'b'.'c']
      }
    })
    vm.items[1] = 'x' // Not responsive
    vm.items.length = 2 // Not responsive
    Copy the code

    To solve the first type of problem, the following two methods can achieve the same effect as vm.items[indexOfItem] = newValue, and also trigger status updates within a responsive system:

    // Vue.set
    Vue.set(vm.items, indexOfItem, newValue)
    // Array.prototype.splice
    vm.items.splice(indexOfItem, 1, newValue)
    Copy the code

    You can also use the vm.$set instance method, which is an alias for the global method vue.set:

    vm.$set(vm.items, indexOfItem, newValue)
    Copy the code

    To solve the second type of problem, you can use Splice:

    vm.items.splice(newLength)
    Copy the code

Displays filtered/sorted results

Sometimes we want to display a filtered or sorted version of an array without actually changing or resetting the original data. In this case, you can create a calculated property to return a filtered or sorted array. Such as:

<li v-for="n in evenNumbers">{{ n }}</li>
Copy the code
data: {
  numbers: [ 1.2.3.4.5]},computed: {
  evenNumbers: function () {
    return this.numbers.filter(function (number) {
      return number % 2= = =0}}})Copy the code

In cases where computed attributes do not apply (for example, in nested V-for loops) you can use one method:

<ul v-for="set in sets">
  <li v-for="n in even(set)">{{ n }}</li>
</ul>
Copy the code
data: {
  sets: [[ 1.2.3.4.5 ], [6.7.8.9.10]]},methods: {
  even: function (numbers) {
    return numbers.filter(function (number) {
      return number % 2= = =0}}})Copy the code

inv-forValue ranges are used in

V -for can also accept integers. In this case, it will repeat the template the corresponding number of times.

<div>
  <span v-for="n in 10">{{ n }} </span>
</div>
Copy the code

in<template>For use onv-for

Similar to v-if, you can use

<ul>
  <template v-for="item in items">
    <li>{{ item.msg }}</li>
    <li class="divider" role="presentation"></li>
  </template>
</ul>
Copy the code

v-forv-ifUsed together

Note that using V-if and V-for on the same element is not recommended.

Never use v-if and V-for on the same element.

When they are on the same node, V-for takes precedence over V-IF, which means that V-IF will run separately in each V-for loop. This priority mechanism can be useful when you only want to render nodes for a subset of items, as follows:

<! Bad -- -- -- >
<! To filter items in a list, replace the list with a calculated property that returns the filtered list. -->
<li v-for="todo in todos" v-if=! "" todo.isComplete">
  {{ todo }}
</li>
Copy the code

The above code will only render the unfinished todo.

If your goal is to conditionally skip the loop, place v-if on the outer element (or

<ul v-if="todos.length">
  <li v-for="todo in todos">
    {{ todo }}
  </li>
</ul>
<p v-else>No todos left!</p>
Copy the code

Used on componentsv-for

On custom components, you can use V-for just like on any normal element.

<my-component v-for="item in items" :key="item.id"></my-component>
Copy the code

In version 2.2.0+, keys are now required when using V-for on components.

However, no data is automatically passed to the component because the component has its own independent scope. To pass iteration data to the component, we use prop:

<my-component
  v-for="(item, index) in items"
  v-bind:item="item"
  v-bind:index="index"
  v-bind:key="item.id"
></my-component>
Copy the code

The reason for not automatically injecting items into the component is that it tightly couples the component to the v-for operation. Knowing where component data comes from enables components to be reused in other contexts.

Here is a complete example of a simple todo list:

<div id="todo-list-example">
  <form v-on:submit.prevent="addNewTodo">
    <label for="new-todo">Add a todo</label>
    <input
      v-model="newTodoText"
      id="new-todo"
      placeholder="E.g. Feed the cat"
    >
    <button>Add</button>
  </form>
  <ul>
    <li
      is="todo-item"
      v-for="(todo, index) in todos"
      v-bind:key="todo.id"
      v-bind:title="todo.title"
      v-on:remove="todos.splice(index, 1)"
    ></li>
  </ul>
</div>
Copy the code

Notice the is=”todo-item” attribute here. This is necessary when using DOM templates, because only

  • elements are considered valid within
      elements. Doing so achieves the same effect as

      , but avoids some potential browser parsing errors. See DOM template parsing instructions for more information.
  • Vue.component('todo-item', {
      template: '\ 
  • \ {{ title }}\ \
  • \ '
    .props: ['title']})new Vue({ el: '#todo-list-example'.data: { newTodoText: ' '.todos: [{id: 1.title: 'Do the dishes'}, {id: 2.title: 'Take out the trash'}, {id: 3.title: 'Mow the lawn'}].nextTodoId: 4 }, methods: { addNewTodo: function () { this.todos.push({ id: this.nextTodoId++, title: this.newTodoText }) this.newTodoText = ' '}}})Copy the code

    The event processing

    Listen for an event

    You can use the V-ON directive to listen for DOM events and run some JavaScript code when triggered.

    <div id="example-1">
      <button v-on:click="counter += 1">Add 1</button>
      <p>The button above has been clicked {{ counter }} times.</p>
    </div>
    Copy the code
    var example1 = new Vue({
      el: '#example-1'.data: {
        counter: 0}})Copy the code

    Event handling methods

    However, much of the event handling logic is more complex, so it is 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="example-2">
      <! -- 'greet' is the method name defined below -->
      <button v-on:click="greet">Greet</button>
    </div>
    Copy the code
    var example2 = new Vue({
      el: '#example-2'.data: {
        name: 'Vue.js'
      },
      // Define methods in the methods object
      methods: {
        greet: function (event) {
          // 'this' refers to the current Vue instance in the method
          alert('Hello ' + this.name + '! ')
          // 'event' is a native DOM event
          if (event) {
            alert(event.target.tagName)
          }
        }
      }
    })
    
    // You can also call the method directly with JavaScript
    example2.greet() // => 'Hello Vue.js! '
    Copy the code

    Methods in inline processors

    In addition to binding directly to a method, you can also call a method in an inline JavaScript statement:

    <div id="example-3">
      <button v-on:click="say('hi')">Say hi</button>
      <button v-on:click="say('what')">Say what</button>
    </div>
    Copy the code
    new Vue({
      el: '#example-3'.methods: {
        say: function (message) {
          alert(message)
        }
      }
    })
    Copy the code

    Sometimes you also need to access the raw DOM event in the associative sentence processor. We can pass it to the method with the special variable $event:

    <button v-on:click="warn('Form cannot be submitted yet.', $event)">
      Submit
    </button>
    Copy the code
    // ...
    methods: {
      warn: function (message, event) {
        // Now we can access the native event object
        if (event) {
          event.preventDefault()
        }
        alert(message)
      }
    }
    Copy the code

    Event modifier

    Calling event.preventDefault() or event.stopPropagation() in the event handler is a very common requirement. While this could easily be done in a method, it’s better if the method has pure data logic instead of dealing with DOM event details.

    To solve this problem, vue.js provides event modifiers for V-Ons. As mentioned earlier, modifiers are represented by an instruction suffix beginning with a dot.

    • .stop
    • .prevent
    • .capture
    • .self
    • .once
    • .passive
    <! -- Prevent the click event from propagating -->
    <a v-on:click.stop="doThis"></a>
    
    <! Submit events no longer reload the page -->
    <form v-on:submit.prevent="onSubmit"></form>
    
    <! -- modifiers can be concatenated -->
    <a v-on:click.stop.prevent="doThat"></a>
    
    <! -- only modifiers -->
    <form v-on:submit.prevent></form>
    
    <! Add event listener with event capture mode
    <! Events triggered by an inner element are processed here before they are processed by the inner element.
    <div v-on:click.capture="doThis">.</div>
    
    <! Trigger handler only if event.target is the current element itself -->
    <! -- that is, events are not triggered from internal elements -->
    <div v-on:click.self="doThat">.</div>
    Copy the code

    When using modifiers, order is important; The corresponding code is generated in the same order. Therefore, using V-on :click.prevent. Self blocks all clicks, whereas V-on :click.self. Prevent only blocks clicks on the element itself.

    2.1.4 new

    <! Click event will only trigger once -->
    <a v-on:click.once="doThis"></a>
    Copy the code

    Unlike other modifiers that only work on native DOM events, the.once modifier can also be used on custom component events. If you haven’t read the documentation for components, don’t worry now.

    2.3.0 new

    Vue also provides the.passive modifier for the Passive option in the addEventListener.

    <! -- The default behavior of the scroll event (i.e. the scroll behavior) will be triggered immediately -->
    <! Instead of waiting for 'onScroll' to finish -->
    <! -- This includes' event.preventdefault () '-->
    <div v-on:scroll.passive="onScroll">.</div>
    Copy the code

    The.passive modifier is especially useful on mobile.

    Do not use.passive with.prevent, as.prevent will be ignored and the browser may show you a warning. Remember that.passive tells the browser that you do not want to block the event’s default behavior.

    Key modifier

    When listening for keyboard events, we often need to check for detailed keystrokes. Vue allows v-ONS to add key modifiers 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

    The event usage of keyCode is deprecated and may not be supported by the latest browsers.

    Using keyCode attributes is also allowed:

    <input v-on:keyup.13="submit">
    Copy the code

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

    • .enter
    • .tab
    • .delete (capture the delete and backspace keys)
    • .esc
    • .space
    • .up
    • .down
    • .left
    • .right

    Some keys (.esc and all arrow keys) have different keys in IE9, and these built-in aliases should be preferred if you want to support IE9.

    Keymodifier aliases can also be customized using the global config.keyCodes object:

    Vue.config.keyCodes = {
      v: 86.f1: 112.// camelCase is not available
      mediaPlayPause: 179.// Instead, use kebab-case 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

    2.1.0 new

    You can use the following modifier to implement a listener that fires a mouse or keyboard event only when the corresponding key is pressed.

    • .ctrl
    • .alt
    • .shift
    • .meta

    Note: On the Mac system 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 either “meta” or “meta”.

    <! -- Alt + C -->
    <input v-on:keyup.alt.67="clear">
    
    <! -- Ctrl + Click -->
    <div v-on:click.ctrl="doSomething">Do something</div>
    Copy the code

    Note that the modifier key differs from the regular key in that, when used with the keyUP event, the modifier key must be in the pressed state when the event is fired. In other words, keyup.ctrl can only be triggered if the other keys are released while CTRL is being held down. Releasing the CTRL alone will not trigger the event. If you want this behavior, use keyCode: keyup.17 for CTRL instead.

    Exact modifier

    2.5.0 new

    The. Exact modifier allows you to control events triggered by the exact combination of system modifiers.

    <! -- Trigger even when Alt or Shift is pressed together -->
    <button v-on:click.ctrl="onClick">A</button>
    
    <! -- Triggered only when Ctrl is pressed -->
    <button v-on:click.ctrl.exact="onCtrlClick">A</button>
    
    <! -- triggered when no system modifier is pressed -->
    <button v-on:click.exact="onClick">A</button>
    Copy the code

    Mouse button modifier

    2.2.0 new

    • .left
    • .right
    • .middle

    These modifiers restrict the handler to responding only to a particular mouse button.

    Why listen for events in HTML?

    You may notice that this way of listening for events violates a long-standing tradition of separation of concern. But don’t worry, because all vue.js event handling methods and expressions are strictly tied to the ViewModel of the current view, it doesn’t cause any maintenance difficulties. Actually, there are several benefits to using v-ON:

    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. You don’t have to worry about cleaning them.

    Form input binding

    Basic usage

    You can use the V-model directive to create two-way data binding on forms ,

    The V-Model ignores the initial value, Checked, and selected attribute values of all form elements and always uses Vue instance data as the data source. You should declare the initial value in the data option of the component via JavaScript.

    Internally, the V-Model uses different properties for different input elements and throws different events:

    • Text and Textarea elements are usedvalueThe property andinputEvents;
    • Checkbox and radio usecheckedThe property andchangeEvents;
    • The select field willvalueAs prop and willchangeAs an event.

    For languages that require input methods (such as Chinese, Japanese, Korean, etc.), you will find that the V-Model is not updated during the input method composition process. If you also want to handle this process, use input events.

    The text

    <input v-model="message" placeholder="edit me">
    <p>Message is: {{ message }}</p>
    Copy the code

    Multiline text

    <span>Multiline message is:</span>
    <p style="white-space: pre-line;">{{ message }}</p>
    <br>
    <textarea v-model="message" placeholder="add multiple lines"></textarea>
    Copy the code

    Interpolation in text areas () does not work, use the V-model instead.

    Check box

    A single check box, bound to a Boolean value:

    <input type="checkbox" id="checkbox" v-model="checked">
    <label for="checkbox">{{ checked }}</label>
    Copy the code

    Multiple check boxes bound to the same array:

    <div id='example-3'>
      <input type="checkbox" id="jack" value="Jack" v-model="checkedNames">
      <label for="jack">Jack</label>
      <input type="checkbox" id="john" value="John" v-model="checkedNames">
      <label for="john">John</label>
      <input type="checkbox" id="mike" value="Mike" v-model="checkedNames">
      <label for="mike">Mike</label>
      <br>
      <span>Checked names: {{ checkedNames }}</span>
    </div>
    Copy the code
    new Vue({
      el: '#example-3'.data: {
        checkedNames: []}})Copy the code

    The radio button

    <div id="example-4">
      <input type="radio" id="one" value="One" v-model="picked">
      <label for="one">One</label>
      <br>
      <input type="radio" id="two" value="Two" v-model="picked">
      <label for="two">Two</label>
      <br>
      <span>Picked: {{ picked }}</span>
    </div>
    Copy the code
    new Vue({
      el: '#example-4'.data: {
        picked: ' '}})Copy the code

    Select box

    1. Radio:

      <div id="example-5">
        <select v-model="selected">
          <option disabled value="">Please select a</option>
          <option>A</option>
          <option>B</option>
          <option>C</option>
        </select>
        <span>Selected: {{ selected }}</span>
      </div>
      Copy the code
      new Vue({
        el: '... '.data: {
          selected: ' '}})Copy the code

    If the initial value of the V-model expression fails to match any of the options, the

    1. Multiple selection (bound to an array) :

      <div id="example-6">
        <select v-model="selected" multiple style="width: 50px;">
          <option>A</option>
          <option>B</option>
          <option>C</option>
        </select>
        <br>
        <span>Selected: {{ selected }}</span>
      </div>
      Copy the code
      new Vue({
        el: '#example-6'.data: {
          selected: []}})Copy the code
    2. Dynamic options for rendering with V-for:

      <select v-model="selected">
        <option v-for="option in options" v-bind:value="option.value">
          {{ option.text }}
        </option>
      </select>
      <span>Selected: {{ selected }}</span>
      Copy the code
      new Vue({
        el: '... '.data: {
          selected: 'A'.options: [{text: 'One'.value: 'A' },
            { text: 'Two'.value: 'B' },
            { text: 'Three'.value: 'C'}]}})Copy the code

    Value binding

    For radio buttons, check boxes, and select box options, the value of the V-model binding is usually a static string (it can also be a Boolean value for check boxes) :

    <! -- "picked" is the string "A" -->
    <input type="radio" v-model="picked" value="a">
    
    <! -- 'toggle' is true or false -->
    <input type="checkbox" v-model="toggle">
    
    <! When the first option is selected, 'selected' is the string "ABC" -->
    <select v-model="selected">
      <option value="abc">ABC</option>
    </select>
    Copy the code

    But sometimes we might want to bind the value to a dynamic property of the Vue instance, using v-bind, and the value of the property may not be a string.

    Check box

    <input
      type="checkbox"
      v-model="toggle"
      true-value="yes"
      false-value="no"
    >
    Copy the code
    // when selected
    vm.toggle === 'yes'
    // When not selected
    vm.toggle === 'no'
    Copy the code

    The true-value and false-value attributes here do not affect the value attribute of the input control because the browser does not include unchecked checkboxes when submitting the form. If you want to ensure that either of these two values on the form can be submitted (that is, “yes” or “no”), use the radio button instead.

    The radio button

    <input type="radio" v-model="pick" v-bind:value="a">
    Copy the code
    // when selected
    vm.pick === vm.a
    Copy the code

    Select the box’s options

    <select v-model="selected">
        <! Inline object literals -->
      <option v-bind:value="{ number: 123 }">123</option>
    </select>
    Copy the code
    // when selected
    typeof vm.selected // => 'object'
    vm.selected.number / / = > 123
    Copy the code

    The modifier

    • .lazy

    By default, v-Model synchronizes the value of the input field with the data each time the input event is triggered (except when the input method combines text as described above). You can add the lazy modifier to synchronize after the change event:

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

    If you want to automatically convert user input values to numeric types, you can add the number modifier to the V-Model:

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

    This is often useful because even when type=”number”, the value of the HTML input element always returns a string. If the value cannot be resolved by parseFloat(), the original value is returned.

    • .trim

    If you want to automatically filter whitespace entered by the user, you can add the trim modifier to the V-model:

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

    Component based

    Basic example

    Here is an example of a Vue component:

    // Define a new component called button-counter
    Vue.component('button-counter', {
      data: function () {
        return {
          count: 0}},template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>'
    })
    Copy the code

    The component is a reusable Vue instance with a name:

    in this case. We can use this component as a custom element in a Vue root instance created with new Vue:

    <div id="components-demo">
      <button-counter></button-counter>
    </div>
    Copy the code
    new Vue({ el: '#components-demo' })
    Copy the code

    Because components are reusable Vue instances, they receive the same options as new Vue, such as Data, computed, Watch, Methods, and lifecycle hooks. The only exceptions are root instance-specific options like EL.

    Component reuse

    You can reuse components as many times as you like:

    <div id="components-demo">
      <button-counter></button-counter>
      <button-counter></button-counter>
      <button-counter></button-counter>
    </div>
    Copy the code

    Note that each component maintains its count independently when the button is clicked. Because every time you use a component, a new instance of it is created.

    Data must be a function

    When the

    component is defined, its data does not provide an object directly like this:

    data: {
      count: 0
    }
    Copy the code

    Instead, a component’s data option must be a function, so each instance can maintain a separate copy of the returned object:

    data: function () {
      return {
        count: 0}}Copy the code

    If Vue does not have this rule, clicking a button may affect all other instances.

    Organization of components

    Typically, an application is organized as a nested component tree.

    For example, you might have headers, sidebars, content areas, and so on, each of which contains other components like navigation links, blog posts, and so on.

    In order to be used in templates, these components must first be registered for Vue to recognize. There are two types of registration for components: == Global registration == and == local registration ==. So far, our components are only registered globally through Vue.com Ponent:

    Vue.component('my-component-name', {
      // ... options ...
    })
    Copy the code

    Globally registered components can be used in any newly created Vue root instance (via New Vue) after they have been registered, as well as in templates for all children of their component tree.

    Pass data to child components through Prop

    Earlier, we talked about creating a blog component. The problem is that it doesn’t work if you can’t pass it the title or content of a particular blog post that we want to display. That’s where Prop comes in.

    Prop is a set of custom attributes that you can register on components. When a value is passed to a prop attribute, it becomes a property of that component instance. To pass a title to the blog component, we can include it in the list of acceptable props for the component with a props option: props

    Vue.component('blog-post', {
      props: ['title'].template: '<h3>{{ title }}</h3>'
    })
    Copy the code

    By default, a component can have any number of props, and any value can be passed to any prop. In the template above, you can see that we can access this value in the component instance just like we can access the value in data.

    Once a prop is registered, you can pass data as a custom attribute like this:

    <blog-post title="My journey with Vue"></blog-post>
    <blog-post title="Blogging with Vue"></blog-post>
    <blog-post title="Why Vue is so fun"></blog-post>
    Copy the code

    However, in a typical application, you might have an array of blog posts in data:

    new Vue({
      el: '#blog-post-demo'.data: {
        posts: [{id: 1.title: 'My journey with Vue' },
          { id: 2.title: 'Blogging with Vue' },
          { id: 3.title: 'Why Vue is so fun'}]}})Copy the code

    And want to render a component for each blog post:

    <blog-post
      v-for="post in posts"
      v-bind:key="post.id"
      v-bind:title="post.title"
    ></blog-post>
    Copy the code

    As shown above, you can see that we can use V-bind to pass prop dynamically. This is useful when you don’t know exactly what to render at first, such as getting a list of blog posts from an API.

    Single root element

    When building a

    component, your template will end up containing much more than a title:

    <h3>{{ title }}</h3>
    Copy the code

    At the very least, you’ll include the body of the post:

    <h3>{{ title }}</h3>
    <div v-html="content"></div>
    Copy the code

    However, if you try to do this in the template, Vue displays an error explaining that ++every component must have a single root element ++. You can fix this by wrapping the contents of the template in a parent element, for example:

    <div class="blog-post">
      <h3>{{ title }}</h3>
      <div v-html="content"></div>
    </div>
    Copy the code

    It seems that as components become more complex, our posts need not only titles and content, but also release dates, comments, etc. It becomes cumbersome to define a prop for each related information:

    <blog-post
      v-for="post in posts"
      v-bind:key="post.id"
      v-bind:title="post.title"
      v-bind:content="post.content"
      v-bind:publishedAt="post.publishedAt"
      v-bind:comments="post.comments"
    ></blog-post>
    Copy the code

    So it’s time to refactor the

    component to accept a single POST prop:

    <blog-post
      v-for="post in posts"
      v-bind:key="post.id"
      v-bind:post="post"
    ></blog-post>
    Copy the code
    Vue.component('blog-post', {
      props: ['post'].template: ` 
          

    {{ post.title }}

    `
    }) Copy the code

    This and some of the following examples use JavaScript template strings to make multi-line templates more readable. They are not supported in IE, so if you need to support IE without compiling (via tools like Babel or TypeScript), use line break escape characters instead.

    Now, whenever a new property is added to a POST object, it is automatically available within

    .

    Listen for child component events

    When we develop a

    component, some of its functionality may require us to communicate with the parent component. For example, we might introduce a helper feature to enlarge the post size while leaving the rest of the page with the default size.

    In its parent component, we can support this by adding a postFontSize data property:

    new Vue({
      el: '#blog-posts-events-demo'.data: {
        posts: [/ *... * /].postFontSize: 1}})Copy the code

    It can be used in templates to control the size of all posts:

    <div id="blog-posts-events-demo">
      <div :style="{ fontSize: postFontSize + 'em' }">
        <blog-post
          v-for="post in posts"
          v-bind:key="post.id"
          v-bind:post="post"
        ></blog-post>
      </div>
    </div>
    Copy the code

    Now we add a button before the body of each post to enlarge the size:

    Vue.component('blog-post', {
      props: ['post'].template: ` 
          

    {{ post.title }}

    `
    }) Copy the code

    The problem is that this button doesn’t do anything:

    <button>
      Enlarge text
    </button>
    Copy the code

    When this button is clicked, we need to tell the parent component to enlarge the text of all the blog posts. Fortunately, the Vue instance provides a system for custom events to solve this problem. The parent component can listen for any event of the child component instance via V-ON just as it handles native DOM events:

    <blog-post
      .
      v-on:enlarge-text="PostFontSize + = 0.1"
    ></blog-post>
    Copy the code

    Meanwhile, the child component can fire an event by calling the built-in $emit method and passing in the event name:

    <button v-on:click="$emit('enlarge-text')">
      Enlarge text
    </button>
    Copy the code

    With the V-ON: magnanim-text =”postFontSize += 0.1″ listener, the parent component would receive the event and update the value of postFontSize.

    Throw a value using an event

    Sometimes it’s useful to have an event that throws a specific value. For example, we might want to let the

    component decide how much larger its text should be. The second argument to $emit can then be used to provide this value:

    <button v-on:click="$emit (' enlarge - text, 0.1)">
      Enlarge text
    </button>
    Copy the code

    Then when the parent component listens for this event, we can access the value thrown by $event:

    <blog-post
      .
      v-on:enlarge-text="postFontSize += $event"
    ></blog-post>
    Copy the code

    Or, if the event handler is a method:

    <blog-post
      .
      v-on:enlarge-text="onEnlargeText"
    ></blog-post>
    Copy the code

    This value will be passed to the method as the first argument:

    methods: {
      onEnlargeText: function (enlargeAmount) {
        this.postFontSize += enlargeAmount
      }
    }
    Copy the code

    Used on componentsv-model

    Custom events can also be used to create custom input components that support V-Models. Remember:

    <input v-model="searchText">
    Copy the code

    Is equivalent to:

    <input
      v-bind:value="searchText"
      v-on:input="searchText = $event.target.value"
    >
    Copy the code

    When used with components, the V-Model looks like this:

    <custom-input
      v-bind:value="searchText"
      v-on:input="searchText = $event"
    ></custom-input>
    Copy the code

    In order for it to work, the inside this component must:

    • itvalueAttribute is bound to a prop named Value
    • In itsinputWhen the event is raised, the code that throws the new value through the custom input event looks like this:
    Vue.component('custom-input', {
      props: ['value'].template: `  `
    })
    Copy the code

    The V-Model should now work perfectly on this component:

    <custom-input v-model="searchText"></custom-input>
    Copy the code

    Distribute content through slots

    As with HTML elements, we often need to pass content to a component like this:

    <alert-box>
      Something bad happened.
    </alert-box>
    Copy the code

    It might render something like this

    Error! Something bad happened.


    Vue’s custom

    element makes this very easy:

    Vue.component('alert-box', {
      template: ` 
          
    Error!
    `
    }) Copy the code

    Dynamic components

    Sometimes it is useful to switch dynamically between components, such as in a multi-tab interface:

    The above content can be accessed through Vue<component>Element plus a special deltaisAttribute to implement:

    <! Components change when 'currentTabComponent' changes -->
    <component v-bind:is="currentTabComponent"></component>
    Copy the code

    In the example above, the currentTabComponent can include

    • The name of the registered component, or
    • An option object for a component

    You can view and experience the full code here, or see examples of binding component option objects rather than registered component names in this release.

    Note that this attribute can be used with regular HTML elements, but these elements will be treated as components, which means that all attributes will be bound as DOM attributes. For a property like value, to make it work as expected, you need to use the.prop modifier.

    Considerations when parsing DOM templates

    Some HTML elements, such as

      , < OL >,

    • ,
    • , and < SELECT >, have strict restrictions on which elements can appear inside them. Some elements, such as

      , and

    This leads to some problems when we use these constrained elements. Such as:

    <table>
      <blog-post-row></blog-post-row>
    </table>
    Copy the code

    The custom component

    will be promoted externally as invalid content and cause the final render to fail. Fortunately, this particular IS attribute gives us a workaround:

    <table>
      <tr is="blog-post-row"></tr>
    </table>
    Copy the code

    Note that this restriction does not exist if we use templates from the following sources:

    • String (for example:template: '... ')
    • Single file component (.vue)
    • <script type="text/x-template">