• 微信号
  • 微信号
您当前的位置:首页 > 学海无涯 > 茑语花香>从小白开始学vue学习笔记(一)——基础篇

从小白开始学vue学习笔记(一)——基础篇

孤峰 孤峰家 2023-08-08 139人阅读

目录

一、引入vue 二、helloWorld程序

三、声明式渲染

四、条件与循环

五、处理用户输入

六、组件化应用构建

与自定义元素的关系

SLOT API

定义

插槽算法

获取分布式节点算法

分布分辨率算法 slot 元件 扩展到 Element 七、Vue实例 1、创建一个Vue实例

2、数据与方法

3、实例生命周期钩子

4、生命周期图示

八、模板语法

1、插值

(1)文本

(2)原始html

(3)特性

(4)使用Js表达式

2、指令

(1)参数

(2)动态参数

(3)修饰符

3、缩写 v-bind缩写 : v-on缩写 @

九、计算属性和侦听器

1、计算属性

(1)基础例子

(2)计算属性缓存vs方法 (2)计算属性setter

2、侦听器 vm.$watch(expOrFn, callback, [options]) 十、Class 与 Style 绑定

1、绑定HTML Class

(1)对象语法

(2)数组语法

(3)用在组件上

2、绑定内联样式

(1)对象语法

(2)数组语法

(3)自动添加前缀

(4)多重值

十一、条件渲染

1、v-if

元素使用v-if条件渲染分组

一、引入vue

1、开发环境版本,包含了有帮助的命令行警告: <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

2、生产环境版本,优化了尺寸和速度: <script src="https://cdn.jsdelivr.net/npm/vue"></script> 请注意我们不推荐新手直接使用 vue-cli,尤其是在你还不熟悉基于 Node.js 的构建工具时。

二、helloWorld程序

var app = new Vue({el: '#app',data: {message: 'Hello, Vue!'}});

三、声明式渲染

我们已经成功创建了第一个 Vue 应用!看起来这跟渲染一个字符串模板非常类似,但是 Vue 在背后做了大量工作。现在数据和 DOM 已经被建立了关联,所有东西都是响应式的。我们要怎么确认呢?打开你的浏览器的 JavaScript 控制台 (就在这个页面打开),并修改 app.message 的值,你将看到上例相应地更新。

var app2 = new Vue({el: '#app-2',data: {message: '页面加载于 ' + new Date().toLocaleString()}})

·span的title属性就是悬停显示的提示信息 这里我们遇到了一点新东西。你看到的 v-bind 特性被称为指令。指令带有前缀 v-,以表示它们是 Vue 提供的特殊特性。可能你已经猜到了,它们会在渲染的 DOM 上应用特殊的响应式行为。在这里,该指令的意思是:“将这个元素节点的 title 特性和 Vue 实例的 message 属性保持一致”。

(1)完整语法:<span v-bind:class="classProperty"></span >,解释:v-bind 是指令,: 后面的 class 是参数,classProperty 则在官方文档中被称为“预期值”。

(2)缩写语法:<span :class="classProperty"></span >,解释:: 后面的 class 是参数,classProperty 则在官方文档中被称为“预期值”。 如果你再次打开浏览器的 JavaScript 控制台,输入 app2.message = '新消息',就会再一次看到这个绑定了 title 特性的 HTML 已经进行了更新。

四、条件与循环

var app3 = new Vue({el: '#app-3',data: {seen: true}})

var app4 = new Vue({el: '#app-4',data: {todos: [{ text: '学习 JavaScript' },{ text: '学习 Vue' },{ text: '整个牛项目' }]}}) 在控制台里,输入 app4.todos.push({ text: '新项目' }),你会发现列表较后添加了一个新项目。

五、处理用户输入

var app5 = new Vue({el: '#app-5',data: {message: 'Hello Vue.js!'},methods: {reverseMessage: function () {this.message = this.message.split('').reverse().join('')}}}) var app6 = new Vue({el: '#app-6',data: {message: 'Hello Vue!'}})

六、组件化应用构建

Vue.component('todo-item', {template: '<li>这是个待办项</li>'})var example = new Vue({el: '.example',data: {}}) Vue.component('todo-item', {props: ['todo'],template: '<li>{{ todo.id }} {{ todo.text }}</li>'})var example = new Vue({el: '.example',data: {groceryList: [{ id: 0, text: '素菜' },{ id: 1, text: '素2菜' },{ id: 2, text: '素23菜' }]}})

<app-nav></app-nav><app-view><app-sidebar></app-sidebar><app-content></app-content></app-view>

与自定义元素的关系

你可能已经注意到 Vue 组件非常类似于自定义元素——它是 Web 组件规范的一部分,这是因为 Vue 的组件语法部分参考了该规范。例如 Vue 组件实现了 Slot API 与 is 特性。但是,还是有几个关键差别:

Web Components 规范已经完成并通过,但未被所有浏览器原生实现。目前 Safari 10.1+、Chrome 54+ 和 Firefox 63+ 原生支持 Web Components。相比之下,Vue 组件不需要任何 polyfill,并且在所有支持的浏览器 (IE9 及更高版本) 之下表现一致。必要时,Vue 组件也可以包装于原生自定义元素之内。

Vue 组件提供了纯自定义元素所不具备的一些重要功能,最突出的是跨组件数据流自定义事件通信以及构建工具集成 虽然 Vue 内部没有使用自定义元素,不过在应用使用自定义元素、或以自定义元素形式发布时,依然有很好的互操作性。Vue CLI 也支持将 Vue 组件构建成为原生的自定义元素。

SLOT API 定义

这些是新的定义。对于所有其他定义,请参阅当前规范。

slot - 阴影树中的已定义位置。由slot元素代表。

插槽名称 -一个名称插槽

默认插槽 -一个插槽用于无指定节点插槽名称

插槽算法

开槽算法分配一个影子树主机节点到插槽那棵树。 输入 HOST - 影子树主机 输出HOST的 所有子节点都已插入

让TREE成为HOST的影子树

让DEFAULT成为一个空的节点列表

对于每个子节点NODE的HOST,按照树形结构顺序:

让NAME成为NODE的插槽名称

如果缺少NAME,请将NODE添加到DEFAULT

设SLOT为TREE的插槽名称为 NAME的插槽

如果SLOT不存在,则丢弃节点

否则,将NODE分配给SLOT

让DEFAULT-SLOT是在默认插槽用于TREE

如果DEFAULT-SLOT不存在,请停止

否则,将DEFAULT中的所有节点分配给DEFAULT-SLOT。 将每个节点分配给插槽时,此插槽也会添加到节点的目标插入点列表中。

获取分布式节点算法

得到分布式节点算法递归收集当前分配到一个给定的所有节点插槽 输入 SLOT - 阴影树中 的插槽输出 LIST - 分布式节点的列表

对于分配给SLOT的每个节点NODE:

如果NODE是一个插槽:1。让SUB-LIST成为(递归)运行带有NODE作为参数的获取分布式节点算法的结果2.将SUB-LIST中的所有节点附加到LIST

否则,将NODE附加到LIST。 分布分辨率算法 该算法从当前规范中取代分布分辨率算法输入 NODE-TREE - 节点树 输出 更新分发结果。

对于参与NODE-TREE的每个影子主机HOST,按树顺序:

HOST为参数运行插槽算法

SHADOW-TREE成为HOST的影子树

使用SHADOW-TREE作为输入运行* 分布式解析算法(递归) slot 元件 slotelement表示阴影树中的一个插槽。具有与content元素相同的渲染行为。

属性:

name - 插槽的名称。 inte**ce HTMLSlotElement:HTMLElement {

属性DOMString名称; NodeList getDistributedNodes();

}

name- 反映name属性。

getDistributedNodes---返回运行get distributed nodes算法的结果。 扩展到 Element

部分界面 元素 {

属性DOMString槽;

}

slot- 反映slot属性。该slot属性表示插槽名称

七、Vue实例

var vm = new Vue({// 选项}) 虽然没有完全遵循 MVVM 模型,但是 Vue 的设计也受到了它的启发。因此在文档中经常会使用 vm (ViewModel 的缩写) 这个变量名表示 Vue 实例。 当创建一个 Vue 实例时,你可以传入一个选项对象。这篇教程主要描述的就是如何使用这些选项来创建你想要的行为。作为参考,你也可以在 API 文档 中浏览完整的选项列表。 一个 Vue 应用由一个通过 new Vue 创建的根 Vue 实例,以及可选的嵌套的、可复用的组件树组成。举个例子,一个 todo 应用的组件树可以是这样的: 根实例└─ TodoList├─ TodoItem│ ├─ DeleteTodoButton│ └─ EditTodoButton└─ TodoListFooter├─ ClearTodosButton└─ TodoListStatistics 我们会在稍后的组件系统章节具体展开。不过现在,你只需要明白所有的 Vue 组件都是 Vue 实例,并且接受相同的选项对象 (一些根实例特有的选项除外)。

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

// 我们的数据对象var data = { a: 1 }// 该对象被加入到一个 Vue 实例中var vm = new Vue({data: data})// 获得这个实例上的属性// 返回源数据中对应的字段vm.a == data.a // => true// 设置属性也会影响到原始数据 

var data = { a: 1 }var vm = new Vue({el: '#example',data: data})vm.$data === data // => truevm.$el === document.getElementById('example') // => true// $watch 是一个实例方法vm.$watch('a', function (newValue, oldValue) {// 这个回调将在 `vm.a` 改变后调用})

以后你可以在 API 参考中查阅到完整的实例属性和方法的列表。

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

new Vue({data: {a: 1},created: function () {// `this` 指向 vm 实例console.log('a is: ' + this.a)} 

})// => "a is: 1"
也有一些其它的钩子,在实例生命周期的不同阶段被调用,如 mounted、updated 和 destroyed。生命周期钩子的 this 上下文指向调用它的 Vue 实例。 不要在选项属性回调上使用箭头函数,比如 created: () => console.log(this.a) 或 vm.$watch('a', newValue => this.myMethod())

因为箭头函数并没有 this,this 会作为变量一直向上级词法作用域查找,直至找到为止,经常导致 Uncaught TypeError: Cannot read property of undefined 或 Uncaught TypeError: this.myMethod is not a function

之类的错误。

4、生命周期图示

下图展示了实例的生命周期。你不需要立马弄明白所有的东西,不过随着你的不断学习和使用,它的参考价值会越来越高。

八、模板语法 Vue.js 使用了基于 HTML 的模板语法,允许开发者声明式地将 DOM 绑定至底层 Vue 实例的数据。所有 Vue.js 的模板都是合法的 HTML ,所以能被遵循规范的浏览器和 HTML 解析器解析。 在底层的实现上,Vue 将模板编译成虚拟 DOM 渲染函数。结合响应系统,Vue 能够智能地计算出最少需要重新渲染多少组件,并把 DOM 操作次数减到最少。 如果你熟悉虚拟 DOM 并且偏爱 JavaScript 的原始力量,你也可以不用模板,直接写渲染 (render) 函数,使用可选的 JSX 语法。

1、插值

<span v-once>这个将不会改变: {{ msg }}</span> <p>Using mustaches: {{ rawHtml }}</p><p>Using v-html directive: <span v-html="rawHtml"></span></p> Using mustaches: <span style="color: red">This should be red.</span> Using v-html directive: This should be red. 这个 span 的内容将会被替换成为属性值 rawHtml,直接作为 HTML——会忽略解析属性值中的数据绑定。注意,你不能使用 v-html 来复合局部模板,因为 Vue 不是基于字符串的模板引擎。反之,对于用户界面 (UI),组件更适合作为可重用和可组合的基本单位。 你的站点上动态渲染的任意 HTML 可能会非常危险,因为它很容易导致 XSS 攻击。请只对可信内容使用 HTML 插值,绝不要对用户提供的内容使用插值。 <button v-bind:disabled="isButtonDisabled">Button</button> 如果 isButtonDisabled 的值是 null、undefined 或 false,则 disabled 特性甚至不会被包含在渲染出来的 <button> 元素中。 {{ number + 1 }}{{ ok ? 'YES' : 'NO' }}{{ message.split('').reverse().join('') }} 这些表达式会在所属 Vue 实例的数据作用域下作为 JavaScript 被解析。有个限制就是,每个绑定都只能包含单个表达式,所以下面的例子都不会生效。
<!-- 这是语句,不是表达式 --> 
{{ var a = 1 }}<!-- 流控制也不会生效,请使用三元表达式 -->{{ if (ok) { return message } }}
模板表达式都被放在沙盒中,只能访问全局变量的一个白名单,如 Math 和 Date 。你不应该在模板表达式中试图访问用户定义的全局变量。

2、指令

<p v-if="seen">现在你看到我了</p> 这里,v-if 指令将根据表达式 seen 的值的真假来插入/移除 <p> 元素。 <a v-on:click="doSomething">...</a>

在这里参数是监听的事件名。我们也会更详细地讨论事件处理。

(2)动态参数

<a v-on:[eventName]="doSomething"> ... </a> 同样地,当 eventName 的值为 "focus" 时,v-on:[eventName] 将等价于 v-on:focus。

对动态参数的值的约束

<!-- 在 DOM 中使用模板时这段代码会被转换为 `v-bind:[someattr]` --><a v-bind:[someAttr]="value"> ... </a> <form v-on:submit.prevent="onSubmit">...</form> 在接下来对 v-on 和 v-for 等功能的探索中,你会看到修饰符的其它例子。 <!-- 完整语法 --><a v-on:click="doSomething">...</a><!-- 缩写 --><a @click="doSomething">...</a>

… 它们看起来可能与普通的 HTML 略有不同,但 : 与 @ 对于特性名来说都是合法字符,在所有支持 Vue 的浏览器都能被正确地解析。而且,它们不会出现在最终渲染的标记中。缩写语法是完全可选的,但随着你更深入地了解它们的作用,你会庆幸拥有它们。

九、计算属性和侦听器

var vm = new Vue({el: '#example',data: {message: 'Hello'},computed: {// 计算属性的 getterreversedMessage: function () {// `this` 指向 vm 实例return this.message.split('').reverse().join('')}}}) console.log(vm.reversedMessage) // => 'olleH'vm.message = 'Goodbye'console.log(vm.reversedMessage) // => 'eybdooG' 你可以打开浏览器的控制台,自行修改例子中的 vm。vm.reversedMessage 的值始终取决于 vm.message 的值。 你可以像绑定普通属性一样在模板中绑定计算属性。Vue 知道 vm.reversedMessage 依赖于 vm.message,因此当 vm.message 发生改变时,所有依赖 vm.reversedMessage 的绑定也会更新。而且最妙的是我们已经以声明的方式创建了这种依赖关系:计算属性的 getter 函数是没有副作用 (side effect) 的,这使它更易于测试和理解。 computed: {now: function () {return Date.now()}}

computed除非刷新页面不然不会更新

methods每次都会自动更新 相比之下,每当触发重新渲染时,调用方法将总会再次执行函数。 我们为什么需要缓存?假设我们有一个性能开销比较大的计算属性 A,它需要遍历一个巨大的数组并做大量的计算。然后我们可能有其他的计算属性依赖于 A 。如果没有缓存,我们将不可避免的多次执行 A 的 getter!如果你不希望有缓存,请用方法来替代。

(2)计算属性setter 计算属性默认只有 getter ,不过在需要时你也可以提供一个 setter :

// ...computed: {fullName: {// getterget: function () {return this.firstName + ' ' + this.lastName},// setterset: function (newValue) {var names = newValue.split(' ')this.firstName = names[0]this.lastName = names[names.length - 1]}} 

}// ...
现在再运行 vm.fullName = 'John Doe' 时,setter 会被调用,vm.firstName 和 vm.lastName也会相应地被更新。

var app8 = new Vue({el: '#app-8',data() {return {firstName: 'Foo',lastName: 'Bar'}// message: 'hello'// firstName: 'Foo',// lastName: 'Bar',// fullName: 'Foo Bar'},// methods: {// now: function() {// return Date.now();// }// }computed: {fullName: {// getterget: function() {return this.firstName + ' ' + this.lastName;},// setterset: function(newValue) {var names = newValue.split(' ');this.firstName = names[0];this.lastName = names[names.length - 1];}}}}) ***不可以在data里面重复定义fullName不然就改不过来,修正后就可。

<p>Ask a yes/no question:<input v-model="question"></p><p>{{ answer }}</p>
<!-- 因为 AJAX 库和通用工具的生态已经相当丰富,Vue 核心代码没有重复 --> 

<!-- 提供这些功能以保持精简。这也可以让你自由选择自己更熟悉的工具。 --><script src="https://cdn.jsdelivr.net/npm/axios@0.12.0/dist/axios.min.js"></script><script src="https://cdn.jsdelivr.net/npm/lodash@4.13.1/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: {// 如果 `question` 发生改变,这个函数就会运行question: function (newQuestion, oldQuestion) {this.answer = 'Waiting for you to stop typing...'this.debouncedGetAnswer()}},created: function () {// `_.debounce` 是一个通过 Lodash 限制操作频率的函数。// 在这个例子中,我们希望限制访问 yesno.wtf/api 的频率// AJAX 请求直到用户输入完毕才会发出。想要了解更多关于// `_.debounce` 函数 (及其近亲 `_.throttle`) 的知识,// 请参考:https://lodash.com/docs#debouncethis.debouncedGetAnswer = _.debounce(this.getAnswer, 500)},methods: {getAnswer: function () {if (this.question.indexOf('?') === -1) {this.answer = 'Questions usually contain a question **rk. ;-)'return}this.answer = 'Thinking...'var vm = thisaxios.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>

在这个示例中,使用 watch 选项允许我们执行异步操作 (访问一个 API),限制我们执行该操作的频率,并在我们得到最终结果前,设置中间状态。这些都是计算属性无法做到的。 除了 watch 选项之外,您还可以使用命令式的 vm.$watch API。 vm.$watch(expOrFn, callback, [options])

参数: {string | Function} expOrFn{Function | Object} callback{Object} [options] {boolean} deep{boolean} immediate

返回值:{Function} unwatch

用法: 观察 Vue 实例变化的一个表达式或计算属性函数。回调函数得到的参数为新值和旧值。表达式只接受监督的键路径。对于更复杂的表达式,用一个函数取代。 注意:在变异 (不是替换) 对象或数组时,旧值将与新值相同,因为它们的引用指向同一个对象/数组。Vue 不会保留变异之前值的副本。

// 键路径vm.$watch('a.b.c', function (newVal, oldVal) {// 做点什么})// 函数vm.$watch(function () {// 表达式 `this.a + this.b` 每次得出一个不同的结果时// 处理函数都会被调用。// 这就像监听一个未被定义的计算属性return this.a + this.b},function (newVal, oldVal) {// 做点什么})

*只要修改后a+b的值没变就不会触发这个函数。

var unwatch = vm.$watch('a', cb)// 之后取消观察unwatch()

选项:deep 为了发现对象内部值的变化,可以在选项参数中指定 deep: true 。注意监听数组的变动不需要这么做。

vm.$watch('someObject', callback, {deep: true 

})vm.someObject.nestedValue = 123// callback is fired

选项:immediate 在选项参数中指定 immediate: true 将立即以表达式的当前值触发回调:

vm.$watch('a', callback, {immediate: true 

var unwatch = vm.$watch('value',function () {doSomething()if (unwatch) {unwatch()}},{ immediate: true })

十、Class 与 Style 绑定 操作元素的 class 列表和内联样式是数据绑定的一个常见需求。因为它们都是属性,所以我们可以用 v-bind 处理它们:只需要通过表达式计算出字符串结果即可。不过,字符串拼接麻烦且易错。因此,在将 v-bind 用于 class 和 style 时,Vue.js 做了专门的增强。表达式结果的类型除了字符串之外,还可以是对象或数组。

data: {isActive: true,hasError: false}

结果渲染为:

data: {classObject: {active: true,'text-danger': false}} var classObject = new Vue({el: '.class',data: {classObject: {isActive: true,hasError: true,}}})

data: {isActive: true,error: null 
},computed: {classObject: function () {return {active: this.isActive && !this.error,'text-danger': this.error && this.error.type === 'fatal'}}}

**********因为是对象所以写在html里的就直接是class的名字不再取值,所以不用写activeClass,写active就行。

<p class="foo bar active">Hi</p>

2、绑定内联样式

data: {styleObject: {color: 'red',fontSize: '13px'}}

同样的,对象语法常常结合返回对象的计算属性使用。

data: {colorStyle: {color: "red"},fontStyle: {fontSize: "30px"}} JavaScript 对象只可以用【驼峰式】! (3)自动添加前缀 当 v-bind:style 使用需要添加浏览器引擎前缀的 CSS 属性时,如 transform,Vue.js 会自动侦测并添加相应的前缀。

(4)多重值

这样写只会渲染数组中较后一个被浏览器支持的值。在本例中,如果浏览器支持不带浏览器前缀的 flexbox,那么就只会渲染 display: flex。

[1] truthy 不是 true,truthy作布尔变换以后是true 在 JavaScript 中,truthy(真值)指的是在布尔值上下文中,转换后的值为真的值。所有值都是真值,除非它们被定义为 假值(即除 false、0、""、null、undefined 和 NaN 以外皆为真值)。 JavaScript 在布尔值上下文中使用强制类型转换(coercion)。 JavaScript 中的真值示例如下(将被转换为 true,if 后的代码段将被执行):

if (true) 

if ({})

if ([])

if (42)if ("foo")if (new Date())

if (-42)

if (3.14)

if (-3.14)

if (Infinity)if (-Infinity)

十一、条件渲染

1、v-if

0.5">Now you see meNow you don't v-else 元素必须紧跟在带 v-if 或者 v-else-if 的元素的后面,否则它将不会被识别。 (3)v-else-if ABCNot A/B/C 类似于 v-else,v-else-if 也必须紧跟在带 v-if 或者 v-else-if 的元素之后。 (4)用key管理可复用的元素 Vue 会尽可能高效地渲染元素,通常会复用已有元素而不是从头开始渲染。这么做除了使 Vue 变得非常快之外,还有其它一些好处。例如,如果你允许用户在不同的登录方式之间切换:
var example = new Vue({el: '.example',data: {loginType: "username"},methods: {change: function(event) {if (this.loginType === "username") {this.loginType = "e**il";} else {this.loginType = "username";}}} 
 <button v-on:click="change">change type</button><template v-if="loginType === 'username'"><label>Username</label><input placeholder="Enter your username"></template><template v-else><label>E**il</label><input placeholder="Enter your e**il address"></template>
那么在上面的代码中切换 loginType 将不会清除用户已经输入的内容因为两个模板使用了相同的元素,<input> 不会被替换掉——仅仅是替换了它的 placeholder。

自己动手试一试,在输入框中输入一些文本,然后按下切换按钮:

<template v-if="loginType === 'username'"><label>Username</label><input placeholder="Enter your username" key="username-input"></template><template v-else><label>E**il</label><input placeholder="Enter your e**il address" key="e**il-input"></template>

现在,每次切换时,输入框都将被重新渲染。请看:

注意,<label> 元素仍然会被高效地复用,因为它们没有添加 key 属性

2、v-show

<h1 v-show="ok">Hello!</h1> 不同的是带有 v-show 的元素始终会被渲染并保留在 DOM 中。v-show 只是简单地切换元素的 CSS 属性 display 注意,v-show 不支持 <template> 元素,也不支持 v-else。

3、v-if vs v-show

v-if 是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。 v-if 也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。 相比之下,v-show 就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。 一般来说,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if 较好。

4、v-if 与 v-for 一起使用

不推荐同时使用 v-if 和 v-for。请查阅风格指南以获取更多信息。 永远不要把 v-if 和 v-for 同时用在同一个元素上。

一般我们在两种常见的情况下会倾向于这样做:

为了过滤一个列表中的项目 (比如 v-for="user in users" v-if="user.isActive")。在这种情形下,请将 users 替换为一个计算属性 (比如 activeUsers),让其返回过滤后的列表。

<ul v-if="shouldShowUsers"><liv-for="user in users":key="user.id">{{ user.name }}</li></ul> 当 v-if 与 v-for 一起使用时,v-for 具有比 v-if 更高的优先级。请查阅列表渲染指南 以获取详细信息。

维护列表

<!-- 内容 --> 建议尽可能在使用 v-for 时提供 key attribute,除非遍历输出的 DOM 内容非常简单,或者是刻意依赖默认行为以获取性能上的提升。 因为它是 Vue 识别节点的一个通用机制,key 并不仅与 v-for 特别关联。后面我们将在指南中看到,它还具有其它用途。 不要使用对象或数组之类的非基本类型值作为 v-for 的 key。请用字符串或数值类型的值。

十二、列表渲染

1、用v-for把一个数组对应为一组元素

var example1 = new Vue({el: '#example-1',data: {items: [{ message: 'Foo' },{ message: 'Bar' }]}}) var example2 = new Vue({el: '#example-2',data: {parentMessage: 'Parent',items: [{ message: 'Foo' },{ message: 'Bar' }]}}) <div v-for="item of items"></div>

2、在v-for里使用对象

new Vue({el: '#v-for-object',data: {object: {title: 'How to do lists in Vue',author: 'Jane Doe',publishedAt: '2016-04-10'}}}) {{ index }}. {{ name }}: {{ value }} 在遍历对象时,会按 Object.keys() 的结果遍历,但是不能保证它的结果在不同的 JavaScript 引擎下都一致。

3、维护状态

<!-- 内容 --> 建议尽可能在使用 v-for 时提供 key attribute,除非遍历输出的 DOM 内容非常简单,或者是刻意依赖默认行为以获取性能上的提升。 因为它是 Vue 识别节点的一个通用机制,key 并不仅与 v-for 特别关联。后面我们将在指南中看到,它还具有其它用途。 不要使用对象或数组之类的非基本类型值作为 v-for 的 key。请用字符串或数值类型的值。 更多 key attribute 的细节用法请移步至 key 的 API 文档。 key

预期:number | string key 的特殊属性主要用在 Vue 的虚拟 DOM 算法,在新旧 nodes 对比时辨识 VNodes。如果不使用 key,Vue 会使用一种较大限度减少动态元素并且尽可能的尝试修复/再利用相同类型元素的算法。使用 key,它会基于 key 的变化重新排列元素顺序,并且会移除 key 不存在的元素。 有相同父元素的子元素必须有独特的 key。重复的 key 会造成渲染错误。它也可以用于强制替换元素/组件而不是重复使用它。

十三、数组更新检测

1、变异方法(mutation method)

Vue 将被侦听的数组的变异方法进行了包裹,所以它们也将会触发视图更新。这些被包裹过的方法包括:

push() 在数组的末尾添加一个或多个元素 返回数组新长度pop() 移除数组的较后一项,返回移除的项

shift() 移除数组的第一项,返回移除项

unshift() 在数组的第一项前面添加一个或多个元素,返回数组的长度splice() splice() 方法向/从数组中添加/删除项目,然后返回被删除的项目。sort() 排序reverse() 反序 你可以打开控制台,然后对前面例子的 items 数组尝试调用变异方法。比如 example1.items.push({ message: 'Baz' })。

2、替换数组

变异方法,顾名思义,会改变调用了这些方法的原始数组

example1.items = example1.items.filter(function (item) {return item.message.**tch(/Foo/)})

你可能认为这将导致 Vue 丢弃现有 DOM 并重新渲染整个列表。幸运的是,事实并非如此。Vue 为了使得 DOM 元素得到较大范围的重用而实现了一些智能的启发式方法,所以用一个含有相同元素的数组去替换原来的数组是非常高效的操作

3、注意事项

由于 JavaScript 的限制,Vue 不能检测以下数组的变动: 当你利用索引直接设置一个数组项时,例如:vm.items[indexOfItem] = newValue当你修改数组的长度时,例如:vm.items.length = newLength 举个例子:

var vm = new Vue({data: {items: ['a', 'b', 'c']} 

})vm.items[1] = 'x' // 不是响应性的vm.items.length = 2 // 不是响应性的

// Vue.setVue.set(vm.items, indexOfItem, newValue)

// Array.prototype.splicevm.items.splice(indexOfItem, 1, newValue)

vm.$set(vm.items, indexOfItem, newValue)

vm.items.splice(newLength)

直接把数组换掉可以

4、对象变更检测注意事项

还是由于 JavaScript 的限制,Vue 不能检测对象属性的添加或删除

var vm = new Vue({data: {a: 1} 

})// `vm.a` 现在是响应式的vm.b = 2// `vm.b` 不是响应式的

Vue.set(vm.userProfile, 'age', 27)

vm.$set(vm.userProfile, 'age', 27) vm.userProfile = Object.assign({}, vm.userProfile, {age: 27,favoriteColor: 'Vue Green'})

5、显示过滤/排序后的结果

<li v-for="n in evenNumbers">{{ n }}</li>
data: {numbers: [ 1, 2, 3, 4, 5 ] 
<li v-for="n in even(numbers)">{{ n }}</li>
data: {numbers: [ 1, 2, 3, 4, 5 ] 
 sortNumbers: function() {return this.numbers.sort(function(x, y) {return x - y;})}

6、在v-for里使用值范围

<span v-for="n in 10">{{ n }} </span> 结果:

7、在<template>上使用v-for

<ul><template v-for="item in items"><li>{{ item.msg }}</li><li class="divider" role="presentation">//</li></template></ul> 结果:

8、v-for与v-if同时使用

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

9、在组件上使用v-for

Vue.component('todo-item', {template: '\<li>\{{ title }}\<button v-on:click="$emit(\'remove\')">Remove</button>\</li>\',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 = ''}}})

转载:感谢您阅览,转载请注明文章出处“来源从小爱孤峰知识网:一个分享知识和生活随笔记录的知识小站”。

链接:从小白开始学vue学习笔记(一)——基础篇http://www.gufeng7.com/niaolang/1826.html

联系:如果侵犯了你的权益请来信告知我们删除。邮箱:119882116@qq.com

标签: