计算属性的本质演变过程:
计算属性一般是没有set方法的,没有set方法的话,就是一个只读属性。
这是一般的情况。
那么,可不可以给计算属性写set方法呢?
是可以的。
set方法的意思就是,设置计算属性的值,设置的意思就是要给set方法传一个新的属性值的。
然后我们把传入的新值,经过处理之后,保存到data的变量当中。
然后当我们进行set的时候,页面当中的数据就可以根据我们set的值,进行改变的。
代码是这个样子的:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<h2>{{fullName}}h2>
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '',
firstName: 'kobe',
lastName: 'bryant'
},
computed: {
fullName: {
set: function (newValue) {
console.log("------", newValue);
const names = newValue.split(' ');
this.firstName = names[0];
this.lastName = names[1];
},
get: function () {
return this.firstName + ' ' + this.lastName;
}
}
}
});
script>
body>
html>
效果就是下面的样子:
问题:为什么计算属性在mustache当中看起来像是函数调用,但是不用写小括号
答案:这是因为计算属性的本质是属性,包含set和get方法,一般没有set方法,只有get方法,这种情况下,可以简写成类似methods函数的写法,虽然看起来很像,但是本质上,计算属性还是属性的。
我们测试计算属性和methods的性能代码如下:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<h2>{{firstName + ' ' + lastName}}h2>
<h2>{{getFullName()}}h2>
<h2>{{getFullName()}}h2>
<h2>{{getFullName()}}h2>
<h2>{{getFullName()}}h2>
<h2>{{fullName}}h2>
<h2>{{fullName}}h2>
<h2>{{fullName}}h2>
<h2>{{fullName}}h2>
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '',
firstName: 'kobe',
lastName: 'bryant'
},
computed: {
fullName: function () {
console.log("fullName");
return this.firstName + ' ' + this.lastName
}
},
methods: {
getFullName: function () {
console.log("getFullName")
return this.firstName + ' ' + this.lastName
}
}
});
script>
body>
html>
测试效果如下:
问题:计算属性和methods的差别在哪里?
答案:vue内部对计算属性有缓存机制,调用多次的情况下,只有相关变量没有改变,计算属性是返回缓存的值,性能特别好。methods就不一样了,调用多次,执行多次,相比性能是比较差的。
还有一些比较难的es6的语法,比如箭头函数,promise,放在后面讲。
es6这种东西,应该放在基础阶段讲。
不要再写var了,尽量写let,尽量写const。变量的时候写let,标识符常量的时候,写const。
JavaScript的作者是Brendan Eich
,长这个样子:
很多编程语言最早设计的时候,都是有一些缺陷的,比如说是Java,之前是不支持lambda语法的,在java8之后支持了。
很早Brendan Eich就想要修复var,你可以将let看成是更加完美的var。、
这是因为let是有块级作用域的,var是没有块级作用域的。
理解什么是块级作用域,先要理解什么作用域。
作用域跟变量相关。
变量在什么范围内可用,这个范围就叫做作用域。
/*代码块*/
{
var name = 'why';
console.log(name); /*可以使用name变量*/
}
console.log(name); /*可以使用name变量*/
/*证明var没有块级作用域*/
/*很多语言,c语言,c++语言,都有块级作用域*/
//没有块级作用域会引起的问题。
//if代码块没有块级作用域
var func;
if (true) {
var name1 = '冀蕊';
//这个函数的作用就是打印冀蕊
func = function () {
console.log(name1);
};
}
console.log(name1); //我在外面可以使用if代码块内部的变量name1
name1 = '马慧丹' //我在外面可以修改if代码块里面的变量name1
func() //本来这个函数的作用就是打印冀蕊的,但是现在却是打印马慧丹了,乌龙了
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<button>按钮1button>
<br><br>
<button>按钮2button>
<br><br>
<button>按钮3button>
<br><br>
<button>按钮4button>
<br><br>
<button>按钮5button>
<br><br>
<script>
var btns = document.getElementsByTagName('button');
for (var i = 0; i < btns.length; i++) {
btns[i].addEventListener('click', function () {
console.log('第' + i + '个按钮被点击');
});
}
script>
body>
html>
上面的代码执行效果是:
这是为什么呢?
请看下面的图例解释:
第一次尝试解释:
怎么解决这个问题呢?
需要通过闭包。
<script>
var btns = document.getElementsByTagName('button');
for (var i = 0; i < btns.length; i++) {
(function (i) {
btns[i].addEventListener('click', function () {
console.log('第' + i + '个按钮被点击');
});
})(i)
}
</script>
为什么闭包可以解决这个问题呢?
因为函数是有块级作用域的。
效果立马正常了。
问题:什么是闭包,怎么写?
答案:(function(参数2){代码})(参数1)
,这个就叫做闭包。闭包是利用了函数具有块级作用域的这个特点,用来解决if、for等没有块级作用域的问题。参数1,是从外部传进来的参数,参数1传递给了参数2,参数2就位于了function的块级作用域当中了,这样无论来自外部的参数1是如何变化,参数2都表示的是最初传进来的参数1的值,不会改变,能够保障【代码】正常执行。
问题:javascript的设计缺陷是什么?
答案:javascript最初设计if、for都没有块级作用域的概念,function是有作用域。很多时候,我们都必须借助于匿名的function来解决if、for的作用域的问题。但是在es6当中加入了let,let是有if和for的块级作用域的。
第一种方式:
因为这里有一个for循环,所以for循环的{}当中的代码会执行多次。
类似下面的情况:
每一次都会用到这个i。for循环的函数是异步回调的。
第二种方式:
第三种方式:
问题:let是有块级作用域吗?
答案:是的。
建议,在我们开发当中,优先使用const,只有需要改变某一个标识符的时候,才使用let。
这个是很正常的。
swift当中也有两个东西,let是用来定义常量的,var是用来定义变量的。
多使用const,这样代码才会更加规范。
注意点:一旦const修饰的标识符被赋值之后,不能够被修改。
注意点:在使用我们的const标识符的时候,必须赋值。
注意点三:常量的含义是指向的对象不能够修改,但是可以改变对象内部的属性。
const name = ‘why’。
变量名name对应的内存里面存放的是字符串对象的内存地址。
一旦变量名用const修饰了,这个内存地址就不能够修改了。
变量名在内存当中是不存储的。要想明白这个,请读这篇文章。
问题:const修饰的标识符指向一个对象的时候,可以修改对象的属性么?
答案:可以。
第一个,对象属性的增强写法
第二个,对象函数的增强写法
javascript有一个很大的问题,就是没有类型检查,这会造成很多的问题。
typescript当中是有类型检查的。
没有类型检查,会有什么问题呢?
假设是下面的代码:
我们定义了一个函数,是要求传入一个字符串,我们来做字符串的切割。
但是用户调用这个函数的时候,就是传入进去了123。
因为js是没有类型检查的,所以在编译的时候,并不会报错的。
只有在真的传入了123,运行到这一行代码的时候,才会真的有错误。
这就会造成很多问题。
我们的项目只有在上线了之后,才会暴露出来很多的问题。
像是上面的问题,应该在编译的时候,就暴露出来错误,然后修复掉的。
当然很多语言都没有类型检查的。
但是typescript是有类型检查的。会这样写:
function split_string(str: String) {
str.split
}
str.split_string(123)
当然除了typescript之外,还有另外一个东西,是可以做类型检车的,叫做flow。
typescript是微软公司的。flow是facebook公司的。现在typescript已经干翻了flow。
angular现在项目开发的时候就是用typescript的。
angular这个框架是属于谷歌的。是谷歌的团队在维护。
看一下react的框架:
facebook是在维护react框架的。
问题:es6属性增强写法和函数增强写法是什么?
答案:属性增强写法就是直接把外部变量或常量名放到对象体内,vue内部会处理好属性名和属性值的。函数的增强写法就是省略了: fucntion
。
问题:react,flow,typescript,angular分别是哪个公司的?
答案:react是facebook的,flow是facebook的,typescript是微软的,angular是谷歌的。
在前端开发,要经常处理和用户交互的东西。点击某个按钮,拖动了某个东西,键盘事件等等。
在vue当中监听事件,需要按照v-on的方式来操作。
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<h2>计数器:{{counter}}h2>
<button v-on:click="counter++">按钮1button>
<button v-on:click="counter--">按钮2button>
<hr>
<h2>计数器:{{counter}}h2>
<button v-on:click="increment">按钮1button>
<button v-on:click="decrement">按钮1button>
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
counter: 0
},
methods: {
increment() {
this.counter++;
},
decrement() {
this.counter--;
}
}
})
script>
body>
html>
v-on的语法糖:
问题:v-on的属性值当中,调用函数需要写小括号吗?
答案:不需要的。第一种情况,在mustache语法或者在v-bind属性值当中调用methods方法,是调用函数,是需要加上小括号的。第二种情况,计算属性在mustache语法当中,看起来很像是调用函数,但是是不需要加上小括号的。第三种情况,v-on的属性值当中调用methods当中的方法,是调用函数,是不需要加上小括号的。这是我自己的总结:v-bind,v-on,计算属性。
点击按钮的时候,我们有时候是需要传入参数的,也有时候也不需要传入参数,不需要传入参数的时候,小括号就不用写的。
这种情况,小括号就不用了。
在mustache当中调用函数,小括号不能省略。
看上面的小代码,如果我们在js当中写了一个函数,这个函数是要求传入一个参数name的,但是你调用的时候,没有传入一个参数name,这种情况会报错吗?
不会的,是打印出来一个undefined。也就是说,你默认不传入参数的时候,参数的默认值是undefined。
经过我的验证,也确实是这个样子的。
但是这种在事件监听的时候,调用函数是加了小括号,但是没有传参的情况,是跟前面说的,js函数传参的问题是一样的。
我想说的,并不是这个情况,而是下面的情况。
我的验证结论是这样的:
我这里得到的结果,跟王红元不一样的地方在于,他得到的事件是:MouseEvent,我得到的事件是PointerEvent。
Pointer EventsAPI是HTML5的事件规范之一,它的主要目的是用来将鼠标(Mouse)
、触摸(touch)
和触控笔(pen)
三种事件整合为统一的API。
可以参考这篇文章进行深入了解。
一旦你在页面做一些操作的时候,浏览器会生成一个对象,这个对象就是Event。
当你用v-on绑定事件函数的时候,函数要求传入一个参数,但是你没有传入参数,也没有加入小括号。
那么这个时候,vue会默认拿到浏览器生成的对象,传入到函数内部。
第一种情况:v-on绑定函数的时候,我们不写小括号。
第二种情况:v-on绑定函数的时候,我们写小括号,我们传入一个普通的参数,也传入一个event参数,本意是想获取浏览器event对象,参数写成event。
第三种情况:v-on绑定函数的时候,我们写小括号,我们传入一个普通的参数,也传入了一个$event参数,这样就可以正确获取到浏览器对象了。
问题:如果函数有参数,调用的时候,没有传参数,那么会怎么样?
答案:js不会报错,函数的形参参数默认值会是undefined。
问题:如果调用事件函数,想要拿到浏览器event对象,传到函数当中,那么参数应该怎么写?
答案:$event。
在某些特殊情况下,会用到v-on的修饰符。
事件冒泡是我们不希望看到的。
我们以前是通过拿event阻止冒泡的。
在vue当中阻止事件冒泡很简单。
通过.stop修饰符
就可以实现。
在vue当中组织默认事件,通过.prevent修饰符
实现。
修饰符:.{keyCode | keyAlias}
。
业务场景中,只需要监听到用户输入enter
,才触发事件。
或者是用户输入 某个固定的键,才触发事件。
我们可以使用键修饰符,如果是keyCode,需要查查一些键盘对应的编码表,也可以是keyAlias。
如图:
这个,现在讲不了,这是跟自定义组件相关的。
如图:
我们有个自定义组件,叫做cpn。
通过v-on绑定了监听点击事件,但是第一种写法,是监听不到自定义组件的点击事件的。
第二种写法,加上了.native
修饰符后,就可以监听到自定义组件的点击事件了。
业务场景,某个按钮,只想让人家点击一次。这个场景少见,不常用。
问题:在vue当中如何阻止事件冒泡
答案:通过v-on的.stop修饰符。
问题:在vue当中如何阻止默认事件触发?
答案:通过v-on的.prevent修饰符。
问题:在vue当中如何监听某个键的点击
答案:通过v-on的.{keyCode}修饰符。
问题:在vue当中如何监听自定义组件的点击事件?
答案:通过v-on的.native修饰符。
问题:在vue当中如何只让一个按钮允许点击一次?
答案:通过v-on的.once修饰符。
2018年12月20日,周四,上午的课程已经结束了。
用的,不是特别多。
用的不是特别多,假如说,有这么复杂的逻辑的话,最好是用计算属性的。
问题:如果页面上,有些条件满足,显示一些信息,不满足,不显示信息,使用什么指令?
答案:使用v-if、v-else、v-else-if。
如图所示的代码:
label当中的for,对应到,input当中的id,这样label和input就绑定了。
有什么作用呢?
这个时候,你点击用户账号
这个文字,输入框当中就有聚焦了。
input当中增加了placeholder,就是下面的效果:
就是在输入框当中,有一个灰色的字。
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<span v-if="isUser">
<label for="username">用户账号label>
<input type="text" id="username" placeholder="用户账号">
span>
<span v-else>
<label for="email">用户邮箱label>
<input type="text" id="email" placeholder="用户邮箱">
span>
<br><br>
<button @click="btnClick">切换类型button>
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
isUser: false
},
methods: {
btnClick() {
return this.isUser = !this.isUser;
}
}
});
script>
body>
html>
点击切换类型之后,就会由用户账号
,变成了用户邮箱
了。
问题:label和input怎么绑定
答案:label当中的for属性的值,等于,input当中的id的属性的值。
问题:label和input绑定有什么效果。
答案:这样点击label上面的文字,input输入框就会自动聚焦的。
问题:placeholder有什么效果。
答案:会在input输入框当中默认显示出灰色的字。
登录切换有点小问题。
这个问题和vue的底层有点关系。
就是input复用的问题。
效果是这样的:
用户在邮箱登录方式情况下,用户已经输入了。
但是这个时候,点击切换类型,进入用户账号登录,用户账号里面,还保留[email protected]
,数据没有删除掉。
这是为什么呢?
假如我有一个div元素,需要渲染到浏览器当中,vue是不会直接把div渲染到浏览器上的。
vue会有一个虚拟DOM,会把我们想要显示的东西,放到内存当中。
虚拟DOM,叫做virtual dom,是真实dom的映射。
从虚拟dom到dom的时候,出于性能的考虑,是会尽可能地复用元素的。
复用元素的时候,元素属性的值会改变,元素标签的内容是会保留的。
我们了解了这个问题的原因后,我们怎么解决呢?
给input元素加一个key,用key作为标识,key相同,虚拟dom就可以复用,key不相同,虚拟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>
<br><br>
<button @click="btnClick">切换类型button>
div>
问题:虚拟dom的元素复用,怎么解决?
答案:给元素添加不同的key,就可以解决。
看看上面的操作,v-if指令控制的元素,如果没有显示,这个元素就不存在的。
v-show指令控制的元素,如果没有显示,这个元素还是存在的,只是在元素上面增加了一个行内样式:display:none
。
问题:v-if和v-show的区别
答案:v-if控制,条件为false,不显示元素,dom就会删除这个元素。v-show只是增加一个样式,不显示。
问题:开发当中怎么选择使用v-show和v-if呢?
答案:显示和隐藏,切换频率很高,使用v-show,切换频率不高,使用v-if。实际上,开发中,v-if使用的频率很高的。
示例代码:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<ul>
<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: ['周放','于越','梁缘','林籽','凯迪','童菲']
},
})
script>
body>
html>
请注意:这里
中,第一个是item,第二个是index。
第一种。
第二种。在遍历对象的过程中,如果只是获取一个值,那么获取到的值就是value。
第三种。获取对象的key和value。
第一个参数是value,第二个参数是key。
第四种。如何获取value,key,index呢?
问题:如何在v-for遍历数组的时候,获取下标值。
答案:在v-for的时候,写两个参数,一个item用来获取元素,第二个参数index用来获取下标值。
问题:v-for遍历对象的时候,怎么获取key,value,index呢?
答案:在v-for的时候,(value,key,index)
。
官方推荐我们在使用v-for的时候,给对应的元素或者组件添加上一个:key
属性。
目的是为了让我们能更好的复用。
push是在数组的最后加入一个元素,不满足需求。
我们的元素,经过虚拟dom,patch到我们的浏览器dom上。
我们的虚拟dom里面有5个li,对应到我们的浏览器上面li元素。
我们插入一个元素li6的时候,原则上,直接把li6在虚拟dom的li2和li3之间插入就可以了。
然后虚拟dom和dom会经过diff算法,比较不同。
如果检测到虚拟dom跟dom不一样,那么就把更新的虚拟dom渲染到dom上。
我们刚才的插入方式不是这样做的。
我们刚才的插入方式是:把li3修改为F,把li4修改为C,把li5修改为D,新增li6,设置为F。
这种方式,性能是很低的。
它在虚拟dom当中,这样做了之后,经过了diff算法,发现虚拟dom和dom很多地方都不一样,然后元素也都需要替换了,渲染的效果也是非常低的。
数组渲染之后,在数据中间插入一个元素。这个需求场景应该怎么比较高效率地做呢?
解决这个问题就是需要绑定key。
那么到底是绑定什么呢?
是绑定index呢?还是绑定item呢?
因为,index和我们元素标签内容当中的item不是一一对应的。所以,绑定index没有啥子用。
我们应该绑定item。
这里的意思就是:以后你在使用v-for的时候,尽量是给元素绑定一个key,这样可以提升性能。
问题:使用v-for的时候怎么提升性能?
答案:给元素绑定一个key。给item绑定item一般。
为什么数组改变的时候,页面是重新刷新的呢?
因为数据是响应式的。
添加一个元素之后,是自动响应的,数据改变之后,页面是自动刷新的。
页面没有发生刷新。并不是所有改变数据的方法,都会做到响应式的。
简单举例可变参数:
三个点就是表示可变参数的,当你传入多个参数的时候,实际上是放到了一个数组当中。
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<ul>
<li v-for="item in pretty">{{item}}li>
ul>
<button @click="btnClick">按钮button>
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
pretty: ['周放', '于越', '梁缘', '林籽', '凯迪', '童菲']
},
methods: {
btnClick() {
//1. push方法: 在数组最后面添加元素
// this.pretty.push('江疏影')
// this.pretty.push('江疏影', '万茜', '车晓');
//2. 通过索引修改值,注意,这个不是响应式的。
// this.pretty[0] = '江疏影';
//3. pop方法: 从最后一位删除元素
// this.pretty.pop();
//4. shift方法:删除数组中的第一个元素
// this.pretty.shift();
//5. unshift()方法:在数组最前面添加元素
// this.pretty.unshift('江疏影');
// this.pretty.unshift('江疏影', '万茜', '车晓');
//6. splice()方法:可以删除元素,可以插入元素,可以替换元素
//这个函数有几个参数
//第一个参数:start,从哪一个位置开始
//第二个参数:如果是删除元素,传入你要删除几个元素; 如果不传一直删除到末尾。
//第二个参数:如果是替换元素,传入你要替换几个元素; 然后后面加上替换的元素。
//
// this.pretty.splice(2, 3); 删除元素
// this.pretty.splice(2, 3, '霍思燕', '宋茜', '乔欣');
//this.pretty.splice(2, 0, '杨颖', '杨幂', '张萌') 插入元素
//7. sort(): 排序,这里是可以传入参数的,参数就是函数
// this.pretty.sort();
//8. reverse(): 反转
// this.pretty.reverse();
//9. vue.set()方法
Vue.set(this.pretty, 0, '陈数');
}
}
});
script>
body>
html>
问题:数组当中通过索引替换元素是不是响应式的。
答案:不是的。
问题:如果数组当中通过索引替换元素不是响应式的,那么应该怎么替换元素呢?
答案:使用splice方法。或者使用Vue.set方法。Vue.set(),第一个参数是要修改的对象,第二个参数是要修改的元素的索引值,第三个参数是修改后的值。
接下来是应该讲阶段案例了,大概是这个样子的:
讲解案例之前,先将作业的需求:
需求就是:点击谁,谁变成红色。
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
<style>
.active {
color: #ea4816;
}
style>
head>
<body>
<div id="app">
<ul>
<li v-for="(item,index) in pretty"
:class="{active: currentIndex === index}"
@click="liClick(index)">
{{index}}-{{item}}
li>
ul>
div>
<script src="../js/vue.js">script>
<script>
const app = new Vue({
el: '#app',
data: {
pretty: ['江疏影', '甘婷婷', '王丽坤', '张天爱', '潘之琳'],
currentIndex: 0,
},
methods: {
liClick(index) {
this.currentIndex = index;
}
}
});
script>
body>
html>
问题:如果想做个需求,列表展示一个数组,点击数组哪一项,哪一项就变红,怎么做?
答案:
变红的索引
,这样的第三方变量。变红的索引
。我这里没有使用王红元的样式,而是下载引入了bootstrap,我下载的版本是5.1.0最新的版本。
然后参考了这篇文章。
无
接下来做细节处理
你知道不知道如何在js当中给数字保留两位小数?
通过123.toFixed(2),这样就可以实现。
第一种解决方案:定义一个methods。
然后在html当中调用方法:
通过methods可以实现复用性。
第二种方案:使用过滤器,vue和angular当中都有过滤器。
过滤器的设置和使用的语法,参考下面的这张图:
通过过滤器,也可以实现,代码的复用性。
问题:vue当中的过滤器是怎么写?
答案:在vue的options对象当中写filters属性名,属性值是一个对象,里面写函数就可以了。在使用的时候,通过|
后面跟着过滤器,就可以了。
需要监听数量添加和改变的事件。
购买数量最多减到一本,如果数量减到1的时候,就可以用移除按钮,删除就可以了。
按钮有一个属性叫做disabled。
所以,当数量减少到1的时候,按钮就不可以点击了。
也就是说,当书籍的数量小于等于1的时候,按钮应该添加一个属性就是disabled
。
这样就可以给按钮动态绑定属性了。
我们之前学过动态绑定src、href、class、style。其实也是可以动态绑定disabled属性的。
问题:如何让一个按钮不能够点击呢?
答案:给一个按钮添加disabled属性。这个也可以使用v-bind来动态绑定disabled属性的。
使用计算属性。
给总价格,也添加上过滤器。
在写这个计算属性的时候,王红元写法是:
我记得他讲过的for的另外的写法,我忘记了。
我参考了这篇文章,知道了for in,for of,for each的这些用法。
我是这样写的:
我们的需求是:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>书籍购物车title>
<link rel="stylesheet" href="./css/bootstrap.css">
<link rel="stylesheet" href="./style.css">
head>
<body>
<div id="app" class="container">
<div v-if="books.length">
<table class="table table-striped table-hover table-bordered">
<thead>
<tr>
<th>th>
<th>书籍名称th>
<th>出版日期th>
<th>价格th>
<th>购买数量th>
<th>操作th>
tr>
thead>
<tbody>
<tr v-for="(item, index) in books">
<td>{{item.id}}td>
<td>{{item.name}}td>
<td>{{item.date}}td>
<td>{{item.price | showPrice}}td>
<td>
<button @click="decrement(index)" :disabled="item.count <= 1">-button>
{{item.count}}
<button @click="increment(index)">+button>
td>
<td>
<button @click="removeHandle(index)">移除button>
td>
tr>
tbody>
table>
<h2>总价格:{{totalPrice | showPrice}}h2>
div>
<h2 v-else>购物车为空h2>
div>
<script src="./js/vue.js">script>
<script src="./js/bootstrap.js">script>
<script src="main.js">script>
body>
html>
const app = new Vue({
el: '#app',
data: {
books: [
{
id: 1,
name: '《算法导论》',
date: '2006-9',
price: 85.00,
count: 1
},
{
id: 2,
name: '《UNIX编程艺术》',
date: '2006-2',
price: 59.00,
count: 1
},
{
id: 3,
name: '《编程珠玑》',
date: '2008-10',
price: 39.00,
count: 1
},
{
id: 4,
name: '《代码大全》',
date: '2006-3',
price: 128.00,
count: 1
},
],
},
methods: {
increment(index) {
this.books[index].count++;
},
decrement(index) {
this.books[index].count--;
},
removeHandle(index) {
this.books.splice(index, 1);
}
},
computed: {
totalPrice() {
let totalPrice = 0;
for (let book of this.books) {
totalPrice += book.price * book.count;
}
return totalPrice;
}
},
filters: {
showPrice(price) {
return '¥' + price.toFixed(2);
}
}
});
问题:es6当中for of和for in有什么区别呢?
答案:for let i of books,这个i是对象。for let i in books,这个i是索引。