目录
一绑定样式
绑定class样式
写法:class="xxx“,xxx可以是字符串、对象、数组。
(1)字符串写法适用于:类名不确定,要动态获取。
(2)数组写法适用于:要绑定多个样式,个数不确定,名字也不确定。
(3)对象写法适用于:要绑定多个样式,个数确定,名字也确定,但不确定用不用。
绑定style样式
:style="{fontSize: xxx}" 其中xx是动态值。
:style="[a,b]"其中a、b是样式对象。
<!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>Document</title>
<style>
.basic{
width:400px;
height:100px;
border:1px solid black ;
}
.happy{
background-color: aqua;
border:1px solid yellow ;
}
.sad{
background-color: silver;
border:1px solid green ;
}
.normal{
background-color: pink;
border:1px solid red ;
}
.a1{
background-color: palegoldenrod;
border:1px solid chocolate ;
}
.a2{
width:400px;
height:100px;
background-color: palegreen;
border:1px solid bisque ;
}
.a3{
width:400px;
height:100px;
background-color: powderblue;
border:1px solid aquamarine ;
}
</style>
<script type="text/javascript" src="..\vue.js"></script>
</head>
<body>
<div id="root">
<!-- 绑定class样式--字符串写法,适用于:样式的类名不确定,需要动态指定.-->
<div class="basic":class="mood" @click="changeMood">{{name}}</div>
<br/><br/>
<!--.绑定class样式--数组写法,适用于:要绑定的样式个数不确定、名字也不确定.-->
<div class="basic":class="sz">{{name}}</div><br><br>
<!--也可以写成<div class="basic" :class="['a1','a2','a3']" >{{name}}</div>
但是这样写vue不保存a1、a2、a3就无法动态切换-->
<!--
<div class="basic":class="[a1,a2,a3]" >{{name}}</div>
就需要在data中加入a1:'a1',a2:'a2',a3:'a3'
加引号就是字符串值,不加引号就需要在data中配备这三个变量的值
-->
<!--绑定class样式--对象写法, 适用于: 要绑定的样式个数确定、名字也确定,但要动态决定用不用。-->
<div class="basic" :class="classObj">{{name}}</div><br><br>
<!-- <div class="basic" :class="{a1:a,a2:b}">{{name}}</div>
再在data中加a:flase,b:false-->
<!--绑定style样式:对象写法 -->
<!--<div class="basic" :style="{fontSize:fsize+'px'}">{{name}}</div>-->
<div class="basic" :style="styleObj">{{name}}</div><br><br>
<!--绑定style样式:数组写法 -->
<div class="basic" :style="styleArr">{{name}}</div>
</div>
</body>
<script>
Vue.config.productionTip=false
const vm=new Vue({
el:'#root',
data:{
name:'小宝',
mood:'normal',
//vm.sz.shift()可以依次移除sz中的元素
//vm.sz.push('a1')向sz中推入a1
sz:['a1','a2','a3'],
classObj:{
a1:false,
a2:false,
},
// fsize:40
styleObj:{
fontSize:'40px',
backgroundColor:'red',
color:'yellow'
},
styleArr:[
{
fontSize:'20px',
backgroundColor:'gray',
},
{
color:'blue'
}
]
},
methods:{
changeMood(){
const arr=['happy','sad','normal']
const index=Math.floor(Math.random()*3)
this.mood=arr[index]
}
},
})
</script>
</html>
二 条件渲染
v-if
写法:
(1).v-if="表达式”
(2).v-else-if="表达式”
(3).v-else="表达式”
适用于:切换频率较低的场景。
特点:不展示的DOM元素直接被移除。
注意: v-if可以和:v-else-if、v-else起使用, 但要求结构不能被“打断”。
v- show
写法: v-show=" 表达式”
适用于:切换频率较高的场景。
特点:不展示的DOM元素未被移除,仅仅是使用样式隐藏掉
注意:使用v-if的时,元素可能无法获取到,而使用v-show 定可以获取到。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>条件渲染</title>
<script type="text/javascript" src="..\vue.js"></script>
</head>
<body>
<!-- 准备好一个容器-->
<div id="root">
<h2>当前的值是:{{n}}</h2>
<button @click="n++">点我n+1</button>
<!-- 使用v-show做条件渲染-->
<!-- <h2 v-show="a">欢迎{{name}}</h2> -->
<!-- <h2 v-show="1 === 1">欢迎来到{{name}}</h2> -->
<!--使用v-if做条件渲染,比v-show彻底,结构都没了-->
<!--<h2 v-if="false">欢迎{{name}}</h2> -->
<!-- <h2 v-if="1 === 1">欢迎{{name}}</h2> -->
<!-- v-else和v-else-if(v-show没有v-else-show结构)-->
<!-- <div v-if="n === 1" >Angular</div>
<div v-else-if="n === 2">React< /div>
<div v-else-if="nI=== 3">Vue< /div>
<div v-else>哈哈</div> -->
<!-- v-if与template的配合使用,template不会影响结构,也不能和v-show一起使用 -->
<template v-if="n === 1">
<h2>你好</h2>
<h2>小宝宝</h2>
<h2>麻辣烫</h2>
</template>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false
const vm = new Vue({
el: ' #root ',
data:{
name:'小宝宝',
//a:false,
n:0
}
})
</script>
</html>
三 列表渲染
v- for指令
1.用于展示列表数据
2.语法: v-for="(item, index) in xxx" :key="yy"
3.可遍历:数组、对象、字符串(用的很少)、指定次数(用的很少)
<!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>Document</title>
<script type="text/javascript" src="..\vue.js"></script>
</head>
<body>
<div id="root">
<!--遍历数组-->
<h2>遍历人员列表</h2>
<ul>
<!--也可以:<li v-for="(p,index) of persons" :key="p.id">-->
<li v-for="(p,index) in persons" :key="index">
{{p.name}}-{{p.age}}
</li>
</ul>
<!--遍历对象-->
<h2>遍历麻辣信息</h2>
<ul>
<li v-for="(value,k) of mala" :key="k">
{{k}}-{{value}}
</li>
</ul>
<!--遍历字符串-->
<h2>遍历字符串</h2>
<ul>
<li v-for="(char,index) of str" :key="index">
{{char}}-{{index}}
</li>
</ul>
<!--遍历指定次数-->
<h2>遍历指定次数</h2>
<ul>
<li v-for="(number,index) of 5" :key="index">
{{index}}-{{number}}
</li>
</ul>
</div>
</body>
<script>
Vue.config.productionTip=false
new Vue({
el:'#root',
data:{
persons:[
{id:'001',name:'张三',age:18},
{id:'002',name:'李四',age:19},
{id:'003',name:'王五',age:20},
],
mala:{
name:'辣条王子',
price:'5块',
color:'黑色'
},
str:'Wow'
}
})
</script>
</html>
面试题: react、 vue中的key有什么作用? (key的内部原理)
1.虚拟DOM中key的作用:
key是虚拟DOM对象的标识,当数据发生变化时,Vue会根据[新数据]生成[新的虚拟DOM],
随后Vue进行[ 新虚拟DOM]与[旧虚拟DOM]的差异比较,比较规则如下:
2.对比规则:
(1).旧虚拟DOM中找到了与新虚拟DOM相同的key:
1)若虚拟DOM中内容没变,直接使用之前的真实DOM!
2)若虚拟DOM中内容变了,则生成新的真实DOM,随后替换掉页面中之前的真实DOM。
(2)旧虚拟DOM中未找到与新虚拟DOM相同的key
创建新的真实DOM,随后渲染到到页面。
3.用index作为key可能会引发的问题:
(1)若对数据进行:逆序添加、逆序删除等破坏顺序操作:
会产生没有必要的真实DOM更新==>界面效果没问题,但效率低。
(2).如果结构中还包含输入类的DOM:
会产生错误DOM更新==> 界面有问题。
4.开发中如何选择key?:
(1)最好使用每条数据的唯一标 识作为key,比如id、手机号、身份证号、学号等唯一值。
(2)如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表用于展示,
使用index作为key是没有问题的。
四 列表的过滤
<!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>Document</title>
<script type="text/javascript" src="..\vue.js"></script>
</head>
<body>
<div id="root">
<h2>遍历人员列表</h2>
<input type="text" placeholder="请输入名字" v-model="keyWord">
<ul>
<li v-for="(p,index) in filPersons" :key="index">
{{p.name}}-{{p.age}}-{{p.sex}}
</li>
</ul>
</div>
</body>
<script>
Vue.config.productionTip=false
//用watch实现
/* new Vue({
el:'#root',
data:{
keyWord:'',
persons:[
{id:'001',name:'亚梦',age:18,sex:'女'},
{id:'002',name:'亚索',age:19,sex:'男'},
{id:'003',name:'鲁班',age:20,sex:'男'},
{id:'003',name:'鲁班大师',age:21,sex:'男'}
],
filPersons:[]
},
watch:{
keyWord:{
immediate:true,
handler(val){
//filter不更改原数组
this.filPersons=this.persons.filter((p)=>{
return p.name.indexOf(val)!=-1
})
}
}
}
})*/
//用computed实现
new Vue({
el:'#root',
data:{
keyWord:'',
persons:[
{id:'001',name:'亚梦',age:18,sex:'女'},
{id:'002',name:'亚索',age:19,sex:'男'},
{id:'003',name:'鲁班',age:20,sex:'男'},
{id:'003',name:'鲁班大师',age:21,sex:'男'}
], },
computed:{
filPersons(){
return this.persons.filter((p)=>
{
return p.name.indexOf(this.keyWord)!=-1
})
}
}
})
</script>
</html>
五 列表排序
<!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>Document</title>
<script type="text/javascript" src="..\vue.js"></script>
</head>
<body>
<div id="root">
<h2>遍历人员列表</h2>
<input type="text" placeholder="请输入名字" v-model="keyWord">
<button @click="sortType=1">升序排列</button>
<button @click="sortType=2">降序排列</button>
<button @click="sortType=0">原顺序</button>
<ul>
<li v-for="(p,index) in filPersons" :key="p.id">
{{p.name}}-{{p.age}}-{{p.sex}}
</li>
</ul>
</div>
</body>
<script>
Vue.config.productionTip=false
new Vue({
el:'#root',
data:{
keyWord:'',
sortType:0,
persons:[
{id:'001',name:'亚梦',age:18,sex:'女'},
{id:'002',name:'亚索',age:29,sex:'男'},
{id:'003',name:'鲁班',age:8,sex:'男'},
{id:'003',name:'鲁班大师',age:21,sex:'男'}
], },
computed:{
filPersons(){
const a=this.persons.filter((p)=>
{
return p.name.indexOf(this.keyWord)!=-1
})
if(this.sortType){
a.sort((p1,p2)=>{
return this.sortType===1?p1.age-p2.age:p2.age-p1.age
})
}
//记得要写返回值
return a
}
}
})
</script>
</html>
六 Vue监视数据
Vue监视数据的原理:
1.vue会监视data中所有层次的数据。
2.如何监测对象中的数据?
通过setter实现监视,且要在newVue时就传入要监测的数据。
(1).对象中后追加的属性,Vue默认不做响应式处理
(2).如需给后添加的属性做响应式,请使用如下API:
Vue.set(target, propertyName/index, value) 或
vm . $set(target, propertyName/ index, value )
3.如何监测数组中的数据?
通过包裹数组更新元素的方法实现,本质就是做了两件事:
(1).调用原生对应的方法对数组进行更新。
(2).重新解析模板,进而更新页面。
4.在Vue修改数组中的某个元素一定要用如 下方法:
1.使用这些API:push()、pop()、 shift()、 unshift()、 splice()、 sort()、 reverse()
2.Vue.set()或vm.$set()
特别注意: Vue.set() 和vm.$set() 不能给vm或vm的根数据对象添加属性!
看懂下面例子就基本掌握上面这些话:
<!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>Document</title>
<script type="text/javascript" src="..\vue.js"></script>
</head>
<body>
<div id="root">
<button @click=" students.age++">年龄+1岁</button> <br/>
<button @click="addSex">添加性别属性,默认值:男</button> <br/>
<button @click="addFriend">在列表首位添加个朋友</button> <br/>
<button @click="updateFirstFriendName">修改第一个朋友的名字为:张三</button> <br/>
<button @click="addHobby">添加一个爱好</button> <br/>
<button @click="updateHobby">修改第一个爱好为:购物</button> <br/>
<button @click="removePlayGames">过滤掉爱好中的打游戏</button> <br/>
<h3>姓名: {{ students. name}}</h3>
<h3>年龄: {{students. age}}</h3>
<h3 v-if="students.sex">学生性别:{{students.sex}}</h3>
<h3>爱好: </h3>
<ul>
<li v-for="(h,index) in students.hobby" :key=" index">
{{h}}
</li>
</ul>
<h3>朋友们: </h3>
<ul>
<li v-for="(f, index) in students.friends" :key=" index">
{{f.name}}--{{f.age}}
</li>
</ul>
</div>
</body>
<script>
Vue.config.productionTip=false
const vm=new Vue({
el:'#root',
data:{
students:{
name:'tom',
age:18,
hobby:[
/*在控制台输入vm._data.students.hobby.push/pop()可以向末尾添加/删除一个元素
此外unshift,shift,splice,sort,reverse都可以用,上述 等同于
vm.students.hobby.push/pop()
Vue将被侦听的数组的变更方法进行了包裹,所以它们也将会触发视图更新。以上为被包裹过的方法
*/
/*通过Vue.set(target,propertyName/index,value)也可以实现替换
具体用法如Vue.set(vm.students.hobby,0,'上课')
*/
'打游戏','看小说','睡觉'
],
friends:[
//数组中的name、age也是响应式的,有为它们服务的set、get
{name:'Eric',age:39},
{name:'Mike',age:29}
]
}
},
methods:{
addSex(){
/*Vue.set(target,propertyName/index,value)对象不能是Vue实例,或者Vue实例的根数据对象。
向响应式对象中添加一个property,并确保这个新property同样是响应式的,且触发视图更新。
它必须用于向响应式对象上添加新property,因为Vue无法探测普通的新增propety
*/
// Vue.set(this.students,'sex','男')
// vm.$set(this.students,'sex','男')
this.$set(this.students,'sex','男')
},
addFriend(){
this.students.friends.unshift({name:'Jenny',age:25})
},
updateFirstFriendName(){
//不能直接索引操作数组元素但是可以操作数组元素(对象)里的属性,即数组元素是对象时,该对象里的属性有set、get方法
this.students.friends[0].name='张三'
// this.students.friends[0].age=50
},
addHobby(){
this.students.hobby.push('蹦迪')
},
updateHobby(){
//this.students.hobby.splice(0,1,'购物')
// Vue.set(this.students.hobby,0,'购物')
this.$set(this.students.hobby,0,'购物')
},
removePlayGames(){
//非vue管理的函数最好写成普通函数
this.students.hobby=this.students.hobby.filter((h)=>{
return h!='打游戏'
})
}
}
})
</script>
</html>
补充:
变更方法,顾名思义,会变更调用了这些方法的原始数组。怊比之下,也有非变更方法,例如
filter()、concat()和 slice() 。它们不会变更原始数组,而总是返回一个新数组。当使用非变更方法时,可以用新数组替换旧数组: