一、安装

<script> 标签引入

直接下载并用 <script> 标签引入,Vue 会被注册为全局变量
和 React 需要引入两个 <script> 标签相比,它少一个引入,只需引入一个

  1. <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.9/vue.min.js"></script>

2. npm 安装、脚手架安装

  1. yarn add vue

Vue 官方 CLI:https://github.com/vuejs/vue-cli

  1. yarn global add @vue-cli
  2. vue create my-app
  3. yarn serve

3. 不同构建版本的解读

Vue.js 整体上可以分成两种版本:完整版 和 运行时版

  • 完整版:同时包含编译器和运行时
  • 运行时版: 用来创建 Vue 实例、渲染并处理虚拟 DOM 等代码。(除去了编译器的一切代码)

完整版 VS 运行时版

  1. // 需要编译器
  2. new Vue({
  3. template:'<div>{{hi}}</div>'
  4. })
  5. // 不需要编译器
  6. new Vue({
  7. render(h){
  8. return h('div',this.hi)
  9. }
  10. })

运行时版本比完整版体积小大约 30%

二、介绍

1. Vue 是什么?

Vue 是一套用于构建用户界面的渐进式框架

一个 Vue 类库学习 GitHub:https://github.com/vuejs/awesome-vue#libraries—plugins
一个 Vue 教学视频:https://scrimba.com/learn/vuedocs
一个小 demo 示例了解核心概念

  1. <!DOCTYPE html>
  2. <html lang="zh-CN">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Document</title>
  8. </head>
  9. <body>
  10. <div id="app">
  11. <h1>Hello Word</h1>
  12. <ul>
  13. <li v-for="product in products">
  14. <input type="number" v-model.number="product.quantity">
  15. {{product.name}}
  16. <span v-if="product.quantity === 0">- OUT OF STOCK</span>
  17. <button @click="product.quantity += 1">Add</button>
  18. </li>
  19. </ul>
  20. <h2>Total Inventory: {{totalProducts}}</h2>
  21. </div>
  22. <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.9/vue.js"></script>
  23. <script>
  24. const app = new Vue({
  25. el:'#app',
  26. data:{
  27. products:[]
  28. },
  29. computed:{
  30. totalProducts(){
  31. return this.products.reduce((sum,product)=>{
  32. return sum + product.quantity
  33. },0)
  34. }
  35. },
  36. created(){
  37. setTimeout(()=>{
  38. const products = [
  39. {id:1,quantity:1,name:'compass'},
  40. {id:2,quantity:0,name:'Jacket'},
  41. {id:3,quantity:5,name:'Hiking Socks'},
  42. {id:4,quantity:2,name:'Suntan Lotion'},
  43. ]
  44. this.products = products
  45. })
  46. }
  47. })
  48. </script>
  49. </body>
  50. </html>

2. 声明式渲染

Vue.js 的核心是采用简介的模板语法来声明式地将数据渲染进 DOM 的系统

  • 不再与 HTML 直接交互
  • 所有东西都是响应式的,修改 app.message 的值,下例的相应地更新
  • 一个 Vue 应用会将其挂载到一个 DOM 元素上然后对其完全控制
  • div#app 是我们的入口

v-bind attribute 叫做指令。指令带有前缀 v-,以表示他们是 Vue 提供的特殊 attribute

  • 下例中,该指令的意思是“将这个元素节点的 title attribute 和 Vue 实例的 message property 保持一致”
    1. <div id="app">
    2. <span>{{ message }}</span>
    3. <span v-bind:title="message2">鼠标悬停几秒钟查看此处动态绑定的提示信息</span>
    4. </div>
    1. var app = new Vue({
    2. el: '#app',
    3. data: {
    4. message: 'Hello Vue!',
    5. message2:'页面加载于' + new Data().toLocaleString()
    6. }
    7. })

3. 条件与循环

v-if 指令可以控制一个元素是否显示
v-for 指令可以绑定数组的数据来渲染一个项目列表

  1. <div id="app-3">
  2. <p v-if="seen">现在你看到我了</p>
  3. <ol>
  4. <li v-for="todo in todos">
  5. {{ todo.text }}
  6. </li>
  7. </ol>
  8. </div>
  1. var app3 = new Vue({
  2. el: '#app-3',
  3. data: {
  4. seen: true,
  5. todos: [
  6. { text: '学习 JavaScript' },
  7. { text: '学习 Vue' },
  8. { text: '整个牛项目' }
  9. ]
  10. }
  11. })

4. 处理用户输入

v-on 指令添加一个事件监听器让用户和应用进行交互,通过它调用在 Vue 实例中定义的方法
Vue 还提供了 v-model 指令,它能轻松实现表单输入和应用状态之间的双向绑定

  1. <div id="app-5">
  2. <p>{{ message }}</p>
  3. <button v-on:click="reverseMessage">反转消息</button>
  4. <p>{{ message2 }}</p>
  5. <input v-model="message2">
  6. </div>
  1. var app5 = new Vue({
  2. el: '#app-5',
  3. data: {
  4. message: 'Hello Vue.js!',
  5. message2: 'Hello Vue!'
  6. },
  7. methods: {
  8. reverseMessage: function () {
  9. this.message = this.message.split('').reverse().join('')
  10. }
  11. }
  12. })

5. 组件化应用结构

组件系统是 Vue 的另一个重要概念,是一种抽象,允许我们使用小型、独立和通常可复用的组件构建大型应用

  • 几乎任何类型的应用洁面都可以抽象为一个组件树
  • 在 Vue 里,一个组件本质上是一个拥有预定义选项的一个 Vue 实例

在 Vue 中注册组件

  1. Vue.component('todo-item', {
  2. template: '<li>这是个待办项</li>'
  3. })
  4. var app = new Vue(...)

构建组件模板并使用该组件

  1. <ol>
  2. <todo-item></todo-item>
  3. </ol>

在一个大型应用中,有必要将整个应用程序划分为组件,以使开发更易管理,下面是一个假象例子

  1. <div id="app">
  2. <app-nav></app-nav>
  3. <app-view>
  4. <app-sidebar></app-sidebar>
  5. <app-content></app-content>
  6. </app-view>
  7. </div>

6. Vue组件与自定义元素

Vue 组件非常类似于自定义元素,它是 Web 组件规范的一部分,Vue 的组件语法部分参考了该规范。例如 Vue 组件实现了 Slot APIis attribute。但是,它们有关键性的差别

  1. Web Component 规范已经完全并通过,但未被所有浏览器原生实现,而 Vue 组件不需要任何 polyfill
  2. Vue 组件提供了一些重要功能,最突出的是跨组件数据流、自定义事件通信及构建工具集成

三、Vue 实例

1. 创建一个 Vue 实例

每个 Vue 应用都是通过用 Vue 函数创建一个新的 Vue 实例开始的

  • 创建一个 Vue 实例时,可以传入一个选项对象
  • 一个 Vue 应用有一个通过 new Vue 创建的跟元素实例,以及可选的嵌套的、可复用的组件树组成
    1. var vm = new Vue({
    2. // 选项
    3. })
    1. // 一个 todo 应用的组建树可以是这样的
    2. 根实例
    3. └─ TodoList
    4. ├─ TodoItem
    5. ├─ TodoButtonDelete
    6. └─ TodoButtonEdit
    7. └─ TodoListFooter
    8. ├─ TodosButtonClear
    9. └─ TodoListStatistics

2. 数据和方法

当一个 Vue 实例被创建时,它将 data 对象中的所有 property 加入到 Vue 的响应式系统中。当这些 property 的值发生改变时,视图将会产生“响应”,即匹配更新为新的值。

  • 当这些数据改变时,视图会进行重渲染
  • 值得注意的是只有当实例被创建时就已经存在于 data 中的 property 才是响应式的
  • 唯一的例外是使用 Object.freeze(),这回阻止修改现有的 property,也意味这响应系统无法再追踪变化
  • 除了数据 property,Vue 实例还暴露了一些有用的实例 property 与方法。它们都有前缀 $,以便与用户定义的 property 区分开来
  1. var data = { a: 1 }
  2. var vm = new Vue({
  3. data: data
  4. })
  5. vm.a == data.a // => true
  6. vm.a = 2
  7. data.a // => 2
  8. data.a = 3
  9. vm.a // => 3
  1. var data = { a: 1 }
  2. var vm = new Vue({
  3. el: '#example',
  4. data: data
  5. })
  6. vm.$data === data // => true
  7. vm.$el === document.getElementById('example') // => true
  8. vm.$watch('a', function (newValue, oldValue) {
  9. // 这个回调将在 `vm.a` 改变后调用
  10. })

3. 实例生命周期钩子

每个 Vue 实例在被创建时都要经过一系列的初始化过程——例如,需要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。同时在这个过程中也会运行一些叫做生命周期钩子的函数,这给了用户在不同阶段添加自己的代码的机会。

  • 下面示例 created 钩子可以用来在一个实例被创建之后执行代码。
  • 还有一些其他的钩子,如 mountedupdateddestroyed
  • 生命周期钩子的 this 上下文指向调用它的 Vue 实例。
  • 不要在选项 property 或回调函数上使用箭头函数,因为箭头函数没有 this,而选项中依赖 this,比如
    • created: () => console.log(this.a)
    • vm.$watch('a', newValue => this.myMethod())
      1. new Vue({
      2. data: {
      3. a: 1
      4. },
      5. created: function () {
      6. console.log('a is: ' + this.a)
      7. }
      8. })
      9. // => "a is: 1"

4. 生命周期图示

image.png

四、模板语法

Vue.js 使用了基于 HTML 的模板语法,允许开发者声明式地将 DOM 绑定至底层 Vue 实例的数据。所有 Vue.js 的模板都是合法的 HTML,所以能被遵循规范的浏览器和 HTML 解析器解析。

在底层的实现上,Vue 将模板编译成虚拟 DOM 渲染函数。结合响应系统,Vue 能够智能地计算出最少需要重新渲染多少组件,并把 DOM 操作次数减到最少。

1. 插值

文本

  • 数据绑定最常见的形式就是使用“Mustache”语法 (双大括号) 的文本插值
  • 通过使用 v-once 指令,也能执行一次性的插值
    1. <span>Message: {{ msg }}</span>
    2. <span v-once>这个将不会改变: {{ msg }}</span>

原始 HTML

  • 双大括号会将数据解释为普通文本,而非 HTML 代码。为了输出真正的 HTML,你需要使用 v-html 指令
  • 站点上动态渲染的任意 HTML 可能会非常危险,因为它很容易导致 XSS 攻击
    1. <p>Using mustaches: {{ rawHtml }}</p>
    2. <p>Using v-html directive: <span v-html="rawHtml"></span></p>

Attribute

  • Mustache 语法不能作用在 HTML attribute 上,遇到这种情况应该使用 v-bind 指令
  • 对于布尔 attribute (它们只要存在就意味着值为 true)
  • 如果 isButtonDisabled 的值是 nullundefinedfalse,则 disabled attribute 甚至不会被包含在渲染出来的 <button> 元素中。
    1. <div v-bind:id="dynamicId"></div>
    2. <button v-bind:disabled="isButtonDisabled">Button</button>

使用 JavaScript 表达式

  • 对于所有的数据绑定,Vue.js 都提供了完全的 JavaScript 表达式支持
  • 模板表达式都被放在沙盒中,只能访问全局变量的一个白名单,如 Math 和 Date 。你不应该在模板表达式中试图访问用户定义的全局变量
    1. {{ number + 1 }}
    2. {{ ok ? 'YES' : 'NO' }}
    3. {{ message.split('').reverse().join('') }}
    4. <div v-bind:id="'list-' + id"></div>

2. 指令

指令 (Directives) 是带有 v- 前缀的特殊 attribute。指令 attribute 的值预期是单个 JavaScript 表达式

  • v-for 是例外情况
  • 指令的职责是,当表达式的值改变时,将其产生的连带影响,响应式地作用于 DOM

参数

  • 一些指令能够接收一个“参数”,在指令名称之后以冒号表示。例如,v-bind 指令可以用于响应式地更新 HTML attribute
  • 另一个例子是 v-on 指令,它用于监听 DOM 事件:
    1. <a v-bind:href="url">...</a>
    2. <a v-on:click="doSomething">...</a>

动态参数

  • 从 2.6.0 开始,可以用方括号括起来的 JavaScript 表达式作为一个指令的参数
  • 下面示例中,attributeName 和 eventName 会被作为一个 JavaScript 表达式进行动态求值
  • 动态参数预期会求出一个字符串,异常情况下值为 null
  • 动态参数表达式有一些语法约束,因为某些字符,如空格和引号,放在 HTML attribute 名里是无效的 ```html

  1. 修饰符
  2. - 修饰符 (modifier) 是以半角句号 . 指明的特殊后缀,用于指出一个指令应该以特殊方式绑定。
  3. - 例如,.prevent 修饰符告诉 v-on 指令对于触发的事件调用 event.preventDefault()
  4. ```html
  5. <form v-on:submit.prevent="onSubmit">...</form>

3. 缩写

Vue 为 v-bind 和 v-on 这两个最常用的指令,提供了特定简写

  • 它们看起来可能与普通的 HTML 略有不同
  • 但 : 与 @ 对于 attribute 名来说都是合法字符,在所有支持 Vue 的浏览器都能被正确地解析 ```html

  1. <a name="ra3GU"></a>
  2. ## 五、计算属性和侦听器
  3. <a name="IdNBo"></a>
  4. ### 1. 计算属性
  5. 我们声明了一个计算属性 reversedMessage,并将函数将用作 property vm.reversedMessage 的 getter 函数
  6. - 我们可以像绑定普通 property 一样在模板中绑定计算属性
  7. - 计算属性的 getter 函数是没有副作用 (side effect) 的,这使它更易于测试和理解
  8. ```html
  9. <div id="example">
  10. <p>Original message: "{{ message }}"</p>
  11. <p>Computed reversed message: "{{ reversedMessage }}"</p>
  12. </div>
  1. var vm = new Vue({
  2. el: '#example',
  3. data: {
  4. message: 'Hello'
  5. },
  6. computed: {
  7. reversedMessage: function () {
  8. return this.message.split('').reverse().join('')
  9. }
  10. }
  11. })

2. 计算属性缓存 vs 方法

通过在表达式中调用方法可以达到同样的效果,然后 Vue 做了对计算属性做了一个功能,就是缓存

  • 计算属性是基于它们的响应式依赖进行缓存的
  • 只在相关响应式依赖发生改变时它们才会重新求值
  • 相比之下,每当触发重新渲染时,调用方法将总会再次执行函数,性能开销会更大
  1. <p>Reversed message: "{{ reversedMessage() }}"</p>
  1. methods: {
  2. reversedMessage: function () {
  3. return this.message.split('').reverse().join('')
  4. }
  5. }

3. 计算属性 vs 侦听属性

Vue 提供了侦听属性来观察和响应 Vue 实例上的数据变动,但有一些数据需要随着其他数据变动而变动时,计算属性会是更好的做法

  • 下面是他们之间的对比
    1. <div id="demo">{{ fullName }}</div>
    1. var vm = new Vue({
    2. el: '#demo',
    3. data: {
    4. firstName: 'Foo',
    5. lastName: 'Bar',
    6. fullName: 'Foo Bar'
    7. },
    8. watch: {
    9. firstName: function (val) {
    10. this.fullName = val + ' ' + this.lastName
    11. },
    12. lastName: function (val) {
    13. this.fullName = this.firstName + ' ' + val
    14. }
    15. }
    16. })
    ```javascript

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

  1. <a name="6b6v7"></a>
  2. ### 4. 计算属性的 setter
  3. 计算属性默认只有 setter,不过在需要时也可以提供一个 setter
  4. - 运行 vm.fullName = 'John Doe' 时,setter 会被调用,vm.firstName 和 vm.lastName 也会相应地被更新
  5. ```javascript
  6. // ...
  7. computed: {
  8. fullName: {
  9. get: function () {
  10. return this.firstName + ' ' + this.lastName
  11. },
  12. set: function (newValue) {
  13. var names = newValue.split(' ')
  14. this.firstName = names[0]
  15. this.lastName = names[names.length - 1]
  16. }
  17. }
  18. }
  19. // ...

5. 侦听器

当需要在数据变化时执行异步或开销较大的操作时,使用 watch 这个方式是最有用的

  • 下面是一个示例,使用 watch 选项允许我们执行异步操作(访问一个 API),限制我们执行该操作的频率,并在我们得到最终结果前,设置中间状态。
  • 除了 watch 选项外,还可以使用命令式的 vm.$watch ```html

    Ask a yes/no question:

    {{ answer }}

  1. <a name="zzp51"></a>
  2. ## 六、Class 与 Style 绑定
  3. 操作元素的 class 列表和内联样式是数据绑定的一个常见需求,可以用 v-bind 处理它们:只需要通过表达式计算出字符串结果即可。<br />在将 v-bind 用于 class 和 style 时,Vue.js 做了专门的增强。表达式结果的类型除了字符串之外,还可以是对象或数组
  4. <a name="iPdTU"></a>
  5. ### 1. 绑定 HTML Class
  6. 对象语法
  7. ```html
  8. <div
  9. class="static"
  10. v-bind:class="{ active: isActive, 'text-danger': hasError }"
  11. ></div>
  12. <div v-bind:class="classObject"></div>

数组语法

  • 可以使用三元表达式
  • 在数组项中,还可以使用对象语法 ```html
用在组件上 - 当在一个自定义组件上使用 class property 时,这些 class 将被添加到该组件的根元素上面 - 这个元素上已经存在的 class 不会被覆盖javascript Vue.component(‘my-component’, { template: ‘

Hi

‘ }) ```html <my-component class="baz boo"></my-component> <!-- 将被渲染为 --> <p class="foo bar baz boo">Hi</p> ### 2. 绑定内联样式 对象语法 - v-bind:style 的对象语法十分直观,看着非常像 CSS,但其实是一个 JavaScript 对象 - CSS property 名可以用驼峰式(camelCase)或短横线(kebal-case)来命名 ```html
数组语法 - 将多个样式对象应用到同一个元素上html
自动添加前缀 - 当 v-bind:style 使用需要添加浏览器引擎前缀的 CSS property 时,如 transform,Vue.js 会自动侦测并添加相应的前缀 多重值 - 从 2.3.0 起你可以为 style 绑定中的 property 提供一个包含多个值的数组,常用于提供多个带前缀的值 - 这样写只会渲染数组中最后一个被浏览器支持的值 - 在本例中,如果浏览器支持不带浏览器前缀的 flexbox,那么就只会渲染 `display: flex` html
<a name="BqZvn"></a> ## 七、条件渲染 `v-if` 指令用于条件渲染一块内容。这块内容只会在指令的表达式返回 truthy 值的时候被渲染。html

Vue is awesome!

Oh no 😢

<a name="r4MHW"></a> ### 1. 在 <template> 元素上使用 v-if 条件渲染分组 最终的渲染结果将不包含 `<template>` 元素html <a name="UqmDg"></a> ### 2. v-elsehtml
Now you see me
Now you don’t
<a name="gCv5U"></a> ### 3. v-else-if - 2.1.0 新增html
A
B
C
Not A/B/C
<a name="Tf6Fr"></a> ### 4. 用 key 管理可复用元素 Vue 会尽可能高效地渲染元素,通常会复用已有元素而不是从头开始渲染 - 这么做除了使 Vue 变得非常快之外,还有其它一些好处,例如,如果你允许用户在不同的登录方式之间切换 - 下面示例中,每次切换时,输入框都将被重新渲染 - 并且 <label> 元素仍然会被高效地复用,因为它们没有添加 key attributehtml <a name="rGBeK"></a> ### 5. v-show v-show 的元素始终会被渲染并保留在 DOM 中。v-show 只是简单地切换元素的 CSS property `display` html

Hello!

<a name="tpazI"></a> ### 6. v-if vs v-show v-if 是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。<br />v-if 也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。 相比之下,v-show 就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。<br />一般来说,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if 较好。 <a name="IGRFl"></a> ### 7. v-if 与 v-for 一起使用 当 v-if 与 v-for 一起使用时,v-for 具有比 v-if 更高的优先级<br />但是,不推荐同时使用 v-if 和 v-for <a name="PJMRD"></a> ## 八、列表渲染 <a name="AkTK3"></a> ### 1. 用 v-for 把一个数组对应为一组元素 `v-for` 指令需要使用 `item in items` 形式的特殊语法,其中 `items` 是源数据数组,而 `item` 则是被迭代的数组元素的别名 - 在 v-for 块中,我们可以访问所有父作用于的 property - `v-for` 还支持一个可选的第二个参数,即当前项的索引 - 也可以用 of 替代 in 作为分隔符,因为它更接近 JavaScript 迭代器的语法html
  • {{ item.message }}
  • {{ parentMessage }} - {{ index }} - {{ item.message }}
<a name="azmLb"></a> ### 2. 在 v-for 里使用对象 v-for 除了可以遍历数组,还可以遍历一个对象的 property - 也可以提供第二个的参数为 property 名称 (也就是键名) - 还可以用第三个参数作为索引 - 在遍历对象时,会按 Object.keys() 的结果遍历,但是不能保证它的结果在不同的 JavaScript 引擎下都一致html
  • {{ value }}
<a name="JSHzf"></a> ### 3. 维护状态 当 Vue 正在更新使用 v-for 渲染的元素列表时,它默认使用“就地更新”的策略。 - 如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序,而是就地更新每个元素,并且确保它们在每个索引位置正确渲染。 为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 `key` attribute - 建议尽可能在使用 `v-for `时提供 `key` attribute,除非遍历输出的 DOM 内容非常简单,或者是刻意依赖默认行为以获取性能上的提升 - 因为它是 Vue 识别节点的一个通用机制,`key` 并不仅与 `v-for` 特别关联,它还有其他用途 - 不要使用对象或数组之类的非基本类型值作为 `v-for` 的 `key`。请用字符串或数值类型的值html
<a name="KvkU7"></a> ### 4. 数组更新检测 变更方法 - Vue 将被侦听的数组的变更方法进行了变更,所以它们也将会触发视图更新。这些被变更过的方法包括 - push() - pop() - shift() - unshift() - splice() - sort() - reverse() 替换数组 - 数组的非变更方法 filter()、concat()、slice(),它们不会变更原始数组,而总是返回一个新数组 - 当使用非变更方法时,可以用新数组替换旧数组html example1.items = example1.items.filter(function (item) { return item.message.match(/Foo/) }) Vue 为了使得 DOM 元素得到最大范围的重用而实现了一些智能的启发式方法,所以用一个含有相同元素的数组去替换原来的数组是非常高效的操作<br />注意事项 - 由于 JavaScript 的限制,Vue 不能检测数组和对象的变化。 <a name="NON4H"></a> ### 5. 显示过滤/排序后的结果 有时,我们想要显示一个数组经过过滤或排序后的版本,而不实际变更或重置原始数据。在这种情况下,可以创建一个计算属性,来返回过滤或排序后的数组html
  • {{ n }}
  • ```javascript data: { numbers: [ 1, 2, 3, 4, 5 ] }, computed: { evenNumbers: function () { return this.numbers.filter(function (number) { return number % 2 === 0 }) } } 在计算属性不适用的情况下 (例如,在嵌套 v-for 循环中) 你可以使用一个方法 html <ul v-for="set in sets"> <li v-for="n in even(set)">{{ n }}</li> </ul> javascript 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 }) } } ### 6. 在 v-for 里使用值范围 v-for 也可以接受整数。在这种情况下,它会把模板重复对应次数 html <div> <span v-for="n in 10">{{ n }} </span> </div> ### 7. 在