vue.js(二)
计算属性
概念
|在某些情况下,我们需要对某些数据进行一些转换/需要将多个数据结合起来 后再显示
|计算属性是写在实例的computed里
|methods和computed都可以实现我们需要的功能,但计算属性也有它存在的意义 => 计算属性会进行缓存,如果多次使用,只会调用一次
<!--这里有两个变量firstName lastName 需要显示完整名字必须拼接两个变量 如果多个地方显示完整名称要写多个{{firstName}}{{lastName}} => 计算属性-->
<div id="app">
<h2>{{getFullName()}}</h2>
<h2>{{fullName}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
firstName: 'Lebron',
lastName: 'James'
},
// computed: 计算属性()
computed: {
fullName: function () {
return this.firstName + ' ' + this.lastName
}
},
methods: {
getFullName() {
return this.firstName + ' ' + this.lastName
}
}
})
</script>
计算属性的复杂操作
下列例子用两种方式计算一个数组对象的总价
<div id="app">
<h2>总价格: {{totalPrice}}</h2>
<h2>总价格: {{getTotalPrice()}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
books: [
{id: 110, name: 'Unix编程艺术', price: 119},
{id: 111, name: '代码大全', price: 105},
{id: 112, name: '深入理解计算机原理', price: 98},
{id: 113, name: '现代操作系统', price: 87},
]
},
methods: {
getTotalPrice: function () {
let result = 0
for (let i=0; i < this.books.length; i++) {
result += this.books[i].price
}
return result
}
},
computed: {
totalPrice: function () {
let result = 0
for (let i=0; i < this.books.length; i++) {
result += this.books[i].price
}
return result
}
}
})
setter和getter
|每个计算属性都包含一个getter和setter,一般情况下,只用getter方法获取,setter不常用
<div id="app">
<h2>{{fullName}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
firstName: 'Kobe',
lastName: 'Bryant'
},
computed: {
// 计算属性一般是没有set方法, 只读属性.
fullName: {
set: function(newValue) {
const names = newValue.split(' ');
this.firstName = names[0];
this.lastName = names[1];
},
get: function () {
return this.firstName + ' ' + this.lastName
}
}
}
})
</script>
v-on 事件绑定
|参数问题:如果不需要额外参数,方法后的括号可以不加,但如果方法本身有一个参数,默认将原生事件event传入;如果需要传参,同时需要event,可以通过$event传入事件
|语法糖:v-on:click =>@click
|修饰符:
@click.stop
阻止事件冒泡
@click.self
当事件在该元素本身触发时才触发事件
@click.capture
添加事件侦听器是,使用事件捕获模式
@click.prevent
阻止默认事件
@click.once
事件只触发一次
<div id="app">
<!--1.事件调用的方法没有参数-->
<button @click="btn1Click">按钮2</button>
<!--2.在事件定义时, 写方法时省略了小括号, 但是方法本身是需要一个参数的, 这个时候, Vue会默认将浏览器生产的event事件对象作为参数传入到方法-->
<button @click="btn2Click">按钮2</button>
<!--3.方法定义时, 我们需要event对象, 同时又需要其他参数-->
<button @click="btn3Click(abc, $event)">按钮3</button>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好啊',
abc: 123
},
methods: {
btn1Click() {
console.log("btn1Click");
},
btn2Click(event) {
console.log('--------', event);
},
btn3Click(abc, event) {
console.log('++++++++', abc, event);
}
}
})
</script>
v-if条件指令
|v-if ,v-else-if,v-else与javascript中的if ,else if,else类似
| 可以根据表达式的值在DOM中渲染或销毁元素或组件
<!--用户登录时可以切换使用账号还是邮箱登录-->
<div id="app">
<span v-if="isUser">
<label for="username">用户账号</label>
<input type="text" id="username" placeholder="用户账号" key="username">
</span>
<span v-else>
<label for="email">用户邮箱</label>
<input type="text" id="email" placeholder="用户邮箱" key="email">
</span>
<button @click="isUser = !isUser">切换类型</button>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
isUser: true
}
})
</script>
<!--在这个案例中有个小问题,在有输入内容的情况下切换了类型,会发现文字依然显示之前输入的内容(应该换到另一个没有内容的input框) 这是因为vue在进行渲染时出于性能的考虑,尽可能复用已经存在的元素=> 给input添加不同且唯一的key-->
v-show和v-if的联系
|相同点:v-if与v-show都可以动态控制元素显示隐藏
|不同点:v-if显示隐藏是将元素整个添加或删除,而v-show隐藏则是为该元素添加css--display:none
,元素还在
|当需要频繁切换 =>v-show,反之 => v-if
v-for
遍历数组
| 有一组数据需要渲染 => v-for实现 类似于js中的for循环
|格式:v-for:item in name(数据的名字)
如果需要索引值:v-for:(item,index) in name(数据的名字)
index代表取出的item在原数组的索引值
<div id="app">
<ul>
<!--1.没有使用索引值(下标值)-->
<li v-for="item in names">{{item}}</li>
<!--2.获取索引值-->
<li v-for="(item, index) in names">{{index+1}}.{{item}}</li>
</ul>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
names: ['why', 'kobe', 'james', 'curry']
}
})
</script>
遍历对象
<div id="app">
<ul>
<!--1.在遍历对象的过程中, 如果只是获取一个值, 那么获取到的是value-->
<li v-for="item in info">{{item}}</li>
<!--2.获取key和value 格式: (value, key) -->
<li v-for="(value, key) in info">{{value}}-{{key}}</li>
<!--3.获取key和value和index 格式: (value, key, index) -->
<li v-for="(value, key, index) in info">{{value}}-{{key}}-{{index}}</li>
</ul>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
info: {
name: 'why',
age: 18,
height: 1.88
}
}
})
</script>
<!--1.why 18 1.88
2.why-name 18-age 1.88-height
3.why-name-0 18-age-1 1.88-height-2
-->
key属性
|在使用v-for时,最好给对应的元素/组件加上key属性,这个和虚拟DOM的Diff
算法有关 => 其核心是基于两个简单的假设:
1. 两个相同的组件产生类似的DOM结构,不同的组件产生不同的DOM结构。
2.同一层级的一组节点,他们可以通过唯一的id进行区分。
|当页面的数据发生变化时,Diff
算法只会比较同一层级的节点:如果节点类型不同,直接干掉前面的节点,再创建并插入新的节点,不会再比较这个节点以后的子节点了。如果节点类型相同,则会重新设置该节点的属性,从而实现节点的更新
|当某一层有很多相同的节点时,也就是列表节点时, 比如一下这个情况:在B和C之间加一个F
Diff
算法默认执行起来是这样的 : 把C更新成F,D更新成C,E更新成D,最后再插入E (很没有效率)
所以我们使用key来给每个节点做一个唯一标识,Diff算法
就可以正确的识别此节点,找到正确的位置区插入新的节点
检测数组更新方法
基本与javascript
中的方法相似
const app = new Vue({
el: '#app',
data: {
letters: ['a', 'b', 'c', 'd']
},
methods: {
btnClick() {
// 1.push方法
this.letters.push('aaaa', 'bbbb', 'cccc')
// 2.pop(): 删除数组中的最后一个元素
this.letters.pop();
// 3.shift(): 删除数组中的第一个元素
this.letters.shift();
// 4.unshift(): 在数组最前面添加元素
this.letters.unshift('aaa', 'bbb', 'ccc')
// 5.splice作用: 删除元素/插入元素/替换元素
// 删除元素: 第二个参数传入你要删除几个元素(如果没有传,就删除后面所有的元素)
// 替换元素: 第二个参数, 表示我们要替换几个元素, 后面是用于替换前面的元素
// 插入元素: 第二个参数, 传入0, 并且后面跟上要插入的元素
// splice(start)
this.letters.splice(1, 3, 'm', 'n', 'l', 'x')
this.letters.splice(1, 0, 'x', 'y', 'z')
// 5.sort():排序
this.letters.sort()
// 6.reverse():反转
this.letters.reverse()
// 注意: 通过索引值修改数组中的元素
this.letters[0] = 'bbbbbb';
// set(要修改的对象, 索引值, 修改后的值)
Vue.set(this.letters, 0, 'bbbbbb')
}
}
})