Vue基础
1、介绍
1.1、Vue.js 是什么
Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架,Vue 的核心库只关注视图层,Vue 吸收了 Angular(模块化)和React(虚拟DOM)
1.2、起步
在html中引入Vue
<!--方式一:直接CDN引入-->
<!--导入 vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<!--方式二:下载和引入-->
<!--导入 vue.js(先从官网下载下来)-->
<script src="../../js/vue.js"></script>
<!--方式二:NPM安装-->
1.3、声明式渲染
- Vue.js 的核心是一个允许采用简洁的模板语法来声明式地将数据渲染进 DOM 的系统
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <!--导入 vue.js--> <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script> <!--view层 模板--> <div id="app"> {{message}} </div> <h1 id="hh">你好</h1> <script> // 申明式编程 let app=new Vue({ el:"#app",//用于挂载要管理的元素 //Model层:数据 data:{ //定义数据 message:'hello,vue!' }, }); </script> </body> </html>
现在数据和 DOM 已经被建立了关联,所有东西都是响应式的。
- 绑定元素 attribute
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script> <div id="app"> <span v-bind:title="message"> 鼠标悬停几秒钟查看此处动态绑定的提示信息!</span> </div> <script> let app=new Vue({ el:"#app", data:{"message":'hello,vue!'}, }); </script> </body> </html>
v-bind
attribute 被称为指令。指令带有前缀v-
,以表示它们是 Vue 提供的特殊 attribute。
1.4、条件(if)与循环(for)
1.4.1、v-if
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<div id="app">
<p v-if="showFlag"> 显示了</p>
</div>
<script>
let app=new Vue({
el:"#app",
data:{"showFlag":true},
});
</script>
</body>
</html>
在控制台输入 app.showFlag= false,你会发现之前显示的消息消失了
1.4.2、v-for
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<div id="app">
<ul>
<li v-for="item in movie">{{item}}</li>
</ul>
</div>
<script>
let app=new Vue({
el:"#app",
data:{movie:['美队','钢铁侠','惊奇队长','蜘蛛侠']},
});
</script>
</body>
</html>
在控制台里,输入 app.movie.push(‘绿巨人’),你会发现列表最后添加了一个新项目
1.5、处理用户输入
- 为了让用户和你的应用进行交互,我们可以用
v-on
指令添加一个事件监听器,通过它调用在 Vue 实例中定义的方法:<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script> <div id="app"> <p>{{ message }}</p> <button v-on:click="reverseMessage">反转消息</button> </div> <script> let app=new Vue({ el:"#app", data:{message:'hello,Vue!'}, methods:{ reverseMessage:function () { this.message = this.message.split('').reverse().join('') } } }); </script> </body> </html>
- 属性:methods,该属性用于在Vue对象中定义方法
- 指令:@click,是v-on:click的简写(语法糖),用于监听某个元素的点击事件,并且需要指定当发生点击时,执行的方法
- 计数器
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--导入 vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<!--view层 模板-->
<div id="app">
当前数为:{{count}}
<!-- <button @click="count++">+</button>-->
<!-- <button @click="count--">-</button>-->
<button v-on:click="count++">+</button>
<button v-on:click="count--">-</button>
</div>
<h1 id="hh">你好</h1>
<script>
let vm=new Vue({
el:"#app",
//Model层:数据
data:{count:0},
});
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--导入 vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<!--view层 模板-->
<div id="app">
当前数为:{{count}}
<!-- <button @click="count++">+</button>-->
<!-- <button @click="count--">-</button>-->
<button v-on:click="add">+</button>
<button v-on:click="sub">-</button>
</div>
<h1 id="hh">你好</h1>
<script>
let vm=new Vue({
el:"#app",
//Model层:数据
data:{count:0},
methods: {
add:function () {
this.count++;
},
sub:function () {
this.count--
}
}
});
</script>
</body>
</html>
注意:在reverseMessage
方法中,我们更新了应用的状态,但没有触碰DOM
——所有的DOM
操作都由 Vue 来处理,你编写的代码只需要关注逻辑层面即可
- Vue 还提供了
v-model
指令,它能轻松实现表单输入和应用状态之间的双向绑定<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <!--导入 vue.js--> <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script> <!--view层 模板--> <div id="app"> <p>{{message}}</p> <input v-model="message" type="text"> </div> <script> let vm=new Vue({ "el":"#app", //Model层:数据 "data":{"message":'hello,vue!'}, }); </script> </body> </html>
1.6、MVVM
- M(Model):数据层
数据可以是固定的,也可以是来自服务器的 - V (View) : 视图层
在前端开发中,通常就是DOM层,主要作用就是给用户展示各种信息 - VM(VueModel):视图模型层, View和Model沟通的桥梁
- 一方面实现了Data Binding,即数据绑定,将Model的改变实时的反应到View当中去
- 另一方面实现了DOM Listener,即DOM监听,当DOM发生一些事件(点击、滚动、touch等)时,可以监听到,并在需要的情况下改变对应的Data
1.7、Vue的options
1.7.1、el
- 类型:String | HtMLElement
- 作用:决定之后Vue实例会管理哪一个DOM
1.7.2、data
- 类型:Object | Function(组件当中data必须是一个函数)
- 作用:Vue实例对应的数据对象
1.7.3、methods
- 类型:{[key:string]:Function}
- 作用:定义属于Vue的一些方法,可以在其他地方调用,也可以在指令中使用
1.8、Vue生命周期
生命周期:事物从诞生到消亡的整个过程
1.7、组件化应用构建
1.7.1、注册组件(静态)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--导入 vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<!--view层 模板-->
<div id="app">
<ol>
<!-- 创建一个 todo-item 组件的实例 -->
<todo-item></todo-item>
</ol>
</div>
<script>
// 定义名为 todo-item 的新组件
Vue.component('todo-item',{
template: '<li>这是个待办项</li>'
})
let vm=new Vue({
"el":"#app"
});
</script>
</body>
</html>
1.7.2、注册组件(动态)
上述注册的组件会为每个待办项渲染同样的文本,这看起来并不炫酷。我们应该能从父作用域将数据传到子组件才对。让我们来修改一下组件的定义,使之能够接受一个 prop:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--导入 vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<!--view层 模板-->
<div id="app">
<ol>
<!--
现在我们为每个 todo-item 提供 todo 对象
todo 对象是变量,即其内容可以是动态的。
我们也需要为每个组件提供一个“key”,稍后再
作详细解释。
-->
<todo-item
v-for="item in groceryList"
v-bind:todo="item"
v-bind:key="item.id"
></todo-item>
</ol>
</div>
<script>
// 定义名为 todo-item 的新组件
Vue.component('todo-item', {
// todo-item 组件现在接受一个
// "prop",类似于一个自定义 attribute。
// 这个 prop 名为 todo。
props: ['todo'],
template: '<li>{{ todo.text }}</li>'
})
let tmp=new Vue({
el:"#app",
data:{
groceryList: [
{ id: 0, text: '蔬菜' },
{ id: 1, text: '奶酪' },
{ id: 2, text: '随便其它什么人吃的东西' }
]
}
});
</script>
</body>
</html>
2、Vue实例
2.1、创建一个vue实例
var vm = new Vue({
// 选项
})
2.2、 数据与方法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--导入 vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<!--view层 模板-->
<div id="app">
{{a}}
</div>
<script>
let data={a:1};
let vm=new Vue({
el:"#app",
//Model层:数据
data:data,
});
</script>
</body>
</html>
当这些数据改变时,视图会进行重渲染。值得注意的是只有当实例被创建时就已经存在于 data 中的 property 才是响应式的。
2、插值操作
2.1、Mustache{{变量/表达式}}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--导入 vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<!--Mustache:可以写变量也可以写简单表达式-->
<div id="app">
<h2>{{message}}</h2> <!-- hello,vue!-->
<h2>{{num1+num2}}</h2> <!-- 15-->
<h2>{{num1}}+{{num2}}</h2> <!-- 10+5-->
</div>
<script>
let app=new Vue({
el:"#app",
data:{
message:'hello,vue!',
num1:10,
num2:5
},
});
</script>
</body>
</html>
2.2、v-once
- 组件和元素只渲染一次,不会随数据的改变而改变
- v-once后面不跟任何表达式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--导入 vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<!--view层 模板-->
<div id="app">
<p>{{message}}</p>
<p v-once>{{message}}</p>
</div>
<script>
let app=new Vue({
el:"#app",
data:{"message":'hello,vue!'},
});
</script>
</body>
</html>
2.3、v-html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--导入 vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<!--view层 模板-->
<div id="app">
<p>{{url}}</p>
<p v-html="url"></p>
</div>
<script>
let app=new Vue({
el:"#app",
data:{
url:'<a href="https://www.baidu.com">百度一下</a>'
},
});
</script>
</body>
</html>
2.4、v-text
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--导入 vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<!--view层 模板-->
<div id="app">
<p>{{message}}</p>
<p v-text="message"></p>
</div>
<script>
let app=new Vue({
el:"#app",
data:{
message:'hello,Vue'
},
});
</script>
</body>
</html>
2.5、v-pre
原封不动输出
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--导入 vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<!--view层 模板-->
<div id="app">
<p>{{message}}</p>
<p v-pre>{{message}}</p>
</div>
<script>
let app=new Vue({
el:"#app",
data:{
message:'hello,Vue'
},
});
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
[v-cloak]{
display:none;
}
</style>
</head>
<body>
<!--导入 vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<!--view层 模板-->
<div id="app">
<p v-cloak>{{message}}</p>
</div>
<script>
//vue在解析之前,div有一个属性v-cloak
//在vuew解析之后,div没有有一个属性v-cloak
setTimeout(function () {
let app=new Vue({
el:"#app",
data:{
message:'hello,Vue'
},
});
},1000)
</script>
</body>
</html>
3、绑定属性
3.1、v-bind基础
用于给标签的属性动态赋值,简写为 :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--导入 vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<!--view层 模板-->
<div id="app">
<img v-bind:src="imgUrl" alt="">
</div>
<script>
let app=new Vue({
el:"#app",
data:{
imgUrl:'https://img11.360buyimg.com/pop/s1180x940_jfs/t1/184696/38/12293/98820/60dff17bE72e204db/07ee09a21f35514b.jpg.webp'
},
});
</script>
</body>
</html>
3.2、v-bind动态绑定class (对象语法)
- 点击按钮实现变色
- 方式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.active{
color: red;
}
.line{
color: blue;
}
</style>
</head>
<body>
<!--导入 vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<!--view层 模板-->
<div id="app">
<!-- <img v-bind:src="imgUrl" alt="">-->
<!-- 语法糖的写法-->
<p :class="{active:isActive,line:isLine}">{{message}}</p>
<button v-on:click="toChangge">点我</button>
</div>
<script>
let app=new Vue({
el:"#app",
data:{
message:'你好呀',
isActive:true,
isLine:false
},methods:{
toChangge:function () {
this.isActive=!this.isActive;
this.isLine=!this.isLine;
}
}
});
</script>
</body>
</html>
3.3、v-bind动态绑定class (数组语法)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--导入 vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<!--view层 模板-->
<div id="app">
<!-- <img v-bind:src="imgUrl" alt="">-->
<!-- 语法糖的写法-->
<p class="title" :class="[active,line]">{{message}}</p>
</div>
<script>
let app=new Vue({
el:"#app",
data:{
message:'你好呀',
active:'aaaa',
line:'bbbb'
}
});
</script>
</body>
</html>
3.4、v-bind+v-for(点击游戏)
描述:初始第一项字体为红,以后点击哪一项该项为红,其他项为黑
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.item{
color: red;
}
</style>
</head>
<body>
<!--导入 vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<!--view层 模板-->
<div id="app">
<ul>
<li :class="toChange(index)" v-on:click="clicked(index)" v-for="(item,index) in movies">{{item}}</li>
</ul>
</div>
<script>
let app=new Vue({
el:"#app",
data:{
current:0,
movies:[
'钢铁侠',
'绿巨人',
'蜘蛛侠',
'美国队长'
],
},
methods:{
clicked:function (e) {
this.current=e;
},
toChange:function(e){
return {item:(this.current==e)};
}
}
});
</script>
</body>
</html>
3.5、v-bind-动态绑定-style(对象语法)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--导入 vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<!--view层 模板-->
<div id="app">
<!-- <h2 :style="{key(属性名):value(属性值)}">{{message}}</h2>-->
<h2 :style="{color:'red'}">{{message}}</h2>
</div>
<script>
let app=new Vue({
el:"#app",
data:{"message":'hello,vue!'},
});
</script>
</body>
</html>
4、计算属性(computed)
4.1、基本使用
4.2、复杂操作
<body>
<!--导入 vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<!--view层 模板-->
<div id="app">
<h2>{{totalSize}}</h2>
</div>
<script>
let app=new Vue({
el:"#app",
data:{
books:[
{id:1,name:'人性的弱点',price:25},
{id:2,name:'简爱',price:20},
{id:3,name:'钢铁是怎样炼成的',price:68}
]
},
computed:{
totalSize:function(){
let price=0
for (let book of this.books){
price+=book.price
}
return price;
}
}
});
</script>
</body>
4.3、计算属性的getset方法
<body>
<!--导入 vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<!--view层 模板-->
<div id="app">
<h2>{{fullName}}</h2>
</div>
<script>
let app=new Vue({
el:"#app",
data:{
firstName:'pang',
lastName:'hx'
},
computed:{
fullName:{
get:function () {
return this.firstName+' '+this.lastName
},
//计算属性一般不设set方法,只读属性
set:function (newVable) {
const names=newVable.split(' ');
this.firstName=names[0];
this.lastName=names[1]
}
}
}
});
</script>
</body>
4.4、计算属性和methods的对比
4.4.1、拼接姓名
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--导入 vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<!--拼接-->
<div id="app">
<!-- 方式一:直接拼接不推荐使用 -->
<h2>{{firstName}} {{lastName}}</h2>
<!-- 方式二:通过定义methods -->
<h2>{{getFullName()}}</h2>
<!-- 方式三:通过computed(推荐使用) -->
<h2>{{fullName}}</h2>
</div>
<script>
let app=new Vue({
el:"#app",
data:{
firstName:'Pang',
lastName:'hx'
},
methods:{
getFullName:function () {
return this.firstName+' '+this.lastName;
}
},
computed:{
fullName: {
get:function () {
return this.firstName+' '+this.lastName;
}
}
}
});
</script>
</body>
4.4.2、methods方法测试
4.4.3、computed计算属性测试
4.4.3、computed对比methods
- computed有缓存机制,性能优于methods
- 只有当属性值发生改变(firstName、lastName)时,compute重新执行,否则只执行一次
5、块级作用域(let、var)
5.1、let/var
var:全局变量,没有块级作用域,会引起一些问题(if/for)
let:局部变量,具有块级作用域,不会预处理
const:常量,不可以被修改
5.1.1、var的缺陷
没有块级作用域引起的问题
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<button>按钮1</button>
<button>按钮2</button>
<button>按钮3</button>
<button>按钮4</button>
<button>按钮5</button>
<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>
存在的问题:无论点击哪一个按钮都输出第5个被点击了
5.1.2、var的缺陷ES5可以通过闭包解决:形参只在函数内有效
5.1.3、var的缺陷ES6可以通过let解决
5.2、const
- 表示一个常量****,只能赋值一次(必须是在定义时就赋值),不可修改
- 如果用来修饰对象表示该对象不能修改,而对象的内部属性是可以修改的
- 建议:在ES6开发中,优先使用const,只有需要改变某一个标识符的时候才使用let
5.3、对象字面量的增强写法
5.3.1、属性的增强写法
<script>
//属性增强
const name='zs';
const height=1.70;
const age=22;
//ES5写法
// const obj={
// name:name,
// height:height,
// age:age
// }
const obj={
name,age,height
}
console.log(obj);
</script>
5.3.2 函数的增强写法
6、事件监听 v-on
- 作用:绑定事件监听器
- 缩写:
@
- 参数:event
6.1、v-on基本使用
<body>
<!--导入 vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<!--view层 模板-->
<div id="app">
<h2>{{count}}</h2>
<!-- <button v-on:click="addClick()">+</button>-->
<button @click="addClick()">+</button>
<button v-on:click="subClick()">-</button>
</div>
<script>
let app=new Vue({
el:"#app",
data:{
count:0
},
methods:{
addClick(){
console.log("+1")
this.count+=1;
},
subClick(){
console.log("-1")
this.count-=1;
}
}
});
</script>
</body>
6.2、v-on参数
6.2.1、不需要参数
情况一:如果该方法不需要额外参数,那么方法后的()
可以不添加
6.2.2、需要参数
情况二:如果需要同时传入某个参数,同时需要event时,可以通过&event传入事件
6.2.2、需要参数但没有参数
注意:情况二需要传入参数
- 如果添加了()
但省略的参数怎会显示undefine=
- 如果省略了()
,则默认传入event对象
- 定义方法是需要event,同时还需要其他参数
6.3、v-on修饰符
6.3.1、 阻止冒泡(.stop)
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<!--view层 模板-->
<div id="app">
<div @click="divClick">
<button @click="btnClick">btn</button>
</div>
</div>
<script>
let app=new Vue({
el:"#app",
methods:{
divClick(){
console.log("divClick");
},
btnClick(){
console.log("btnClick");
},
}
});
</script>
每一次点击button会触发divClick和btnClick,而我们需求是点击button只触发btnClick
使用.stop
6.3.1、阻止默认事件(.prevent)
问题描述:点击提交按钮默认提交
需求:点击提交不走默认事件
6.3.3、 监听某个键盘键帽的点击
问题:只要有键帽按下后抬起就会触发keyUp(),而我们只想监听某一个键帽的点击事件
6.3.4、.once的使用
存在问题:每次点击都会触发toClick事件,而我们的需求是只能点击一次
- .once
7、条件判断
7.1、if、 else、 else if
7.1.1、登录切换demo
<body>
<!--导入 vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<!--view层 模板-->
<div id="app">
<h2 v-if="score>=90&&score<=100">优秀</h2>
<h2 v-else-if="score>=80&&score<90">良好</h2>
<h2 v-else-if="score>=60&&score<80">及格</h2>
<h2 v-else-if="score>=0&&score<60">不及格</h2>
<h2 v-else>输入不合法</h2>
</div>
<script>
let app=new Vue({
el:"#app",
data:{score:90},
});
</script>
</body>
7.1.2、登录切换demo存在的问题
- 问题:当用户输入信息后点击“切换登录方式”时,用户输入的内容没有被清空
- 原因:vue内部的复用(虚拟dmo)
- 解决方案:添加key,当key的值不一致时不会进行复用
7.2、v-show
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<!--view层 模板-->
<div id="app">
<h2 id="aaaaa" v-if="isShow">{{message}}</h2>
<h2 id="bbbbb" v-show="isShow">{{message}}</h2>
</div>
<script>
let app=new Vue({
el:"#app",
data:{
message:'hello,vue!',
isShow:true
},
});
</script>
当isShow=false时,两个都不显示,但隐藏方式不同
- v-show控制的时节点的display属性,v-if是将节点删除了,即包含v-if指令的元素,根本不会存在在dom中。
- 如何选择?
- 当需要在显示和隐藏之间切换很平凡时,使用v-show
- 当只有一次切换时,通过使用v-if
8、循环遍历
8.1、v-for遍历数组
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<!--view层 模板-->
<div id="app">
<ul>
<!--v-for 遍历数组-->
<li v-for="item in movies">{{item}}</li>
<!-- index:数组下标;
item:某一项的值
-->
<li v-for="(item,index) in movies">{{index+1}}、{{item}}</li>
</ul>
</div>
<script>
let app=new Vue({
el:"#app",
data:{
movies:['钢铁侠','美国队长','绿巨人','蚁人']
},
});
</script>
8.2、v-for遍历对象
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<!--view层 模板-->
<div id="app">
<ul>
<!--v-for 遍历对象,如果只获取一个值,那么获取到的是value-->
<li v-for="item in info">{{item}}</li>
<!-- value:对象的属性值;
key:对象的属性名
-->
<li v-for="(value,key) in info">{{key}}:{{value}}</li>
</ul>
</div>
<script>
let app=new Vue({
el:"#app",
data:{
info: {
name:'zs',
sex:'男',
age:23,
height:1.75
}
}
});
</script>
- 同时获取
value,key,index
8.3、组件的key属性
- 官方推荐我们在使用v-for时,给对应的元素或组件添加一个:key属性
- key的作用:主要是为了高效地更新虚拟DOM
- 个人理解;for循环给数组添加数据时,在没有加key时相当于线性表的插入,在添加了key属性之后相当于往链表中插入数据,性能更高
- 个人理解;for循环给数组添加数据时,在没有加key时相当于线性表的插入,在添加了key属性之后相当于往链表中插入数据,性能更高
8.4、数组的响应式方法
8.4.1、响应式方法
push(),pop(),shift(),unshift(),splice(),sort(),reverse()
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<!--view层 模板-->
<div id="app">
<ul>
<li v-for="(item) in movies">{{item}}</li>
</ul>
<button @click="toClick">点我</button>
</div>
<script>
let app=new Vue({
el:"#app",
data:{
movies:['a','b','c','d']
},
methods:{
toClick() {
//一:响应式方法:
//1、push方法:数组末尾添加一个或多个元素
// this.movies.push('eee')
//2、pop方法“数组末尾删除一个元素
//this.movies.pop()
//3、shift:在数组头位置删除一个元素
//this.movies.shift()
//4、unshift:在数组头位置添加一个或多个元素
//this.movies.unshift('111','222','333')
//5、splice()
//5.1、从下标为1的元素开始删除两个元素(b,c)
//this.movies.splice(1,2)
//5.2、从下标为1的元素开始插入三个元素(a,1,2,3,b,c,d)
//this.movies.splice(1,0,'1','2','3')
//5.3、从下标为1的元素开始替换2个元素(a,1,2,d)
//this.movies.splice(1,2,'1','2')
//6、sort:数组排序
//this.movies.sort();
//7、数组翻转
//this.movies.reverse();
//二:非响应式方法
//1、通过索引值修改数组中的元素
this.movies[0]='123'
}
}
});
</script>
8.4.2、 非响应式方法
如何实现响应式?
- 方式一:通过splice()
- 方式二:Vue.set()
8.4.3、 响应式方法重点介绍:splice()
- 作用:删除/插入/替换元素
- 参数一:要操作的元素位置
- 根据参数的个数判断是何种操作:
- 参数个数为2,表示删除操作
- 参数个数大于二,表示是插入/替换操作
- 第二个参数为0,表示插入操作,后面跟要插入的元素
- 第二个元素不是0,表示替换操作,代表要替换元素的个数,后面跟要替换前面的元素
9、书籍购物车案例
9.1、在价格前面加‘¥’,后面保留两位小数
9.1.1、拼接
9.1.2、过滤器
9.2、改变购物数量
9.3、移除书籍
9.4、自动计算总价
10、JavaScript中的高阶函数
10.1、filter()
- filter的回调函数有一个要求,必须返回一个boolean值
- 当返回值为true,函数内部会自动将这次回调的n加入到新的数组中
- 当返回值为false时, 函数内部会自动过滤掉这次的n
- 通过filter显示大于等于100的数字
<body>
<!--导入 vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<!--view层 模板-->
<div id="app">
<h2 >{{getNum()}}</h2><!-- [ 100, 222, 333 ]-->
</div>
<script>
let app=new Vue({
el:"#app",
data:{
arr:[1,100,222,60,333,90,70]
},
methods:{
getNum(){
let newArr=this.arr.filter(function (n) {
return n>=100
});
return newArr;
}
}
});
</script>
</body>
10.2、map()
对原来的数组的每一项进行相同的操作,返回一个新的数组
<body>
<!--导入 vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<!--view层 模板-->
<div id="app">
<h2 >{{getNum()}}</h2> <!-- [ 2, 200, 444, 120, 666, 180, 140 ]-->
</div>
<script>
let app=new Vue({
el:"#app",
data:{
arr:[1,100,222,60,333,90,70]
},
methods:{
getNum(){
let newArr=this.arr.map(function (n) {
return n*2
});
return newArr;
}
}
});
</script>
</body>
10.3、reduce()
对数组中所有的内容进行汇总
<body>
<!--导入 vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<!--view层 模板-->
<div id="app">
<h2 >{{getNum()}}</h2> <!-- 22-->
</div>
<script>
let app=new Vue({
el:"#app",
data:{
arr:[2,4,6,10]
},
methods:{
getNum() {
let newArr = this.arr.reduce(function (preValue,n) {
return preValue+n
},0);
return newArr
}
}
});
</script>
</body>
11、v-model
11.1、v-model基本使用
- 实现双向绑定:
- model(data)的数据改变,view(input)显示的数据会发生改变;
- view(input)显示的数据会发生改变, model(data)的数据也会发生改变
<body>
<!--导入 vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<!--view层 模板-->
<div id="app">
<input type="text" v-model="message">
<h2>{{message}}</h2>
</div>
<script>
let app=new Vue({
el:"#app",
data:{message:'hello,vue!'},
});
</script>
</body>
11.2、v-model原理
<body>
<!--导入 vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<!--view层 模板-->
<div id="app">
<input type="text" :value="message" @input="change">
<h2>{{message}}</h2>
</div>
<script>
let app=new Vue({
el:"#app",
data:{message:'hello,vue!'},
methods:{
change(event){
this.message=event.target.value
}
}
});
</script>
</body>
11.3、v-model结合radio
- 通过v-model属性可以实现组的绑定(和name的作用一样)
<body>
<!--导入 vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<!--view层 模板-->
<div id="app">
<!-- 使用 v-model可以省略name(绑定组)-->
<label for="male">
<input type="radio" name="sex" value="男" id="male" v-model="sex">男
</label>
<label for="female">
<input type="radio" name="sex" value="女" id="female" v-model="sex">女
</label>
<h2>性别:{{sex}}</h2>
</div>
<script>
let app=new Vue({
el:"#app",
data:{sex:'女'},
methods:{
change(event){
this.message=event.target.value
}
}
});
</script>
</body>
11.3、v-model结合checkbox
11.3.1、checkbox单选框
<body>
<!--导入 vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<!--view层 模板-->
<div id="app">
<!-- 使用 v-model可以省略name(绑定组)-->
<label for="license">
<input type="checkbox" name="sex" value="男" id="license" v-model="isAgree">同意协议
</label>
<h2>您选择的是:{{isAgree}}</h2>
<button :disabled="!isAgree">下一步</button>
</div>
<script>
let app=new Vue({
el:"#app",
data:{isAgree:false},
});
</script>
</body>
11.3.2、checkbox多选框
<body>
<!--导入 vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<!--view层 模板-->
<div id="app">
<!-- 使用 v-model可以省略name(绑定组)-->
<label for="license">
<input type="checkbox" name="sex" value="男" id="license" v-model="isAgree">同意协议
</label>
<h2>您选择的是:{{isAgree}}</h2>
<button :disabled="!isAgree">下一步</button>
<br>
<input type="checkbox" value="唱" v-model="hobby">唱
<input type="checkbox" value="跳" v-model="hobby">跳
<input type="checkbox" value="rap" v-model="hobby">rap
<input type="checkbox" value="篮球" v-model="hobby">篮球
<h2>我的爱好是:{{hobby}}</h2>
</div>
<script>
let app=new Vue({
el:"#app",
data:{
isAgree:false,
hobby:[]
},
});
</script>
</body>
11.4、v-model结合select
11.4.1、选择一个
<body>
<!--导入 vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<!--view层 模板-->
<div id="app">
<select name="select" v-model="fruit" >
<option value="banana">香蕉</option>
<option value="apple">苹果</option>
<option value="peach">桃子</option>
</select>
<h2>您选择的水果是:{{fruit}}</h2>
</div>
<script>
let app=new Vue({
el:"#app",
data:{
fruit:'apple'
},
});
</script>
</body>
11.4.2、选择多个(ctrl+选择)
<body>
<!--导入 vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<!--view层 模板-->
<div id="app">
<select name="select" v-model="fruit" >
<option value="banana">香蕉</option>
<option value="apple">苹果</option>
<option value="peach">桃子</option>
</select>
<h2>您选择的水果是:{{fruit}}</h2>
<select name="select" v-model="fruits" multiple>
<option value="banana">香蕉</option>
<option value="apple">苹果</option>
<option value="peach">桃子</option>
</select>
<h2>您选择的水果是:{{fruits}}</h2>
</div>
<script>
let app=new Vue({
el:"#app",
data:{
fruit:'apple',
fruits:['apple','peach']
},
});
</script>
</body>
11.5、值绑定
<body>
<!--导入 vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<!--view层 模板-->
<div id="app">
<label v-for="item in orginHobby" for="item">
<input type="checkbox" :value="item" v-model="hobby" id="item">{{item}}
</label>
<h2>我的爱好是:{{hobby}}</h2>
</div>
<script>
let app=new Vue({
el:"#app",
data:{
hobby:[],
orginHobby:["唱","跳","rap","篮球"]
},
});
</script>
</body>
11.6、v-model修饰符
11.6.1 、lazy
- 点击回车或失去焦点时再去绑定值
<body>
<!--导入 vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<!--view层 模板-->
<!--修饰符-->
<!-- 1、lazy-->
<div id="app">
<input type="text" v-model.lazy="message" la>
<h2>输入的值{{message}}</h2>
</div>
<script>
let app=new Vue({
el:"#app",
data:{
message:'',
},
});
</script>
</body>
11.6.2 、number
- 限制输入内容为数字
<body>
<!--导入 vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<!--view层 模板-->
<!--修饰符-->
<!-- 1、lazy-->
<div id="app">
<input type="text" v-model.lazy="message" la>
<h2>输入的值{{message}}</h2>
<input type="number" v-model.number="number" >
<h2>输入的值{{number}}</h2>
</div>
<script>
let app=new Vue({
el:"#app",
data:{
message:'',
number:0
},
});
</script>
</body>
11.6.3、trim
<body>
<!--导入 vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<!--view层 模板-->
<!--修饰符-->
<div id="app">
<!-- 1、lazy-->
<input type="text" v-model.lazy="message" la>
<h2>输入的值:{{message}}</h2>
<!-- 2、number-->
<input type="number" v-model.number="number" >
<h2>输入的值:{{number}}</h2>
<!-- 3、trim-->
<input type="text" v-model.trim ="str" >
<h2>输入的值:{{str}}</h2>
</div>
<script>
let app=new Vue({
el:"#app",
data:{
message:'',
number:0,
str:''
},
});
</script>
</body>