VueJs(3)---V-指令(1)
一、语法
v- 指令是带有v-的特殊属性
- v-if 条件渲染
- v-show
- v-else (必须在v-if/v-else-if/v-show指令后)
- v-else-if (v-if/v-else-if后)
- v-for (遍历)
- v-html (绑定HTML属性中的值) (本篇先讲这6个)
- v-bind (响应更新HTML特性,绑定自定义属性,如绑定某个class元素或style)
- v-on (监听指定元素的dom事件)
- v-model (内置的双向数据绑定,用在表单控件,绑定的value通常是静态字符串)
- v-cloak 关于vuejs页面闪烁{{message}}
- v-once 只渲染元素和组件一次,随后的重新渲染,元素/组件及其所有的子节点将被视为静态内容并跳过
v-text和v-html
v-test
<span v-text="msg"></span> <!-- 和下面的一样 --> <span>{{msg}}</span>
v-html :如果你的数据是“<h1>标题文字<h1>"那么它会解析成下面的,v-test永远是按文本输出。
v-show、v-if、v-else、v-else-if
v-show
根据表达式之真假值,切换元素的 display
CSS 属性。
<h1 v-show="ok">Hello!</h1>
不同的是带有 v-show
的元素始终会被渲染并保留在 DOM 中。v-show
只是简单地切换元素的 CSS 属性 display
注意,v-show
不支持 <template>
元素,也不支持 v-else
v-if
根据表达式的值的真假条件渲染元素。在切换时元素及它的数据绑定 / 组件被销毁并重建。如果元素是 <template>
,将提出它的内容作为条件块。
<h1 v-if="ok">Yes</h1> <!--也可以和v-else一起用--> <h1 v-if="ok">Yes</h1> <h1 v-else>No</h1>
在 <template>
元素上使用 v-if
条件渲染分组
因为 v-if
是一个指令,所以必须将它添加到一个元素上。但是如果想切换多个元素呢?此时可以把一个 <template>
元素当做不可见的包裹元素,并在上面使用 v-if
。最终的渲染结果将不包含 <template>
元素。
<template v-if="ok"> <h1>Title</h1> <p>Paragraph 1</p> <p>Paragraph 2</p> </template>
v-else
你可以使用 v-else
指令来表示 v-if
的“else 块
<div v-if="Math.random() > 0.5"> Now you see me </div> <div v-else> Now you don't </div>
注意:v-else
元素必须紧跟在带 v-if
或者 v-else-if
的元素的后面,否则它将不会被识别。
v-else-if
v-else-if
,顾名思义,充当 v-if
的“else-if 块”,可以连续使用
<div v-if="type === 'A'"> A </div> <div v-else-if="type === 'B'"> B </div> <div v-else> Not A/B/C </div>
v-if
vs v-show
v-if
是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。
v-if
也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。
相比之下,v-show
就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。
一般来说,v-if
有更高的切换开销,而 v-show
有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show
较好;如果在运行时条件很少改变,则使用 v-if
较好。
v-for
v-for需要用特定语法:alias in expression 为当前遍历的元素提供别名
<!--常见的四种用法--> <div v-for="item in items"> {{ item.text }}</div> <div v-for="(item, index) in items"></div> <div v-for="(val, key) in object"></div> <div v-for="(val, key, index) in object"></div>
v-for
默认行为试着不改变整体,而是替换元素。迫使其重新排序的元素,你需要提供一个 key
的特殊属性
<div v-for="item in items" :key="item.id"> {{ item.text }} </div>
案例官网:v-for列表渲染
key
当 Vue.js 用 v-for
正在更新已渲染过的元素列表时,它默认用“就地复用”策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序, 而是简单复用此处每个元素,并且确保它在特定索引下显示已被渲染过的每个元素。这个类似 Vue 1.x 的 track-by="$index"
为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 key
属性。理想的 key
值是每项都有的且唯一的 id。这个特殊的属性相当于 Vue 1.x 的 track-by
,但它的工作方式类似于一个属性,所以你需要用 v-bind
来绑定动态值 (在这里使用简写)
<div v-for="item in items" :key="item.id"> <!-- 内容 --> </div>
注意事项
由于 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 <!-- 不是响应性的-->
为了解决第一类问题,以下两种方式都可以实现和 vm.items[indexOfItem] = newValue
相同的效果,同时也将触发状态更新:
<!-- Vue.set--> Vue.set(vm.items, indexOfItem, newValue) <!-- Array.prototype.splice--> vm.items.splice(indexOfItem, 1, newValue)
你也可以使用 vm.$set
实例方法,该方法是全局方法 Vue.set
的一个别名
vm.$set(vm.items, indexOfItem, newValue)
为了解决第二类问题,你可以使用 splice
:
vm.items.splice(newLength)
对象更改检测注意事项
还是由于 JavaScript 的限制,Vue 不能检测对象属性的添加或删除
var vm = new Vue({ data: { a: 1 } }) <!-- `vm.a` 现在是响应式的--> vm.b = 2 <!--vm.b` 不是响应式的-->
对于已经创建的实例,Vue 不能动态添加根级别的响应式属性。但是,可以使用 Vue.set(object, key, value)
方法向嵌套对象添加响应式属性。例如,对于:
var vm = new Vue({ data: { userProfile: { name: 'Anika' }}}) <!--你可以添加一个新的 age 属性到嵌套的 userProfile 对象--> Vue.set(vm.userProfile, 'age', 27)
你还可以使用 vm.$set
实例方法,它只是全局 Vue.set
的别名
vm.$set(vm.userProfile, 'age', 27)
显示过滤/排序结果
v-for
with v-if
当它们处于同一节点,v-for
的优先级比 v-if
更高,这意味着 v-if
将分别重复运行于每个 v-for
循环中。当你想为仅有的_一些_项渲染节点时,这种优先级的机制会十分有用,如下
<li v-for="todo in todos" v-if="!todo.isComplete"> {{ todo }} </li> <!--上面的代码只传递了未完成的 todos。-->
而如果你的目的是有条件地跳过循环的执行,那么可以将 v-if
置于外层元素 (或 <template>
)上。如
<ul v-if="todos.length"> <li v-for="todo in todos"> {{ todo }} </li> </ul> <p v-else>No todos left!</p>
一个组件的 v-for
在自定义组件里,你可以像任何普通元素一样用 v-for
<my-component v-for="item in items" :key="item.id"></my-component>
2.2.0+ 的版本里,当在组件中使用 v-for
时,key
现在是必须的。
然而,任何数据都不会被自动传递到组件里,因为组件有自己独立的作用域。为了把迭代数据传递到组件里,我们要用 props
完整例子
<div id="todo-list-example"> <input v-model="newTodoText" v-on:keyup.enter="addNewTodo" placeholder="Add a todo" > <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>
组件
Vue.component('todo-item', { template: '\ <li>\ {{ title }}\ <!--z这里有两个地方不太明白1:"/"是什么意思。 2:这里的remove是什么意思,是调用上面的remove吗?求解。--> <button v-on:click="$emit(\'remove\')">X</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({ <!--push代表末尾添加--> id: this.nextTodoId++, title: this.newTodoText }) this.newTodoText = '' } } })
注意这里的 is="todo-item"
属性。这种做法在使用 DOM 模板时是十分必要的,因为在 <ul>
元素内只有 <li>
元素会被看作有效内容。
动态效果看官网:一个组件的v-for
想的太多,做的太少,中间的落差就是烦恼,要么去做,要么别想 中尉【13】