vue初体验
vue.js基础
- new 运算符创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例。
var和let和const
var
- var声明全局变量,即生明在for循环中的变量,跳出for循环同样可以使用
- 变量提升:
原:
console.log(b);
var b = 200;
现:
var b;
console.log(b);
b=200;
let
- let拥有块级作用域,一个{}就是一个作用域,也就是let声明块级变量,即局部变量.即定义在for循环中的变量
for(let i = 0;i < 2; i++){
alert(i);
}
alert("循环体之外:" + i);不会输出
-
let在其作用域下面不存在变量提升(上述例子会报错)
-
let在其作用域中不能被重复声明(函数作用域和块级作用域)。
(function(){
let test1 = "let";
var test2 = "var"
let test1 = "let changed";//Uncaught SyntaxError: Identifier 'lTest' has already been declared
var test2 = "var changed";
console.log(test1);
console.log(test2);
})();
const
- const用来声明常量,一旦声明,其值就不可以更改,而且必须初始化。如果你非得修改常量的值,js不会报错,只是默默表示失败(不起作用)。
const b = 2;//正确
const b;//Uncaught SyntaxError: Missing initializer in const declaration错误,必须初始化
console.log(b);//有输出值
b = 5;
console.log(b);//Uncaught TypeError: Assignment to constant variable.无法输出
- const的作用域与let相同,只在声明所在的块级作用域内有效,并且也是和let一样不可以重复进行声明。const是常数变量,即一般在require一个模块的时候用或者定义一些全局常量,一旦定义,无法更改,无法重复赋值。
hello vue.js的初体验
- vue.js好处:数据与页面分离
响应式:当数据发生一些改变的时候,界面会自动发生一些响应 - vue.js里面有一个类似于function person(){} new person创建一个实例
编程范式:声明式编程
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>01-hellovuejs</title>
</head>
<body>
<div id="app">{{message}}</div> // 你好啊
<div >{{message}}</div> //{{message}}
<script src="../js/vue.js"></script>
//vue.js里面有一个类似于function person(){} new person创建一个实例
//当代码执行到这里的时候,还是原来的,继续向下执行,创建vue实例,对原HTML进行解析和修改
<script>
//let(变量)/const(常量)
//编程范式:声明式编程
const app = new Vue({
el:'#app',//用于挂载要管理的元素
data:{//定义数据
message:'你好啊'
}
})
</script>
</body>
</html>
元素js的的做法(编程范式:命令式编程)
//元素js的的做法(编程范式:命令式编程)
//1.创建div元素,设置id属性
//2.定义一个变量叫message
//3.将message变量放在前面的div元素中
//4.修改message的数据:今天天气不错!
//5.将修改后的数据再次替换到div元素
for in 和 for of
- 1.for…in循环:只能获得对象的键名,不能获得键值
- for…of循环:允许遍历获得键值
- 2.for…of不能遍历对象,会报错,for…in可以遍历对象的键名,可以使用 Object.keys(obj) 方法将对象的键名生成一个数组,然后遍历这个数组
遍历对象会报错
var obj = {
'name': 'Jim Green',
'age': 12
}
for(let key of obj) {
console.log('for of obj', key)
}
// Uncaught TypeError: obj is not iterable
for...in遍历键名
for(let key in obj) {
console.log('for in key', key)
}
/*
for in key name
for in key age
*/
可以使用 Object.keys(obj) 方法将对象的键名生成一个数组,然后遍历这个数组
for(let key of Object.keys(obj)) {
console.log('key', key)
}
/*
key name
key age
*/
- 3.for…in 循环不仅遍历数字键名,还会遍历手动添加的其它键,甚至包括原型链上的键。for…of 则不会这样
let arr = [1, 2, 3]
arr.set = 'world' // 手动添加的键
Array.prototype.name = 'hello' // 原型链上的键
for(let item in arr) {
console.log('item', item)
}
/*
item 0
item 1
item 2
item set
item name
*/
for(let value of arr) {
console.log('value', value)
}
/*
value 1
value 2
value 3
*/
- 4.forEach 循环无法中途跳出,break 命令或 return 命令都不能奏效
let arr = [1, 2, 3, 5, 9]
arr.forEach(item => {
if(item % 2 === 0) {
return
}
console.log('item', item)
})
/*
item 1
item 3
item 5
item 9
*/
for…of 循环可以与break、continue 和 return 配合使用,跳出循环
for(let item of arr) {
if(item % 2 === 0) {
break
}
console.log('item', item)
}
// item 1
- 5.无论是 for…in 还是 for…of 都不能遍历出 Symbol 类型的值,遍历 Symbol 类型的值需要用 Object.getOwnPropertySymbols() 方法
- 6.总之,for…in 循环主要是为了遍历对象而生,for…of 循环可以用来遍历数组、类数组对象,字符串
Vue列表的展示
<li v-for="item in movies">{{item}}</li>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
<ul>
<li v-for="item in movies">{{item}}</li>
</ul>
</div>
<script>
const app = new Vue({
el:"#app",
data:{
message:'你好啊',
movies:['星际穿越','大话西游','少年派','盗梦空间','海王']
}
})
</script>
</body>
</html>
- 响应式:只需要修改数据,不需要创建什么
案例:计数器
- 新的属性:methods,该属性用于在Vue对象中定义方法。
- 新的指令:@click,该指令用于监听某个元素的点击事件,并且需要指定当发生点击时,执行的方法(方法通常是methods中定义的方法)
- @click是v-on:click语法糖:即为简写
第一版
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
<h2>当前技术:{{counter}}</h2>
<button v-on:click="counter++">+</button>
<button v-on:click="counter--">-</button>
</div>
<script>
const app = new Vue({
el:"#app",
data:{
counter:0
}
}
})
</script>
</body>
</html>
第二版
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
<h2>当前技术:{{counter}}</h2>
<button v-on:click="add">+</button>
<button v-on:click="sub">-</button>
//写的太多了,写成函数
</div>
<script>
const app = new Vue({
el:"#app",
data:{
counter:0
},methods:{//对象
add:function () {
console.log('add被执行');
this.counter++;
//这里拿到的counter是全局的counter,拿不到data里面的counter,所以要加this
},
sub:function () {
console.log('sub被执行');
this.counter--;
}
}
})
//js
//1.拿button元素
//2.添加监听事件
</script>
</body>
</html>
Vue中的MVVM
什么是MVVM
-
MVVM是Model-View-ViewModel的缩写。MVVM主要是一种设计思想。
-
View层是视图层,也就是用户界面。前端主要由HTML和CSS来构建,通常就是DOM层
-
Model层 是指数据层,数据可能是我们固定的死数据,更多的是来自我们服务器,从网络上请求下来的数据,泛指后端进行的各种业务逻辑处理和数据操控,对于前端来说就是后端的提供的API接口;
-
ViewModel层是视图数据层,是沟通前两个的桥梁,一个同步View和Model的对象。
-
在MVVM架构下,View和Model之间并没有直接的联系,而是通过ViewModel进行交互,ViewModel通过双向数据绑定把View层和Model层连接了起来,View和Model之间的同步工作是自动的。
什么是vue中的MVVM
ViewModel
Data Bindings:数据绑定,把MOdel中的数据改变返回到view上
DOM listeners:DOM监听,界面上发生一些操作,一些事件时,再把这些操作返回到JavaScript 对象中,在需要的情况下改变对应的Data
计数器中的MVVM图示
Vue的options选项
options
- 我们在创建Vue实例的时候,传入了一个对象options.
- options包含哪些选项呢,目前掌握这些
el:
类型:string|HTMLElement
作用;决定之后vue实例会管理哪一个DOM
data:
如果是Vue实例是一个对象,组件是一个函数
类型:Object|Function
作用:Vue实例对应数据对象
methods://对象
类型:{[key:string]:Function}
作用:定义一些属于Vue的一些方法,可以在其他地方调用,也可以在指令中使用
Javascript定义类(class)的三种方法
一,构造函数法
- 用构造函数模拟"类",在其内部用this关键字指代实例对象。
function Cat() {
this.name = "大毛";
}
- 生成实例的时候,使用new关键字。
var cat1 = new Cat();
alert(cat1.name); // 大毛
- 类的属性和方法,还可以定义在构造函数的prototype对象之上。
Cat.prototype.makeSound = function(){
alert("喵喵喵");
}
二、Object.create()法
- 用这个方法,"类"就是一个对象,不是函数。
var Cat = {
name: "大毛",
makeSound: function(){ alert("喵喵喵");
}
};
- 直接用Object.create()生成实例,不需要用到new。
var cat1 = Object.create(Cat);
alert(cat1.name); // 大毛
cat1.makeSound(); // 喵喵喵
三、极简主义法
- 用一个对象模拟"类"。在这个类里面,定义一个构造函数createNew(),用来生成实例。然后,在createNew()里面,定义一个实例对象,把这个实例对象作为返回值。
var Cat = {
createNew: function(){
var cat = {};
cat.name = "大毛";
cat.makeSound = function(){ alert("喵喵喵"); };
return cat;
}
};
- 用的时候,调用createNew()方法,就可以得到实例对象。
var cat1 = Cat.createNew();
cat1.makeSound(); // 喵喵喵
开发中,什么时候称之为方法,什么时候称之为函数
1.方法(method)
- 在类里的一般称之为方法,因为方法都是和某个实例对象挂钩的
- 在下面代码块中,add和sub都被称为方法,因为里面的this和实例化对象app相挂钩。
const obj = {
counter = 0
}
const app = new Vue({
el:'#app',
data: obj,
methods:{
add: function(){
this.counter++
},
sub: function(){
this.counter--
}
}
})
2.函数
- 如果在script中直接定义,则被称为函数
<script>
function a(){
}
</script>
3.js中既有方法又有函数,java中只有方法的概念
Vue的生命周期
生命周期
- 事物从诞生到消亡的整个过程
- 当你写了一个简单的new vue时,内部做了一系列的事情,在做每一系列事情的过程当中,如果你有写一些函数的话,他会告诉你我执行到这一步了,这个过程就叫做我们使用生命周期函数去做一些我们想做的事情
在github上下载vue时,下载后面加了tag的,debug开发版本,release发布版本
Vue的生命周期函数有哪些
- hook :钩子 回调函数
- 一般组件会销毁
封装成一个插件
设置->live ->vue ->define->html
<div id="app">
{{message}}
</div>
<script src="../js/vue.js"></script>
<div >{{message}}</div>
<script>
const app = new Vue({
el:'#app',
data:{
message:'你好啊'
}
})
</script>
插值的操作{{message}}–将data里面的值放到Dom里面显示是有关系的
Mustache
- Mustache语法:双大括号语法
- Mustache:胡子
- Mustache语法中,不仅仅可以直接写变量,也可以写简单的表达式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>01-Mustache</title>
</head>
<body>
<div id="app">
<h2>{{message}}</h2>
<h2>{{message}},小可爱</h2>
<!-- Mustache语法中,不仅仅可以直接写变量,也可以写简单的表达式-->
<h2>{{firstname + lastname}}</h2>
<h2>{{firstname + ' ' +lastname}}</h2>
<h2>{{firstname}} {{lastname}}</h2>
<h2>{{counter * 2}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el:'#app',
data:{
message:'你好啊',
firstname:'kobe',
lastname: 'bryant',
counter:100
}
})
</script>
</body>
</html>
v-once
- 在某些情况下,我们可能不希望界面随意的跟随改变
- 这个时候,我们使用一个Vue的指令
-该指令后面不需要跟任何表达式,比如前面的v-for是需要跟表达式的
该指令表示元素和组件只渲染一次,不会随着数据的改变而改变
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>02-v-once</title>
</head>
<body>
<div id="app">
<h2> {{message}}</h2>
<h2 v-once>{{message}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el:'#app',
data:{
message:'你好啊'
}
})
</script>
</body>
</html>
v-html
- url穿的是一个标签带链接
url:'<a href="http://www.baidu.com">百度一下</a>'
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>03-v-html</title>
</head>
<body>
<div id="app">
<h2>{{url}}</h2>
<h2 v-html="url"></h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el:'#app',
data:{
message:'你好啊',
url:'<a href="http://www.baidu.com">百度一下</a>'
}
})
</script>
</body>
</html>
v-text
- v-text作用和Mustache比较相似,都是用于将数据显示在界面中
- v-text通常情况下,接受一个string类型
<h2 v-text="message">,llll</h2>
使用这个写法的话前面的内容会将后面的内容覆盖
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>04-v-text</title>
</head>
<body>
<div id="app">
<h2> {{message}},llll</h2>
<h2 v-text="message">,llll</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el:'#app',
data:{
message:'你好啊'
}
})
</script>
</body>
</html>
v-pre
- v-pre用于跳过这个元素和他子元素的编译过程,用于显示原始的mustache语法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>05-v-pre</title>
</head>
<body>
<div id="app">
<h2>{{message}}</h2>
<h2 v-pre>{{message}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el:'#app',
data:{
message:'你好啊'
}
})
</script>
</body>
</html>
v-cloak(斗篷)
- 在某些情况下,我们浏览器可能会直接显示出未编译的Mustance标签。
- 浏览器解析太慢,可能会显示出一个未编译的,然后再出现一个编译的,使用这个可以将未编译的不显示出来
-
//在vue解析之前,div中有一个属性叫v-cloak //在vue解析之后,div中没有一个属性叫v-cloak
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>06-cloak</title>
<style>
[v-cloak]{
display: none;
}
</style>
</head>
<body>
<div id="app" v-cloak>
{{message}}
</div>
<script src="../js/vue.js"></script>
<script>
//在vue解析之前,div中有一个属性叫v-cloak
//在vue解析之后,div中没有一个属性叫v-cloak
setTimeout(function () {
const app = new Vue({
el:'#app',
data:{
message:'你好啊'
}
})
},1000)
</script>
</body>
</html>
动态绑定属性
v-bind介绍
- 前面我们学习的指令类容主要作用是将值插入到我们模板的类容中
- 但是,除了类容需要动态来决定外,某些属性我们也希望动态来绑定
- 语法糖:
:
<img v-bind:src="imageURL" alt="">
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>01-v-bind</title>
</head>
<body>
<div id="app">
<!-- 错误的做法:这里不可以使用mustache语法-->
<img src="{{imageURL}}" alt="">
<!-- 正确的做法:使用v-bind指令-->
<img v-bind:src="imageURL" alt="">
<a v-bind:href="ahref">百度一下</a>
<!-- 语法糖的写法-->
<img :src="imageURL" alt="">
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el:'#app',
data:{
message:'你好啊',
imageURL:'https://img20.360buyimg.com/pop/s1180x940_jfs/t1/1' +
'74967/24/19467/90450/60f0ea26E55af4e31/3056b4680268fc25.jpg.webp',
ahref:'http://www.baidu.com'
}
})
</script>
</body>
</html>
v-bind动态绑定class对象语法
- 很多时候我们希望动态来切换class,数据为某个状态时,字体显示红色,另一个状态时,字体显示黑色
- 绑定class的两种方式
- 对象语法
含义:class后面跟的是一个对象
- 数组语法
class后面跟的是一个数组
对象语法
<h2 v-bind:class="{类名1:true,类名二:boolean}">{{massage}}</h2>
- 这样绑定的class属性是动态的,并且前面有一个class的话,后面的不会覆盖前面的
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>02-bind动态绑定class对象语法</title>
<style>
.active{
color: #5cb85c;
}
</style>
</head>
<body>
<div id="app">
<!-- <h2 class="active">{{message}}</h2>-->
<!-- <h2 :class="active">{{message}}</h2>-->
<!-- <h2 v-bind:class="{类名1:true,类名二:boolean}">{{massage}}</h2>-->
<h2 class="title" v-bind:class="{active:isActive,line:isline}">{{message}}</h2>
//后面的class不会覆盖掉前面的class
<button v-on:click="btnclick">点我换色</button>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el:'#app',
data:{
message:'你好啊',
isActive:true,
isline:true
},
methods:{
btnclick:function () {
this.isActive = !this.isActive
}
}
})
</script>
</body>
</html>
解释上面用法四
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>02-bind动态绑定class对象语法</title>
<style>
.active{
color: #5cb85c;
}
</style>
</head>
<body>
<div id="app">
<!-- <h2 class="active">{{message}}</h2>-->
<!-- <h2 :class="active">{{message}}</h2>-->
<!-- <h2 v-bind:class="{类名1:true,类名二:boolean}">{{massage}}</h2>-->
<!-- <h2 class="title" v-bind:class="{active:isActive,line:isline}">{{message}}</h2>-->
//后面的class不会覆盖掉前面的class
<h2 class="title" v-bind:class="getclasses()">{{message}}</h2>
<button v-on:click="btnclick">点我换色</button>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el:'#app',
data:{
message:'你好啊',
isActive:true,
isline:true
},
methods:{
btnclick:function () {
this.isActive = !this.isActive
},
getclasses:function () {
return {active:this.isActive,line:this.isline}
}
}
})
</script>
</body>
</html>
数组语法
- active加上单引号是一个字符串,就会显示active,不加是一个变量,显示aaa
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<h2 class="title" :class="['active','line']">{{meaasge}}</h2>
<h2 class="title active line ">{{message}}</h2>
//这两种写法是一个意思
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el:'#app',
data:{
message:'你好啊'
active:'aaaa',
line:'bbbb'
}
})
</script>
</body>
</html>
v-for和v-bind的结合
- 默认第一个为红色,当点击哪一个哪一个变成红色
- 遍历每一个li的内容和下标,动态添加属性,当下标值和临时变量相等时为true,显示,添加点击事件,当点击某一个li时,将他改为true,即将index值赋给临时变量
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.active{
color:red;
}
</style>
</head>
<body>
<div id="app">
<ul>
<li v-for="(m,index) in movies"
:class = "{active:currentindex === index}"
@click = "liclick(index)">
{{index}}.{{m}}
</li>
</ul>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el:'#app',
data:{
movies:['海王','海尔','我的姐姐','小红花'],
currentindex:0
},
methods:{
liclick(index){
this.currentindex = index
}
}
})
</script>
</body>
</html>
v-bind绑定style
对象语法
- style后面跟的是一个对象
- 点击列表中的哪一项,那么该项的文字变成红色
- 驼峰命名法: 50px如果不加单引号的话,就会将50px当成一个变量
<h2 :style="{key(属性名):value(属性值)}">{{message}}</h2>
fontsize值写死了,不如使用stylecss
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>05-v-bind绑定style</title>
</head>
<body>
<div id="app">
<!--<h2 :style="{key(属性名):value(属性值)}">{{message}}</h2>-->
<h2 :style="{fontSize:'50px'}">{{message}}</h2>
<!-- 驼峰命名法: 50px如果不加单引号的话,就会将50px当成一个变量去解析,在下面找不到,会报错-->
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el:'#app',
data:{
message:'你好啊',
}
})
</script>
</body>
</html>
- 值不写死
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>05-v-bind绑定style</title>
</head>
<body>
<div id="app">
<!--<h2 :style="{key(属性名):value(属性值)}">{{message}}</h2>-->
<h2 :style="{fontSize:'50px',color:finacolor}">{{message}}</h2>
<!-- 驼峰命名法: 50px如果不加单引号的话,就会将50px当成一个变量去解析,在下面找不到,会报错-->
<h2 :style="{fontSize:finasize}">{{message}}</h2>
<!--finasize当成一个变量使用-->
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el:'#app',
data:{
message:'你好啊',
finasize:'100px',
// 如果这里是100,在上面写成finasize+'px'
finacolor:'red',
}
})
</script>
</body>
</html>
数组语法
- style后面跟的是一个数组
<h2 :style="[basestyle,basestyle1]">{{message}}</h2>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<h2 :style="[basestyle,basestyle1]">{{message}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el:'#app',
data:{
message:'你好啊',
basestyle:{background:'red'},
basestyle1:{fontSize:'100px'},
}
})
</script>
</body>
</html>
计算属性
计算属性的基本使用
- 在计算中我们可以通过一些插值语法显示一些data中的数据,但是在某写情况下,我们可能需要对一些数据进行转换后在显示,或者需要将多个数据结合起来进行显示
- 下面是四种将两个字符串拼接起来的案例
<h2>{{firstName + ' ' + lastname}}</h2>
<h2>{{firstName}} {{lastname}}</h2>
<h2>{{getfullname()}}</h2>
<h2>{{fullName}}</h2>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div id="app">
<h2>{{firstName + ' ' + lastname}}</h2>
<h2>{{firstName}} {{lastname}}</h2>
<h2>{{getfullname()}}</h2>
<h2>{{fullName}}</h2>
<!-- 这里将fullname看成是一个属性,所以不用加大括号-->
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el:'#app',
data:{
message:'你好啊',
firstName: 'lebron',
lastname: 'james'
},
//computed:计算属性()
computed:{
fullName:function () {
//起名字的时候尽量不加动词,当成一个属性来
return this.firstName + ' ' + this.lastname
}
},
methods:{
getfullname:function () {
//这里写成一个methods,可以写成:function(),也可以直接写成getfullname(){}
return this.firstName + ' ' + this.lastname
}
}
})
</script>
</body>
</html
计算属性的复杂操作
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<h2>总价格:{{totalPrice}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el:'#app',
data:{
books:[
{id:110,name:'编程价格',price:123},
{id:110,name:'编程价格',price:123},
{id:110,name:'编程价格',price:123},
]
},
computed:{
//filter/map/reduce
totalPrice: function () {
// return this.books.reduce()
let result = 0
for(let i = 0;i<this.books.length;i++){
result += this.books[i].price
}
// for(let i in this.books)
// for(let book of this.books)
return result
}
}
})
</script>
</body>
</html>
计算属性的setter和getter
- computed本质上是一个对象套一个对象,fullname内部有两个函数,一般set函数是空的, 计算属性一般没有set方法(删除),所以他是一个只读属性,不设置值,所以写上面那种写法是下面这种写法的简写,所以调用的时候没有括号
- [
简写:
computed:{
fullname:function () {
return this.firstName + ' ' + this.lastname
}
}
实质:
computed:{
fullname:{
set:function () {
},
get:function () {
return this.firstName + ' ' + this.lastname
}
}
set方法完整格式
set:function (newvalue) {
console.log('....',newvalue);
const names = newvalue.split(' ') ;
this.firstName = names[0];
this.lastname = names[1];
},
所有代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<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:{
// fullname:function () {
// return this.firstName + ' ' + this.lastname
// }
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
//computed本质上是一个对象套一个对象,fullname内部有两个函数,一般set函数是空的,
// 计算属性一般没有set方法(删除),所以他是一个只读属性,不设置值,所以写上面那种写法是下面这种写法的简写
// 所以调用的时候没有括号
//app.fullname = 'abc'设置值,调用的是get方法
}
}
}
})
</script>
</body>
</html>
计算属性和methods的对比
- methods和computed看起来都可以实现我们的功能,为什么多计算属性这个东西呢
计算属性会进行缓存,如果多次使用,计算属性只会调用一次
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<h2>{{fullname}}</h2>
<h2>{{fullname}}</h2>
<!-- <h2>{{getfullname()}}</h2>-->
<!-- <h2>{{getfullname()}}</h2>-->
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el:'#app',
data:{
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>
如图,getfullname执行了两次
fullname执行了一次
ES6补充
let var
- ES5中的var是没有块级作用域的(if/for)
- ES6中的let是有块级作用域的(if/for),ES5之前之前因为if和for都没有块级作用域的概念,所以在很多时候,我们都需要借助function匿名函数的作用域来解决应用外面变量的问题
- ES6中,加入了let,let它是有if和for的块级作用域
- getElementsByTagName与getElementsByName,一个是标签,一个是属性未为name
- addEventListener() 方法用于向指定元素添加事件句柄。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>菜鸟教程(runoob.com)</title>
</head>
<body>
<p>该实例使用 addEventListener() 方法来向按钮添加点击事件。</p>
<button id="myBtn">点我</button>
<p id="demo"></p>
<script>
//script标签写在body里,写在head里面,script type="text/javascript",window.onload = function(){}
document.getElementById("myBtn").addEventListener("click", function()
{
document.getElementById("demo").innerHTML = "Hello World";
});
</script>
</body>
</html>
//添加点击事件内部写入Hello World
1.变量作用域 :变量在什么范围内是可用
{
var name = 'why';
console.log(name);
}
console.log(name);//可以打印
- JavaScript只有函数有作用域
2.没有块级作用域引起的问题:if的块级
var func;
if(true){
var name = 'why';
func = function () {
console.log(name);
}
}
name = 'jhgi';
func();
//此时name的值不是我们想要的why
var name = 'why';
function abc(bbb) {
console.log(bbb);
}
abc('iyhuh');
name = 'secds';
//在这里前面后面随便改,都和函数没有影响
3.没有块级作用域引起的问题:for的块级
错误:
const btns = document.getElementsByTagName('button');
for(var i =0;i<btns.length;i++) {
btns[i].addEventListener('click',function () {
console.log('第' + num + '按钮被点击');
})
}
//这里的话点击第一个会显示第2个被点击
解决:闭包,闭包是一个作用域,立即执行函数
var btns = document.getElementsByTagName('button');//byname :name属性
for(var i =0;i<btns.length;i++){
(function (num) {
btns[i].addEventListener('click',function () {
console.log('第' + num + '按钮被点击');
})
})(i)
}
//这里已经将i传进去了
用了let之后
const btns = document.getElementsByTagName('button');
for(let i =0;i<btns.length;i++) {
btns[i].addEventListener('click',function () {
console.log('第' + num + '按钮被点击');
})
//正确
const
- const修饰的标识符为常量,不可以再次赋值
- 当我们修饰的标识符不会被再次赋值时,就可以使用const来保证数据的安全性
- 在ES6开发中,优先使用const,只有需要改变某一个标识符的时候才用let
注意点
- 不可以修改
<body>
<script>
//注意一:一旦给const修饰的标识符被赋值后,不能修改
const name = 'haha';
namev = 'eslrbmv';
- 必须赋初值
//注意二:在使用const定义标识符,必须进行赋值
const name;
namev = 'eslrbmv';
//Uncaught SyntaxError: Missing initializer in const declaration报错
- 常量的含义是指向对象不能修改,即保存的内存地址不能修改,的但是可以改变对象内部的属性
//注意点三:常量的含义是指向对象不能修改,即保存的内存地址不能修改,的但是可以改变对象内部的属性
const obj = {
name:'why',
age:12,
height:1.88
}
obj.name = 'haha';
obj.age = 45;
obj.height = 1.89;
</script>
</body>
ES6对象字面量增强写法
一些变量或者常量,将变量的名称作为key,值作为value
-
typescript(Microsoft)–简称ts,有类型检测,TypeScript 是一种给 JavaScript 添加特性的语言扩展,TypeScript 是 JavaScript 的一个超集(包括),支持 ECMAScript 6 标准,而JavaScript没有
-
flow(Facebook)也有,Flow 是 Facebook 出品的一个用于 JavaScript 代码的静态类型检查工具。用于找出 JavaScript 代码中的类型错误。Flow 采用 OCaml 语言开发。
react(Facebook在维护)editorconfig规定书写格式:缩进两个,React 是一个用于构建用户界面的 JAVASCRIPT 库。 -
angular(这个框架是)—》Google,大部分用的是typescript,缩进两个空格AngularJS 是一个 JavaScript 框架。它是一个以 JavaScript 编写的库。
对象字面量
- 对象字面量:包围在一个花括号”{}“中的0个或多个键值对。键值对之间使用逗号隔开
// <!-- const obj = new object()-->
// <!-- const obj = {}-->
//{}对象字面量
//我们以前写对象字面量
const obj = {
name : 'why',
age : 18,
run:function () {
console.log('在');
},
eat:function () {
console.log('干嘛');
}
}
1.属性的增强写法
//1.属性的增强写法
const name = 'why';
const age = 18;
const height = 1.88
//ES5的写法
const obj = {
name : name,
age : age,
height : height
}
console.log(obj);
//ES6的写法
const obj = {
name,
age,
height,
}
console.log(obj);
2.函数的增强写法
//ES5的写法
const obj = {
run : function () {
},
eat : function () {
}
}
//ES6的写法
const obj = {
fun(){
},
eat(){
}
}
webstorm光标变成小方块,会覆盖
- 解决方法:按下insert
事件监听
v-on的基本使用
- 语法糖的使用
v-on:click可以写成@click
通过下面案例监听按钮的点击事件,看看v-on的使用
- 三种写法
<button v-on:click = "counter++">+</button>
<button v-on:click = "increase">+</button>
<button @click = "increase">语法糖</button>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<h2>点击次数:{{counter}}</h2>
<!-- <button v-on:click = "counter++">+</button>-->
<!-- <button v-on:click = "counter--">-</button>-->
<button v-on:click = "increase">+</button>
<button v-on:click = "decrease">-</button>
<button @click = "increase">语法糖</button>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el:'#app',
data:{
counter:0
},
methods:{
increase(){
this.counter++
},
decrease(){
this.counter--
}
}
})
</script>
</body>
</html>
v-on参数问题
1.事件调用的方法没有参数
- 意思是下面的btn1click里面没有参数
<button @click = "btn1click()">按钮1</button>
<button @click = "btn1click">按钮1</button>
2.在事件定义时,写函数时省略了小括号,但是方法本身是需要一个参数的
<!-- <button @click="btn2click(123)">按钮2</button>-->
//正常
<!-- <button @click="btn2click()">按钮2</button>-->
<!-- 会打印undefined-->
<button @click="btn2click">按钮2</button>
会把浏览器生成的event对象传过来 在事件定义时,写方法时省略了小括号,但是方法本身是需要一个参数的,这个时候,vue会默认将浏览器的event事件对象作为参数传入到方法
某些情况你需要拿到这个event对象,你就可以这样写,下面写一个event参数,上面不带括号
3. 方法定义时,我们需要event对象,同时又需要其他参数
- 当你在界面上进行一些操作时,浏览器会自动给你生成一个event对象,写成event会报错,没有一个event属性或者方法,当成一个变量,如果在data里面写上一个event:‘ocder’就不会报错了,
<button @click = "btn3click">按钮3</button>
都不写,会把event传给第一个参数,第二个event变成undefined
<button @click = "btn3clic(123,event)">按钮3</button>
后一个参数写成event会报错,为undefined,这里是把event当成一个变量,就会在下面找,在data里面定义一个变量,就可以找到
如何手动的拿到浏览器参数event对象:$event
<button @click = "btn3clic(123,$event)">按钮3</button>
传一个123,‘abc’,当成基本内型传进去了,如果写成abc,当成一个变量,又会在下面找
<button @click = "btn3clic(abc,$event)">按钮3</button>
<script>
const app = new Vue({
el:'#app',
data:{
message:'你好啊',
abc:'ektbav'
},
methods:{
btn1click(){
console.log("btn1click");
},
btn2click(event){
console.log('-----',event);
},
btn3click(abc,event){
console.log('++++',abc, event);
}
}
})
//如果函数需要参数,但是没有传入,那么函数的形参为undefined
// function abc(name){
// console.log(name);
// }
// abc()
</script>
v-on修饰符
1. .stop修饰符的使用
阻止冒泡
<div @click = "divclick">
<button @click.stop="btnclick">按钮</button>
</div>
//加了之后,只打印btnclick,不打印divclick
2. .prevent修饰符的使用
<form action="baidu">
<input type="submit" value="提交" >
不希望通过submit自动提交,使用下面这样,可以自己收集数据进行提交
<!-- <input type="submit" value="提交" @click.prevent="submitclick">-->
</form>
3.监听某个键盘的键帽
keyup:键盘的点击事件:一直按着键盘不会有打印,松开才会有
<input type="text" v-on:keyup="keyup">
语法糖
<input type="text" @keyup="keyup">
监听enter
<input type="text" @keyup.enter="keyup">
4.once修饰符的使用,只执行一次回调
<button @click.once="btn2click">只能执行一次</button>
其他代码:
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el:'#app',
data:{
message:'你好啊'
},
methods:{
btnclick(){
console.log("btnclick");
},
divclick(){
console.log("divclick");
},
submitclick(){
console.log("submitclick");
},
keyup(){
console.log("keyup");
},
btn2click(){
console.log("btn2click");
}
}
})
</script>
</body>
条件判断
1.v-if的使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<h2 v-if="isshow">{{message}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el:'#app',
data:{
message:'你好啊',
isshow:true
}
})
</script>
</body>
</html>
02-v-if和v-else的使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<h2 v-if="isshow">{{message}}</h2>
<h1 v-else>isshow为false时,显示我</h1>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el:'#app',
data:{
message:'你好啊',
isshow:true
}
})
</script>
</body>
</html>
03-v-if和v-else-if和v-else的使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<h2 v-if="score>=90 ">优秀</h2>
<h2 v-else-if="score>=80">良好</h2>
<h2 v-else-if="score>=90 ">优秀</h2>
<h2 v-else>不及格</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el:'#app',
data:{
score:99
}
})
</script>
</body>
</html>
但是建议使用下面这种写法,不建议使用上面那种在标签里面直接写属性
<h1>{{result}}</h1>
computed:{
result(){
let show ='';
if(this.score>=90){
show = '优秀'
}else if(this.score。=80){
show = '良好'
}
//...
return show;
}
}
用户登录切换的案例
- 使用v-if和v-else制作
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<span v-if="isuser">
<label for="username">用户账号</label>
<!-- 设置label标签的for和input标签的id一样,当点击用户账号时,框框会被选中-->
<input type="text" id="username" placeholder="用户账号">
</span>
<span v-else>
<label for="email"> 用户邮箱</label>
<input type="text" id="email" placeholder="用户邮箱">
</span>
<button @click="isuser = !isuser">切换登录方式</button>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el:'#app',
data:{
message:'你好啊',
isuser:true,
}
})
</script>
</body>
</html>
用户登录切换的案例问题–当切换登录方式之后,原来的数据并不会进行修改
- 过程:把一个东西放到浏览器上面渲染,不会直接放到浏览器上,react也是,会先将我们即将显示的东西放到我们的内存里面,这个东西我们一般称之为vdom–虚拟dom,虚拟dom其实是我们真实dom的一种映射,再把虚拟dom渲染到浏览器上
- Vue在进行Dom渲染时,出于性能考虑,会尽可能的复用已经存在的元素,而不是重新创建新的元素
- 在上面的案例中,Vue内部会发现原来的input元素不再使用,直接作为else中的input来使用了, 互斥,不会保存两个
- 解决方法:在下面两个input标签的后面加上key,并且我们需要保证两个key值的不同
解决方法:在下面两个input标签的后面加上key,并且我们需要保证两个key值的不同,这样提交的时候就会进行对比
<input type="text" id="username" placeholder="用户账号" key="username">
<input type="text" id="email" placeholder="用户邮箱" key="email">
v-show的使用
- v-show的用法和v-if非常相似,也用于决定一个元素是否渲染、
v-if和v-show的对比
- v-if和v-show都决定一个元素是否渲染,那么开发中我们如何选择?
- 同
- 两个元素都会消失
- 异
- 当isshow为false时,包括v-if指令的元素,根本就不会存在dom中
- 当isshow为false时,v-show只是给我们元素添加一个行内样式:dispaly;none
开发中如何选择
- 当需要在显示和隐藏之间切换很频繁时,使用v-show,当只有一次切换时,使用v-if
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
当isshow为false时,两个元素都会消失,但是不同的是,包括v-if指令的元素,根本就不会存在dom中
<h2 v-if="isshow" id="aaa">{{message}} </h2>
当isshow为false时,v-show只是给我们元素添加一个行内样式:dispaly;none
<h2 v-show="isshow" id="bbb">{{message}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el:'#app',
data:{
message:'你好啊',
isshow:true,
}
})
</script>
</body>
</html>
循环遍历
v-for遍历数组
-
值,下标
1.在遍历的过程中,没有使用索引值(下标值) -
<li v-for="m in names">{{m}}</li>
2.在遍历的过程中,获取索引值
<li v-for="(item , index) in names">
完整代码;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
1.在遍历的过程中,没有使用索引值(下标值)
<ul>
<li v-for="m in names">{{m}}</li>
</ul>
2.在遍历的过程中,获取索引值
<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:['why','haha','gygy','juju']
}
})
</script>
</body>
</html>
v-for遍历对象
- 值,名字,索引
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>
完整代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
1.在遍历对象的过程中,如果只获取一个值,那么获取到的是value
<ul>
<li v-for="item in info">{{item}}</li>
</ul>
2.获取key和value 格式:(value,key)
<ul>
<li v-for="(value,key) in info">{{value}}--{{key}}</li>
</ul>
3.获取key和value和index 格式:(value,key,index)
<ul>
<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:'hahah',
age:12,
height:1.88
}
}
})
</script>
</body>
</html>
v-for使用过程添加key
- 官方推荐我们在使用v-for时,给对应的元素或组件上添加一个:key属性
为甚么需要key属性呢
- 这个其实和Vue的虚拟Dom的Diff算法有关系
- 当某一层有很多相同的节点时,也就是列表节点时,我们插入一个新的节点,数组渲染之后,在中间插入元素的渲染过程,假如一个数组里面有abcd五个元素,当我们想在b和c之间插入一个元素f时,Diff算法默认将c更新成f,d更新成c,最后在插入d
app.letters.splice(2,0,'f')
- 所以我们需要使用key给每一个节点做一个唯一标识,有key的话会先根据我们的key和我们的内容一一对应,这里绑定的key值需要一一对应,不能绑定索引,不是一一对应的,每次会变,有key的li里面的元素有没有发生变化,没有的话就会进行复用
- key的作用主要是为了高效的更新虚拟Dom
- 从第二个开始,删除零个,添加f
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<ul>
<li v-for="item in letters" :key="item">{{item}}</li>
</ul>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el:'#app',
data:{
letters:['a','b','c','d','e'],
}
})
</script>
</body>
</html>
那些数组的方法是响应式的
- 数据是响应式的,将会渲染出来一个虚拟Dom,再根据虚拟Dom将我们的真实进行修改
- Duplicate(重复)多点几次就会重复,所以报错了
1.可变参数
function sum(...num){
//这么写的话这里可以传好多值(可变参数)
console.log(num);
//打印出来是一个数组
}
sum(12,3,4,4,4,4,434,90);
2.通过索引值修改数组中的元素
1.this.letters[0] = 'bbbb';
因为这种方式vue并没有进行监听的,所以通过这种方法不会刷新界面,重新渲染dom
并不是所有改变我们数据的方法都可以做到响应式的,上面这个修改之后数组里面的值确实被改变了,但是我们的页面却没有改变
怎么解决这种办法:
1.this.letters.splice(0,1,'a');//比较推荐这种方法
2.set(要修改的对象,索引值,修改后的值)
Vue.set(this.letters,0,'bbbbb');
那些数组的方法是响应式的
- push()–向最后添加元素
- pop()–删除最后元素
- shift()–删除第一个元素
- unshift()–删除最后一个元素
- splice()–删除元素,插入元素,替换元素
- sort()–排序
- reserve()–反转
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<ul>
<li v-for="item in letters">{{item}}</li>
</ul>
<button @click="btn1click">按钮</button>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el:'#app',
data:{
letters:['a','b','c']
},
methods:{
btn1click() {
//1.push方法,可以一次加多个
this.letters.push('aaa');
//2. pop():删除数组中的最后一个元素
this.letters.pop();
//3.shift():删除数组中的第一个元素
this.letters.shift();
//4.unshift():在数组最前面添加元素,可以一次加多个
//按着ctrl键指上单词可以查看源码,里面有...
this.letters.unshift('aaa','ejfi');
//5.splice作用:删除元素/插入元素/替换元素
第一个元素:开始位置
删除元素:第二个参数传入你要删除几个元素,如果不传第二个参数,会从第一个开始到最后都删除,除了第一个
替换元素:第二个参数,表示我们要替换几个元素,后面是用于替换前面的元素,可以理解成先删除,在替换,替换可以大于删除个数
插入元素:this.letters.splice(1,0,'a','a');第二个参数,传入0,后面跟上要插入的元素,在1的后面插入
splice(1,3,'f','d','d','s');
//6.sort();排序:可以传参数,传一个函数
this.letters.sort();//排出来a,b,c,d
//reverse()反转
this.letters.reverse();//dcba
}
}
})
</script>
</body>
</html>
书籍购物车案例
实现以下功能
- 价格保留两位小数
- count++ --监听
- 购买数量最少为一
- 移除
- 购物车为空
- 总价格
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div id="app">
<div v-if="books.length">
<table>
<thead>
<tr>
<th></th>
<th>书籍名称</th>
<th>出版日期</th>
<th>价格</th>
<th>购买数量</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr v-for="(item,index) in books">{{item}}
<!-- <td v-for="value in item">{{value}} </td>-->
<!--tr这样写相当于将一个对象当作字符串放到里面,这里可以循环遍历td(标准单元格),还有保留两位小数,不建议这样写-->
<td>{{item.id}}</td>
<td>{{item.name}}</td>
<td>{{item.date}}</td>
<!--第一种写法:<td>{{'¥' + item.price.toFixed(2)}}</td>这样写可以保留两位小数 -->
<!-- 第二种写法:<td>{{ getfinalprice(item.price)}}</td>写到methods里面,这样的话在后面的总价格也能用-->
<!-- 第三种写法:<td>{{item.price | showprice}}</td>过滤器,实际上是一个函数,会把我们要过滤的这个参数传到里面来的,写在vue里-->
<td>{{item.price | showprice}}</td>
<td>
<button @click="decrement(index)" v-bind: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>
-->
<h2>总价格:{{totalPrice}}</h2>
</div>
<h2 v-else>购物车为空</h2>
</div>
<!--下面引用这两个顺序不能乱-->
<script src="../js/vue.js"></script>
<script src="main.js" ></script>
</body>
</html>
vue
const app = new Vue({
el:"#app",
data:{
books:[
{
id:1,
name:'算法导论',
date:'2006-9',
price:85.00,
count:1
},
{
id:2,
name:'算法导论',
date:'2006-9',
price:90.00,
count:1
},
{
id:3,
name:'算法导论',
date:'2006-9',
price:72.00,
count:1
},
{
id:4,
name:'算法导论',
date:'2006-9',
price:59.00,
count:1
},
]
},
methods:{
// getfinalprice(price){
// return '$' + price.toFixed(2);
// }
decrement(index){
this.books[index].count--;
},
increment(index){
this.books[index].count++;
},
removehandle(index){
this.books.splice(index,1);
}
},
computed:{
totalPrice(){
let totalPrice = 0;
for(let i=0;i < this.books.length; i++){
totalPrice += this.books[i].price * this.books[i].count
}
return totalPrice
}
},
//过滤器,实际上是一个函数,会把我们要过滤的这个参数传到里面来的
filters:{
showprice(price){
return '$' + price.toFixed(2);
}
}
})
css
table{
border: 1px solid #e9e9e9;
border-collapse: collapse;
/*为表格设置合并边框模型:*/
border-spacing: 2;
/*borderSpacing 属性设置或返回表格中单元格之间的距离*/
}
th,td{
padding: 8px 16px;
border: 1px solid #e9e9e9;
text-align: center;
}
th{
background-color: #f7f7f7;
color: #5cb85c;
font-weight: 600;
}
对于案例总价格的其他两种写法
for(let i in this.books)
键值for (let item of this.books)
对象reduce
高阶函数
computed:{
totalPrice() {
// 1. let totalPrice = 0;
// for(let i=0;i < this.books.length; i++){
// totalPrice += this.books[i].price * this.books[i].count
// }
// return totalPrice
// 2.let totalPrice = 0;
// for(let i in this.books){
// const book = this.books[i];
// totalPrice += book.price * book.count;
// }
// return totalPrice;
3. let totalPrice = 0;
for (let item of this.books) {
totalPrice += item.price * item.count;
}
return totalPrice;
4.return this.books.reduce(function (prevalue,book) {
return prevalue + book.price * book.count
},0)
}
},
高阶函数
- 编程范式:命令式编程/声明式编程
- 编程范式:面向对象编程(第一公民:对象)/函数式编程(第一公民:函数)
- 好处:函数式编程可以进行好多的链式编程
filter/map/reduce
原始的代码:
const nums = [10,20,30,111,222,444,40];
//1.需求:取出所有小于100的数字
let newNums = [];
for (let n of nums){
if(n <100){
newNums.push(n)
}
}
//2.需求:将所有小于100的数字进行转换:全部*2
let new2Nums = [];
for(let n of newNums){
new2Nums.push( n * 2 )
}
console.log(new2Nums);
//3.需求:将所有new2Nums数字相加,得到最终的记过
let toatl = 0
for (let n of new2Nums){
total += n
}
console.log(total);
- 高阶函数也就实说,函数需要的参数本来也是一个参数
1.filter函数的使用—过滤作用
- filter:传一个function,每次都会从数组里面取出一个值传进来
- filter中的回调函数有一个要求:必须返回一个Boolean值
- 当返回true时,函数内部会自动将这次回调的n加入到新的数组中
- 当返回false时,函数内部会过滤掉这次的n
- 会形成一个新的数组·,而这个数组会作为filter这个大的函数的返回值,只需要在前面接收一下
//1.需求:取出所有小于100的数字
//10,20,30,40
const nums = [10,20,30,111,222,444,40];
let newNums = nums.filter(function (n) {//10
return n < 100//false
})
console.log(newNums);
2.map函数的使用–变化作用
- 如果你想对数组里面所有的东西进行某一次的变化,使用map函数
2.需求:将所有小于100的数字进行转换:全部*2
//20,40,60,80
let new2Nums = newNums.map(function (n) {
return n * 2
})
console.log(new2Nums);
3.reduce函数的使用
- reduce作用对数组中所有的内容进行汇总,传两个参数
- new2Nums.reduce(参数一,参数二);
- 后面的一般为零,零是初始化值
- 值的情况:第一次:prevalue 0 n 20 第二次:prevalue 20 n 40,第三次:prevalue 60 n 60 第四次:prevalue 120 n 80 最后得到的结果为200
- prevalue第一次的值初始化的值0,第二三四次为返回的值,而后面的值就为我们数组里面的值
//200
let total = new2Nums.reduce(function (prevalue,n) {
return prevalue + n;
},0)
写在一起简洁
1.链式
let total = nums.filter(function (n) {
return n<100
}).map(function (n) {
return n * 2
}).reduce(function (prevalue,n) {
return prevalue + n
},0)
console.log(total);
2.箭头函数
let total = nums.filter(n => n <100).map(n => n*2).reduce((pre , n) => pre +n);
console.log(total);
v-model的使用
-Vue中使用v-model指令来实现表单元素和数据的双向绑定
v-model也可以用于textarea
v-model的基本使用
- input标签实现了双向绑定,当我们删除输入框里面的内容时,外面的内容也会被删除,当我们通过控制台改变message里面的内容时,输入框里面的内容也会被改变
- v-model会自动将message里面的信息作为我们的input里面的value值显示在界面,data里面的东西已经被绑定到input上面
- input有一个事件叫input,动态监听我们用户输入东西
<input type="text" v-model = "message">
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<!-- v-model会自动将message里面的信息作为我们的input里面的value值显示在界面中-->
data里面的东西已经被绑定到input上面了,双向绑定,当我们删除输入框里面的内容时,外面的内容也会被删除
<input type="text" v-model = "message">
{{message}}
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el:'#app',
data:{
message:'你好啊'
}
})
</script>
</body>
</html>
v-model的原理
原理
- v-model其实是一个语法糖,背后本质上包括两个操作
- v-bind绑定一个value属性
- v-on指令给当前元素绑定input事件
Vue event.target.value( ) 获取当前文本框的值(由事件触发时)
- 将message里面的值绑定到input标签里面v-bind:value input有一个事件叫input,动态监听我们用户输入东西,反过来绑定:v-on:input
不用v-model我们也可以实现双向绑定,如下
- 两种写法
<input type="text" :value="message" @input="valuechange">,methods方法
<input type="text" :value="message" @input="message = $event.target.value">
v-model结合radio
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<!-- <input type="text" v-model = "message">-->
<!-- 不用v-model我们也可以实现双向绑定,如下-->
<!-- 将message里面的值绑定到input标签里面v-bind:value input有一个事件叫input,动态监听我们用户输入东西,反过来绑定:v-on:input-->
<!-- <input type="text" :value="message" @input="valuechange">-->
<input type="text" :value="message" @input="message = $event.target.value">
<h2>{{message}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el:'#app',
data:{
message:'你好啊'
}
// ,
// methods:{
// valuechange(event){
// this.message = event.target.value;
// }
// }
})
</script>
</body>
</html>
v-model结合radio
- 通过v-model将我们选择的东西绑定到sex里面
- 这里加上name属性才会互斥,但是一旦加上v-model也会互斥,就不用写name了
- 默认选中的话,在sex里面写上性别,就会默认选中
- v-model结合radio是选中
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<label for="male">
//这里可以不写name属性
<input type="radio" id="male" name="sex" value="男" v-model="sex">男
</label>
<label for="female">
<input type="radio" id="female" name="sex" value="女" v-model="sex">女
</label>
<h2>您选择的性别是:{{sex}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el:'#app',
data:{
message:'你好啊',
sex:'男'
}
})
</script>
</body>
</html>
v-model结合checkbox类型
- 复选框分为两种情况,单个勾选框和多个勾选框
- v-model是选中
- 当点击多选框的时候,数据会被加到数组里
1.checkbox单选框:一般对应的是一个布尔内型
- 此时的value值并不影响v-model的值
<label for="agree">-->
label的好处,有了label,可以点文字,也会选中-->
<input type="checkbox" id="agree" v-model="isagree">同意协议-->
</label>-->
<h2>您选择的是:{{isagree}}</h2>-->
disabled等于true,表示禁用-->
<button :disabled=" !isagree">下一步</button>-->
2.checkbox多选框,一般对应的是一个数组类型
为什么这里通过控制台修改数组,多选框会被全部选中
- 当选中某一个时,就会将input的value添加到数组中
这里就不要用label了,一般来说,一个input绑定一个label-->
<input type="checkbox" value="篮球" v-model="hobbies">篮球
<input type="checkbox" value="足球" v-model="hobbies">足球
<input type="checkbox" value="乒乓球" v-model="hobbies">乒乓球
<input type="checkbox" value="羽毛球" v-model="hobbies">羽毛球
<h2>您的爱好是:{{hobbies}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el:'#app',
data:{
message:'你好啊',
isagree:false,
hobbies:[]
}
})
</script>
</body>
</html>
v-model结合select类型
- multiple 属性规定输入字段可选择多个值。如果使用该属性,则字段可接受多个值。
- select也分单选和多选两种情况
1.选择一个
- id是不能重复的,name到时候是向服务器提交的key
- v-model绑定的是一个值
- 当我们选中option中的一个值时,会将它对应的value赋值到fruit里面
- 是一个字符串内型
<select name="abc" id="" v-model="fruit">
<option value="苹果" >苹果</option>
<option value="香草" >香草</option>
<option value="桃子" >桃子</option>
<option value="葡萄" >葡萄</option>
</select>
<h2>您选择的水果是:{{fruit}}</h2>
2.选择多个,加上multiple
- v-model绑定的是一个数组
- 当选中多个值时,就会将选中的option对应的value添加到fruits里面
<select name="abc" id="" v-model="fruits" multiple>
<option value="苹果" >苹果</option>
<option value="香草" >香草</option>
<option value="桃子" >桃子</option>
<option value="葡萄" >葡萄</option>
</select>
<h2>您选择的水果是:{{fruits}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el:'#app',
data:{
message:'你好啊',
fruit:'香草',
fruits:[]
}
})
</script>
</body>
</html>
值绑定
- 就是动态的给value赋值而已,上面我们的例子是value值是写死的,直接定义在input标签里面的,但是真是开发中,这些input的值可能是从网络获取或者定义在data中的,所以我们可以通过v-bind:value动态的给value绑定值,就是v-bind在input中的应用
这样界面中显示不出来item
<input type="checkbox" v-for="item in originhobbies " :value = "item">
<h2>{{item}}</h2>
使用如下写法:我们在label中需要使用我们的item
<label v-for="item in originhobbies " :for="item">-->
<input type="checkbox" :value = "item" :id="item" v-model="hobbies">{{item}}-->
</label>-->
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el:'#app',
data:{
message:'你好啊',
isagree:false,
hobbies:[],
originhobbies:['篮球','平棒球','羽毛球']
}
})
</script>
修饰符
1.修饰符:lazy
- lazyload:懒加载,用到时才加载
- 这样的话用户每输一个字符,都会实时的把我们的结果放到message里面,默认情况下,v-model是在input事件中同步输入框的数据的,一般没有这个必要
<input type="text" v-model="message">
<h2>{{message}}</h2>
- 我们想让用户按下回车或者当文本框失去焦点时,这个时候才绑定过来,绑定就不会调用那么频繁了-- .lazy
<input type="text" v-model.lazy="message">
<h2>{{message}}</h2>
2.修饰符:number
-
这样用户只能输入数字,将文本框的内型改为number
-
默认情况下,V-model在给变量赋值时,都是string类型
-
这样写,默认传个0,第一次为number,当我们在继续往里面写入数字时,会变成number内型,但是我们确实希望他是一个number内型,这样的话就不用进行内型转换了
<input type="number" v-model="age">
<h2>{{age}}--{{typeof age}}</h2>
- 解决办法:-- .number
<input type="number" v-model.number="age">
<h2>{{age}}--{{typeof age}}</h2>
3.修饰符:trim
- 当我们输入有很多空格时,浏览器会进行一个处理不显示在界面上,但是通过控制台就可以看到
- 怎么去除空格
var str = "1 123 123";
const str1 = str.replace(/\s/ig"")
console.log(str1) // 1123123
- 使用trim,只能去除首尾的空格
<input type="text" v-model.trim="name">
<h2>您输入的名字;{{name}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el:'#app',
data:{
message:'你好啊',
age:0,
name:''
}
})
</script>
</body>
</html>