一、属性绑定(掌握)
1、v-bind介绍
前面我们都是通过指令来将值插入到我们的标签内容中,但除了内容外,我们还需要动态绑定某些属性,比如:a标签中的href属性,img标签中的src属性;这个时候我们就可以使用v-bind指令,它的作用就是可以动态绑定属性。
例子:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<img :src="src"/>
<a :href="href">Vue官网</a>
</div>
</body>
<script>
new Vue({
el: '#app',
data: {
src: 'https://vuejs.org/images/logo.png',
href: 'https://vuejs.org/'
}
})
</script>
</html>
注意点
v-bind
和 v-on
一样也有简写的方式,v-bind:src=""
可以简写成 :src=""
2、v-bind绑定class
很多时候,我们希望能动态切换class,选中字体颜色变红,初始状态字体为黑色;绑定class有两种方式:对象语法,数组语法。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title></title>
<style>
.current{
color: blue;
}
.italicFont{
font-style: italic;
}
.line{
text-decoration: underline;
}
</style>
</head>
<body>
<div id="app">
<ul>
<li>普通一行文字</li>
<li class="current">添加了current类名的文字</li>
<li v-bind:class="{'current': isCurrent}">对象格式,由isCurrent判断是否添加current类名</li>
<li class="line" :class="{'current': isCurrent, 'italicFont': isItalic}">多个类名</li>
<li :class="isCurrent ? 'current line' : 'line'">三元运算符决定类名</li>
<li :class="['current', 'line']">数组形式的多类名</li>
<li :class="getClass()">通过方法来返回类名</li>
</ul>
</div>
</body>
</html>
<script src="./lib/vue.js"></script>
<script>
new Vue({
el: "#app",
data: {
isCurrent: true,
isItalic: true
},
methods: {
getClass(){
return {
'current': this.isCurrent
}
}
}
})
</script>
3、v-bind绑定style
我们可以利用v-bind:style来绑定一个内嵌样式。
注意:
我们可以使用驼峰式语法:比如font-size ---> fontSize
绑定class有两种方式:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title></title>
</head>
<body>
<div id="app">
<ul>
<li style="background: skyblue;">通过style标签属性写的样式</li>
<li :style="{background: 'pink',fontStyle: 'italic'}">通过v-bind来绑定样式</li>
<li :style="{background: bgColor,color: fontColor}">数据来自data</li>
<li :style="[colorStyle, bgStyle]">数组形式</li>
<li :style="getStyle()">方法形式</li>
</ul>
</div>
</body>
</html>
<script src="./lib/vue.js"></script>
<script>
new Vue({
el: "#app",
data: {
bgColor: 'orange',
fontColor: '#cfc',
colorStyle: {color: 'pink'},
bgStyle: {background: 'skyblue'}
},
methods: {
getStyle(){
return [this.colorStyle, this.bgStyle]
}
}
})
</script>
二、循环遍历v-for、key(掌握)
v-for格式:item in items形式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<div>
<input type="text" v-model="inputVal"/>
<button @click="add">添加</button>
</div>
<ul>
<li v-for="(item,index) in arr" :key="index">
<input type="checkbox"/>
{{item.name}}
</li>
</ul>
</div>
</body>
<script>
new Vue({
el: '#app',
data: {
arr: [
{id: 1, name: 'Vue'},
{id: 2, name: 'React'},
{id: 3, name: 'Angular'}
],
inputVal: ''
},
methods: {
add() {
this.arr.unshift({id: this.arr.length + 1, name: this.inputVal})
}
}
})
</script>
</html>
组件的key属性
官方推荐我们使用v-for时,给对应的元素或组件添加一个key属性。
为什么需要这个key属性呢(了解)?
这个其实和Vue的虚拟DOM的Diff算法有关系。
当某一层有很多相同节点时,也就是列表节点时,我们插入一个新的节点到列表中
在B和C之间加一个F,Diff算法默认执行起来时这样的;即把C更新成F,D更新成C,E更新成D,最后再插入一个新的E,这样的效率也太低了。
当我们使用key来为每一个节点做唯一标识
Diff算法会以key作为标识来识别此节点,找到正确的位置区插入新的节点,所以key的作用是为了高效的更新虚拟DOM
三、计算属性(掌握)
https://cn.vuejs.org/v2/guide/computed.html
我们知道,在模板中可以直接通过插值语法显示一些data中的数据。但是某些情况下,我们可能需要对数据进行转化后再显示,或者需要将多个数据结合起来进行显示
例子
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title></title>
</head>
<body>
<div id="app">
<ul>
<li v-for="item in arr" :key="item.id">
书名:{{item.name}} -- 价格:{{item.price}}
</li>
</ul>
<h4>总价:{{totalPrice}}</h4>
</div>
</body>
</html>
<script src="./vue.js"></script>
<script>
new Vue({
el: "#app",
data: {
arr: [
{id: "b01", name: "海底两万里", price: 23},
{id: "b02", name: "西游记", price: 24},
{id: "b03", name: "红楼梦", price: 32}
]
},
computed: {
totalPrice(){
let sum = 0;
this.arr.map(val=>{
sum+=val.price;
})
return "¥ " + sum.toFixed(2) + " 元";
}
}
})
</script>
为什么会有这样的一个属性呢,用methods都可以实现我们的功能,为什么多了这样一个计算属性的东西呢?
computed与methods的区别
1、computed是属性调用,methods是方法调用
2、computed有缓存功能,多次使用时,该属性只会触发一次调用,而methods是使用一次就触发一次
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title></title>
</head>
<body>
<div id="app">
<ul>
<li v-for="item in arr" :key="item.id">
书名:{{item.name}} -- 价格:{{item.price}}
</li>
</ul>
<h4>computed计算总结:{{totalPrice1}}</h4>
<h4>computed计算总结:{{totalPrice1}}</h4>
<h4>computed计算总结:{{totalPrice1}}</h4>
<hr>
<h4>methods计算总价:{{totalPrice()}}</h4>
<h4>methods计算总价:{{totalPrice()}}</h4>
<h4>methods计算总价:{{totalPrice()}}</h4>
</div>
</body>
</html>
<script src="./vue.js"></script>
<script>
new Vue({
el: "#app",
data: {
arr: [
{id: "b01", name: "海底两万里", price: 23},
{id: "b02", name: "西游记", price: 24},
{id: "b03", name: "红楼梦", price: 32}
]
},
computed: {
totalPrice1(){
let sum = 0;
this.arr.map(val=>{
sum+=val.price;
})
console.log('计算属性: '+sum)
return "¥ " + sum.toFixed(2) + " 元";
}
},
methods: {
totalPrice(){
let sum = 0;
this.arr.map(val=>{
sum+=val.price;
})
console.log('methods方法: '+sum)
return "¥ " + sum.toFixed(2) + " 元";
}
}
})
</script>
每个计算属性其实都包含一个getter和setter
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title></title>
</head>
<body>
<div id="app">
<h3>名:{{firstName}}</h3>
<h3>姓:{{lastName}}</h3>
<h3>姓名:{{fullName}}</h3>
</div>
</body>
</html>
<script src="./lib/vue.js"></script>
<script>
var vm = new Vue({
el: "#app",
data: {
firstName: 'Michael',
lastName: 'Jackson'
},
computed: {
fullName: {
get(){
return this.firstName + ' ' + this.lastName;
},
set(val){
const fullName = val.split(' ');
this.firstName = fullName[0];
this.lastName = fullName[1];
}
}
},
})
</script>
四、v-model原理(掌握)
v-model
其实是个语法糖,它背后本质上包含了两个操作:
<input type="text" v-model="msg"/>
<!-- 等同于 -->
<input type="text" v-bind:value="msg" v-on:input="msg = $event.target.value"/>
下拉选择框
<body>
<div id="app">
<select v-model="mySelect">
<option value="orange">橙子</option>
<option value="apple">苹果</option>
<option value="banana">香蕉</option>
</select>
</div>
</body>
<script>
const vm = new Vue({
el: '#app',
data: {
mySelect: 'banana'
}
})
</script>
五、数组操作(掌握)
常用操作: push(返回数组长度)、unshift(返回数组长度)、shift(返回删除的值)、pop(返回删除的值)、slice(返回新的数组)、splice、concat(返回新数组)
新增迭代方法:forEach(没有返回值)、map、filter、reduce
六、自定义过滤器(掌握)
Vue.js 允许你自定义过滤器,可被用于一些常见的文本格式化。过滤器可以用在两个地方:双花括号插值和 v-bind 表达式 ( 后者从 2.1.0+ 开始支持 )。过滤器应该被添加在 JavaScript 表达式的尾部,由“管道”符号指示:
格式化价格:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title></title>
</head>
<body>
<div id="app">
<h2>价格为:{{price | priceFilter}}</h2>
</div>
</body>
</html>
<script src="./vue.js"></script>
<script>
new Vue({
el: "#app",
data: {
price: 25.3
},
// 局部过滤器
filters: {
priceFilter(val){
return "¥ "+val.toFixed(2)+" 元";
}
}
})
</script>
// 全局过滤器
Vue.filter("priceFilter", function(val){
return "¥ "+val.toFixed(2)+" 元";
})
七、图书购物车例子
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<style>
table {
border: 1px solid #e9e9e9;
border-collapse: collapse;
border-spacing: 0;
}
td,
th {
padding: 8px 16px;
border: 1px solid #e9e9e9;
text-align: left;
}
th {
background-color: #f7f7f7;
}
</style>
</head>
<body>
<div id="app">
<table>
<thead>
<tr>
<th v-for="(title,index) in titles" :key="index" v-text="title"></th>
</tr>
</thead>
<tbody>
<tr v-for="(item,index) in books" :key="item.id">
<td v-text="index"></td>
<td v-text="book.name"></td>
<td v-text="book.date"></td>
<td>{{book.price | priceRule}}</td>
<td>
<button @click="sub(index)">-</button>
<span>{{book.num}}</span>
<button @click="add(index)">+</button>
</td>
<td>
<button @click="remove(index)">移除</button>
</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="6">总价格:{{totalPrice | priceRule}}</td>
</tr>
</tfoot>
</table>
</div>
</body>
<script>
const vm = new Vue({
el: '#app',
data: {
titles: ['编号', '书籍名称', '出版日期', '价格', '购买数量', '操作'],
books: [
{
id: 1,
name: '算法导论',
date: '2006-9',
price: 85,
num: 1
},
{
id: 2,
name: 'UNIX编程艺术',
date: '2006-2',
price: 59,
num: 1
},
{
id: 3,
name: 'Vue程序设计',
date: '2008-10',
price: 35,
num: 1
},
{
id: 4,
name: '颈椎康复',
date: '2006-3',
price: 129,
num: 1
}
]
},
filters: {
priceRule(value) {
return '¥' + value.toFixed(2)
}
},
computed: {
totalPrice() {
return this.books.reduce((prev, current)=> {
prev +=current.num * current.price
return prev
}, 0)
}
},
methods: {
add(idx){
this.books[idx].num++
},
sub(idx){
this.books[idx].num--
if (this.books[idx].num == 0) {
this.books.splice(idx, 1)
}
},
remove(idx){
this.books.splice(idx, 1)
}
}
})
</script>
</html>
八、本地存储(掌握)
localStorage永久存储
// 添加数据;setItem的value值是字符串类型的数据
localStorage.setItem('name','张三');
// 获取数据
localStorage.getItem('name'); // 张三
// 清空
localStorage.clear();
注意事项:
5M = 1024 * 5kb
sessionStorage临时会话存储
// 添加数据;setItem的value值是字符串类型的数据
sessionStorage.setItem('name','张三');
// 获取数据
sessionStorage.getItem('name'); // 张三
// 清空
sessionStorage.clear();
注意事项:
cookie
网站中,http请求时无状态的。也就是第一次登陆成功(发送请求),第二次请求服务器依然不知道是哪一个用户。这时候的cookie就是解决这个问题的,第一次登陆后服务器返回数据(cookie)给浏览器,然后浏览器保存在本地,当该用户发送第二次请求,浏览器自动会把上次请求存储的cookie数据自动带上给服务器,服务器根据客户端的cookie来判断当前是哪一个用户。cookie存储有大小限制,不同浏览器不一样,一般是4kb,所以cookie只能存储小量数据。
4kb = 4 * 1024 byte (字节) = 4 * 1024 * 8 bit(位)
服务器会把第一次登陆后服务器返回的cookie存储到浏览器中
发一个请求给后端(自动带上第一次登陆后的cookie),拿回我自己购物车的列表
服务端接收到这个请求后,根据浏览器带上的cookie做出判断,判断当前是哪一个用户
session和cookie的作用有点类似,也是存储用户相关信息。不同的是cookie存储在浏览器,而session存储在服务器。
九、作业
独自完成图书馆购物车案例。