ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
[[官方文档,template syntax]](https://vuejs.org/v2/guide/syntax.html) Vue.js uses an HTML-based template syntax that allows you to declaratively bind the rendered DOM to the underlying Vue instance’s data. All Vue.js templates are valid HTML that can be parsed by spec-compliant browsers and HTML parsers. If you are familiar with Virtual DOM concepts and prefer the raw power of JavaScript, you can also [directly write render functions](https://vuejs.org/v2/guide/render-function.html) instead of templates, with optional JSX support. ***** 内容索引 [TOC] ***** ## Interpolations ### Text (`v-once={{}}`) The most basic form of data binding is text interpolation using the “Mustache” syntax (double curly braces): ~~~html <!-- html--> <span>Message: {{ msg }}</span> ~~~ The mustache tag will be replaced with the value of the`msg`property on the corresponding data object. It will also be updated whenever the data object’s`msg`property changes. You can also perform one-time interpolations that do not update on data change by using the [v-once directive](https://vuejs.org/v2/api/#v-once), but keep in mind this will also affect any other bindings on the same node: ~~~ <span v-once>This will never change: {{ msg }}</span> ~~~ ### Raw HTML (`v-html=""`) The double mustaches interprets the data as plain text, not HTML. In order to output real HTML, you will need to use the`v-html`directive: ~~~html <!-- html--> <p>Using mustaches: {{ rawHtml }}</p> <p>Using v-html directive: <span v-html="rawHtml"></span></p> ~~~ ~~~javascript //js var rawHtml ='<span style="color:red;">This should be red</span>' ~~~ >[warning] Dynamically rendering arbitrary HTML on your website can be very dangerous because it can easily lead to [XSS vulnerabilities](https://en.wikipedia.org/wiki/Cross-site_scripting). Only use HTML interpolation on trusted content and**never**on user-provided content. ### Attributes (`v-bind:attr=""`) Mustaches cannot be used inside HTML attributes. Instead, use a[v-bind directive](https://vuejs.org/v2/api/#v-bind): ~~~html <!-- html--> <div v-bind:id="dynamicId"></div> ~~~ In the case of boolean attributes, where their mere existence implies`true`,`v-bind`works a little differently. In this example: ~~~html <!-- html--> <button v-bind:disabled="isButtonDisabled">Button</button> ~~~ If` isButtonDisabled` has the value of `null`,`undefined`, or `false`, the `disabled` attribute will not even be included in the rendered `<button>` element. ### JavaScript expressions Vue.js actually supports the full power of JavaScript expressions inside all data bindings: ~~~html <!-- html--> {{ number + 1 }} {{ ok ? 'YES' : 'NO' }} {{ message.split('').reverse().join('') }} <div v-bind:id="'list-' + id"></div> ~~~ These expressions will be evaluated as JavaScript in the data scope of the owner Vue instance. One restriction is that each binding can only contain **one single expression**, so the following will **NOT** work: ~~~html <!-- html--> <!-- this is a statement, not an expression: --> {{ var a = 1 }} <!-- flow control won't work either, use ternary expressions --> {{ if (ok) { return message } }} ~~~ >[warning] Template expressions are sandboxed and only have access to a [whitelist of globals](https://github.com/vuejs/vue/blob/v2.6.10/src/core/instance/proxy.js#L9) such as `Math` and `Date`. You should not attempt to access user defined globals in template expressions. ## Directives (`v-*`) Directives are special attributes with the`v-`prefix. Directive attribute values are expected to be **a single JavaScript expression** (with the exception of`v-for`, which will be discussed later). A directive’s job is to reactively apply side effects to the DOM when the value of its expression changes. ~~~html <!-- html--> <p v-if="seen">Now you see me</p> ~~~ Here, the`v-if`directive would remove/insert the`<p>`element based on the truthiness of the value of the expression`seen`. ### Argument (`v-bind:attr=""` `v-on:event=""` ) Some directives can take an “argument”, denoted by a colon after the directive name. For example, the `v-bind`directive is used to reactively update an HTML attribute: ~~~html <!-- html--> <a v-bind:href="url"> ... </a> ~~~ Here`href`is the argument, which tells 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 to DOM events: ~~~html <!-- html--> <a v-on:click="doSomething"> ... </a> ~~~ Here the argument is the event name to listen to. We will talk about event handling in more detail too. ### Dynamic Arguments (2.6.0+, `v-bind:[attr]=""` `v-on:[event]=""`) Starting in version 2.6.0, it is also possible to use a JavaScript expression in a directive argument by wrapping it with square brackets: ~~~html <!-- html--> <!-- Note that there are some constraints to the argument expression, as explained in the "Dynamic Argument Expression Constraints" section below. --> <a v-bind:[attributeName]="url"> ... </a> ~~~ For example, if your Vue instance has a data property, `attributeName`, whose value is`"href"`, then this binding will be equivalent to `v-bind:href`. use dynamic arguments to bind a handler to a dynamic event name: ~~~html <!-- html--> <a v-on:[eventName]="doSomething"> ... </a> ~~~ In this example, when`eventName`‘s value is`"focus"`,`v-on:[eventName]`will be equivalent to`v-on:focus`. >[warning] * Dynamic arguments are expected to evaluate to a string, with the exception of`null`. The special value`null`can be used to explicitly remove the binding. Any other non-string value will trigger a warning. > * HTML attribute names are case-insensitive, so browsers will interpret any uppercase characters as lowercase. ~~~html <!-- html--> <!-- This will be converted to v-bind:[someattr] in in-DOM templates. Unless you have a "someattr" property in your instance, your code won't work. --> <a v-bind:[someAttr]="value"> ... </a> ~~~ ### Modifiers (`v-on:event.modifier=""` `v-model:event.modifier=""`) Modifiers are special postfixes denoted by a dot, which indicate that a directive should be bound in some special way. For example, the`.prevent`modifier tells the`v-on`directive to call`event.preventDefault()`on the triggered event: ~~~html <!-- html--> <form v-on:submit.prevent="onSubmit"> ... </form> ~~~ You’ll see other examples of modifiers later, [for`v-on`](https://vuejs.org/v2/guide/events.html#Event-Modifiers)and [for`v-model`](https://vuejs.org/v2/guide/forms.html#Modifiers). ## Shorthands (`:` `@`) the need for the`v-`prefix becomes less important when you are building a `SPA(Single page application)`, where Vue manages every template. Therefore, Vue provides special shorthands for two of the most often used directives,`v-bind`and`v-on`: `v-bind` Shorthand ~~~html <!-- html--> <!-- full syntax --> <a v-bind:href="url"> ... </a> <!-- shorthand --> <a :href="url"> ... </a> <!-- shorthand with dynamic argument (2.6.0+) --> <a :[key]="url"> ... </a> ~~~ `v-on`Shorthand ~~~html <!-- html--> <!-- full syntax --> <a v-on:click="doSomething"> ... </a> <!-- shorthand --> <a @click="doSomething"> ... </a> <!-- shorthand with dynamic argument (2.6.0+) --> <a @[event]="doSomething"> ... </a> ~~~ `:`and`@`are valid characters for attribute names and all Vue-supported browsers can parse it correctly. In addition, they do not appear in the final rendered markup. The shorthand syntax is totally optional. ## Class and Style Bindings A common need for data binding is manipulating an element’s class list and its inline styles. Since they are both attributes, we can use`v-bind`to handle them: we only need to calculate a final string with our expressions. Vue provides special enhancements when`v-bind`is used with`class`and`style`. In addition to strings, the expressions can also evaluate to objects or arrays. ### Binding HTML Classes (`v-bind:class=""`) 1. Object Syntax You can have multiple classes toggled by having more fields in the object. In addition, the`v-bind:class`directive can also co-exist with the plain`class`attribute. So given the following template: ~~~html <!-- html--> <div class="static" v-bind:class="{ active: isActive, 'text-danger': hasError }" ></div> ~~~ And the following data: ~~~javascript //js data: { isActive: true, hasError: false } ~~~ It will render: ~~~html <!-- html--> <div class="static active"></div> ~~~ When`isActive`or`hasError`changes, the class list will be updated accordingly. For example, if`hasError`becomes`true`, the class list will become`"static active text-danger"`. ~~~html <!-- html--> <div v-bind:class="classObject"></div> ~~~ ~~~javascript //js data: { isActive: true, error: null }, computed: { classObject: function () { return { active: this.isActive && !this.error, 'text-danger': this.error && this.error.type === 'fatal' } } } ~~~ 2. Array Syntax We can pass an array to`v-bind:class`to apply a list of classes: ~~~html <!-- html--> <div v-bind:class="[activeClass, errorClass]"></div> ~~~ ~~~javascript //js data: { activeClass: 'active', errorClass: 'text-danger' } ~~~ Which will render: ~~~html <!-- html--> <div class="active text-danger"></div> ~~~ If you would like to also toggle a class in the list conditionally, you can do it with a ternary expression: ~~~html <!-- html--> <div v-bind:class="[isActive ? activeClass : '', errorClass]"></div> ~~~ This will always apply`errorClass`, but will only apply`activeClass`when`isActive`is truthy. However, this can be a bit verbose if you have multiple conditional classes. That’s why it’s also possible to use the object syntax inside array syntax: ~~~html <!-- html--> <div v-bind:class="[{ active: isActive }, errorClass]"></div> ~~~ 3. With Components When you use the`class`attribute on a custom component, those classes will be added to the component’s root element. Existing classes on this element will not be overwritten. For example, if you declare this component: ~~~javascript //js Vue.component('my-component', { template: '<p class="foo bar">Hi</p>' }) ~~~ Then add some classes when using it: ~~~html <!-- html--> <my-component class="baz boo"></my-component> ~~~ The rendered HTML will be: ~~~html <!-- html--> <p class="foo bar baz boo">Hi</p> ~~~ The same is true for class bindings: ~~~html <!-- html--> <my-component v-bind:class="{ active: isActive }"></my-component> ~~~ When`isActive`is truthy, the rendered HTML will be: ~~~html <!-- html--> <p class="foo bar active">Hi</p> ~~~ ### Binding Inline Styles (`v-bind:style=""`) 1. Object Syntax You can use either camelCase or kebab-case (use quotes with kebab-case) for the CSS property names: ~~~html <!-- html--> <div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div> ~~~ ~~~javascript //js data: { activeColor: 'red', fontSize: 30 } ~~~ ~~~html <!-- html--> <div v-bind:style="styleObject"></div> ~~~ ~~~javascript //js data: { styleObject: { color: 'red', fontSize: '13px' } } ~~~ Again, the object syntax is often used in conjunction with computed properties that return objects. 2. Array Syntax apply multiple style objects to the same element: ~~~html <!-- html--> <div v-bind:style="[baseStyles, overridingStyles]"></div> ~~~ 3. Auto-prefixing When you use a CSS property that requires [vendor prefixes](https://developer.mozilla.org/en-US/docs/Glossary/Vendor_Prefix) in `v-bind:style`, for example `transform`, Vue will automatically detect and add appropriate prefixes to the applied styles. 4. Multiple Values Starting in 2.3.0+ you can provide an array of multiple (prefixed) values to a style property, for example: ~~~html <!-- html--> <div v-bind:style="{ display: ['-webkit-box', '-ms-flexbox', 'flex'] }"></div> ~~~ This will only render the last value in the array which the browser supports. In this example, it will render `display: flex`for browsers that support the unprefixed version of flexbox. ## Conditional Rendering (`v-if` `v-else` `v-show` `v-for`) ~~~html <!-- html--> <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> ~~~ Similar to `v-else`, a `v-else-if`element must immediately follow a `v-if`or a `v-else-if`element. **`v-if`vs`v-show`** * `v-if`is “real” conditional rendering because it ensures that event listeners and child components inside the conditional block are properly destroyed and re-created during toggles. * `v-if`is also **lazy**: if the condition is false on initial render, it will not do anything - the conditional block won’t be rendered until the condition becomes true for the first time. * `v-show`is much simpler - the element is always rendered regardless of initial condition and remain in the DOM, with CSS-based toggling(only toggles the`display`CSS property of the element). Generally speaking,`v-if`has higher toggle costs while`v-show`has higher initial render costs. So prefer`v-show`if you need to toggle something very often, and prefer`v-if`if the condition is unlikely to change at runtime. **`v-if`vs`v-for`** * Using`v-if`and`v-for`together is **not recommended**. * When used together with`v-if`,`v-for`has a higher priority than`v-if`. ### `v-for` We can use the`v-for`directive to render a list of items based on an array/object. The`v-for`directive requires a special syntax in the form of`item in items`, where`items`is the source data array and`item`is an**alias**for the array element being iterated on: 1. Mapping an Array to Elements ~~~html <!-- html--> <ul id="example-1"> <li v-for="item in items"> {{ item.message }} </li> </ul> ~~~ ~~~javascript //js var example1 = new Vue({ el: '#example-1', data: { items: [ { message: 'Foo' }, { message: 'Bar' } ] } }) ~~~ `v-for`also supports an optional second argument for the index of the current item. ~~~html <!-- html--> <ul id="example-2"> <li v-for="(item, index) in items"> {{ parentMessage }} - {{ index }} - {{ item.message }} </li> </ul> ~~~ ~~~javascript //js var example2 = new Vue({ el: '#example-2', data: { parentMessage: 'Parent', items: [ { message: 'Foo' }, { message: 'Bar' } ] } }) ~~~ 2. iterating over an object ~~~javascript //js new Vue({ el: '#v-for-object', data: { object: { title: 'How to do lists in Vue', author: 'Jane Doe', publishedAt: '2016-04-10' } } }) ~~~ use`v-for`to iterate through the properties of an object. ~~~html <!-- html--> <ul id="v-for-object" class="demo"> <li v-for="value in object"> {{ value }} </li> </ul> ~~~ displayed: * How to do lists in Vue * Jane Doe * 2016-04-10 a second argument for the property’s name (a.k.a. key): ~~~html <!-- html--> <div v-for="(value, name) in object"> {{ name }}: {{ value }} </div> ~~~ displayed: * title: How to do lists in Vue * author: Jane Doe * publishedAt: 2016-04-10 another for the index: ~~~html <!-- html--> <div v-for="(value, name, index) in object"> {{ index }}. {{ name }}: {{ value }} </div> ~~~ displayed: * 0\. title: How to do lists in Vue * 1\. author: Jane Doe * 2\. publishedAt: 2016-04-10 ### `key` It is recommended to provide a `key`attribute with`v-for`whenever possible, unless the iterated DOM content is simple, or you are intentionally relying on the default behavior for performance gains. Since it’s a generic mechanism for Vue to identify nodes, the`key`also has other uses that are not specifically tied to`v-for`. ~~~html <!-- html--> <div v-for="item in items" v-bind:key="item.id"> <!-- content --> </div> ~~~ >[warning] Don’t use non-primitive values like objects and arrays as`v-for`keys. Use string or numeric values instead. For detailed usage of the`key`attribute, please see the [`key`API documentation](https://vuejs.org/v2/api/#key). The`key`special attribute is primarily used as a hint for Vue’s virtual DOM algorithm to identify VNodes when diffing the new list of nodes against the old list. * Without keys, Vue uses an algorithm that minimizes element movement and tries to patch/reuse elements of the same type in-place as much as possible. * With keys, it will reorder elements based on the order change of keys, and elements with keys that are no longer present will always be removed/destroyed. It can also be used to force replacement of an element/component instead of reusing it. This can be useful when you want to: * Properly trigger lifecycle hooks of a component * Trigger transitions For example: ~~~html <!-- html--> <transition> <span :key="text">{{ text }}</span> </transition> ~~~ When`text`changes, the`<span>`will always be replaced instead of patched, so a transition will be triggered. ### Array Change Detection ?? ### Object Change Detection Caveats **Vue cannot detect property addition or deletion**,due to limitations of modern JavaScript. For example: ~~~javascript //js var vm = new Vue({ data: { a: 1 } }) // `vm.a` is now reactive vm.b = 2 // `vm.b` is NOT reactive ~~~ Vue does not allow dynamically adding new root-level reactive properties to an already created instance. However, it’s possible to add reactive properties to a nested object using the`Vue.set(object, propertyName, value)`method. For example, given: ~~~javascript //js var vm = new Vue({ data: { userProfile: { name: 'Anika' } } }) ~~~ You could add a new`age`property to the nested`userProfile`object with: ~~~javascript //js Vue.set(vm.userProfile, 'age', 27) ~~~ You can also use the`vm.$set`instance method, which is an alias for the global`Vue.set`: ~~~javascript //js vm.$set(vm.userProfile, 'age', 27) ~~~ Sometimes you may want to assign a number of new properties to an existing object, for example using`Object.assign()`or`_.extend()`. In such cases, you should create a fresh object with properties from both objects: ~~~javascript //js vm.userProfile = Object.assign({}, vm.userProfile, { age: 27, favoriteColor: 'Vue Green' }) ~~~ instead of: ~~~javascript //js Object.assign(vm.userProfile, { age: 27, favoriteColor: 'Vue Green' }) ~~~