目录
一.条件渲染
1.v-if
写法:
(1)v-if=“表达式”
(2)v-else-if=“表达式”
(3)v-else=“表达式”
适用于:切换频率较低的场景
特点:不展示DOM元素直接被移除
注意:v-if可以和:v-else-if\v-else一起用,但邀请结构不能被打断
2.v-show
写法:v-show=“表达式”
适用于:切换频率较高的场景
特点:不展示的DOM元素未被移除,仅仅是使用样式隐藏掉
3.备注:使用v-if时,元素可能无法获取到,而使用v-show一定可以获取到
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<title>初识vue</title>
<script type="text/javascript" src="../js/vue.js">
alert("这是我的第一行JS代码")
document.write("看我出不出来")
</script>
</head>
<body>
<!-- 容器 -->
<div id="root">
<h2>{{n}}</h2>
<button @click="n++">点我加1</button>
<!-- 使用v-show做条件渲染 -->
<!-- <h2 v-show="false">hello{{name}}</h2>
<h2 v-show="1 ===1">hello{{name}}</h2> -->
<!-- 使用v-if做条件渲染 -->
<!-- <h2 v-if="false">hello{{name}}</h2>
<h2 v-if="1 ===1">hello{{name}}</h2> -->
<!-- v-else和v-else-if -->
<!-- <div v-if="n===1">A</div>
<div v-else-if="n===2">B</div>
<div v-else-if="n===3">C</div>
<div v-else>哈哈</div> -->
<template v-if="n===1">
<h2>你好</h2>
<h2>哈哈</h2>
<h2>嗯嗯</h2>
</template>
</div>
<script type="text/javascript" >
Vue.config.productionTip = false
const vm = new Vue({
el:'#root',
data:{
name:'atguigu',
a:false,
n:0
},
})
console.log(vm)
</script>
</body>
</html>
二.列表渲染
v-for指令
1。用于展示列表数据
2.语法:v-for="(item,index) in xxx" :key="yyy"
3.可遍历:数组、对象、字符串(很少)、指定次数(很少)
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<title>姓名案例</title>
<script type="text/javascript" src="../js/vue.js">
</script>
</head>
<body>
<!-- 容器 -->
<div id="root">
<!-- 遍历数组(用的多) -->
<ul>
<!-- <li v-for="p in persons" :key="p.id">
{{p.name}}-{{p.age}}
</li> -->
<li v-for="(p,index) in persons" :key="index">
{{p.name}}-{{p.age}}
</li>
</ul>
<!-- 遍历对象 -->
<ul>
<li v-for="(val,key) in car" :key="key">
{{key}}-{{val}}
</li>
</ul>
<!-- 遍历字符串(用得少) -->
<ul>
<li v-for="(char,index) in str" :key="index">
{{char}}-{{index}}
</li>
</ul>
<!-- 遍历指定次数(用得少) -->
<ul>
<li v-for="(number,index) in 5" :key="index">
{{index}}-{{number}}
</li>
</ul>
</div>
<script type="text/javascript" >
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'}
],
car:{
name:"aodiA8",
price:"70wan",
color:"black"
},
str:'hello'
}
})
</script>
</body>
</html>
in也可以改为of
最好写上小括号
三.Key原理
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<title>姓名案例</title>
<script type="text/javascript" src="../js/vue.js">
</script>
</head>
<body>
<!-- 容器 -->
<div id="root">
<!-- 遍历数组(用的多) -->
<button @click="add">增加老刘</button>
<ul>
<li v-for="(p,index) in persons" :key="index">
{{p.name}}-{{p.age}}
<input type="text">
</li>
</ul>
</div>
<script type="text/javascript" >
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'}
],
car:{
name:"aodiA8",
price:"70wan",
color:"black"
},
str:'hello'
},
methods:{
add(){
const p = {id:'004',name:'老刘',age:'21'}
this.persons.unshift(p)
}
}
})
</script>
</body>
</html>
当index作为列表渲染key,以上代码会有问题。需要改为id作为key
react和Vue中key有什么作用?(key的原理)
1.虚拟DOM中对象的标识,当数据发生变化时,Vue会根据【新数据】生成【新的虚拟DOM】
随后Vue进行【新的虚拟DOM】与【旧的虚拟DOM】的差异进行比较
2.对比规则:
(1)旧虚拟DOM中找到了与新虚拟DOM相同的key
①若虚拟DOM中内容没变,直接使用之前的真实DOM
②若虚拟DOM中内容变了,则生成新的真实DOM,随后替换掉页面之前的真实DOM
(2)旧虚拟DOM中未找到与新虚拟DOM相同的key
创建新的真实DOM,随后渲染到页面
3.用index作为key可能会引发的问题:
(1)若数据进行:逆序添加、逆序删除等破坏顺序操作:
会产生没有必要的真实DOM更新==>姐妹效果没有问题,单效率低
(2)如果结构中还有包含输入类的DOM:
会产生错误DOM更新==>界面有问题
4.开发中如何选择key?
(1)最后使用每条数据的唯一标识作为key,比如:id,手机号、身份证号、学号等唯一值
(2)如果不存在对数据的逆序添加、逆序删除等破坏性操作,仅用于渲染列表用于展示,使用index作为key是没有问题的。
四.列表过滤
1.收集用户输入
2.用用户输入进行匹配
写法1:watch
写法2:计算属性
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<title>姓名案例</title>
<script type="text/javascript" src="../js/vue.js">
</script>
</head>
<body>
<!-- 容器 -->
<div id="root">
<!-- 遍历数组(用的多) -->
<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>
<script type="text/javascript" >
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){
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.filPersons = this.persons.filter((p)=>{
return p.name.indexOf(this.keyWord)!==-1
})
}
}
})
</script>
</body>
</html>
其中watch方法需要加immediate
计算属性方法,初始化会调一次,依赖的this.keyWord发生变化时也会调用
计算属性方法更方便
五.列表排序
其中,前减后未升序,后减前为降序
let arr =[1,3,2,6,4,5]
arr.sort((a,b)=>{
return b-a
})
console.log("@@",arr)
//升序前减后,降序后减前
在computed中配置,把逻辑配在计算属性中,里面只要任何一个属性发生变化,整个计算属性都会重新计算。点击升序、降序,是在改sortType,每次修改sortType,计算属性重新计算
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<title>姓名案例</title>
<script type="text/javascript" src="../js/vue.js">
</script>
</head>
<body>
<!-- 容器 -->
<div id="root">
<!-- 遍历数组(用的多) -->
<input type="text" placeholder="请输入名字" v-model="keyWord">
<button @click="sortType =2">年龄升序</button>
<button @click="sortType =1">年龄降序</button>
<button @click="sortType =0">原顺序</button>
<ul>
<li v-for="(p,index) in filPersons" :key="index">
{{p.name}}-{{p.age}}--{{p.sex}}
</li>
</ul>
</div>
<script type="text/javascript" >
Vue.config.productionTip = false
//用computed实现
new Vue({
el:'#root',
data:{
sortType:0,
keyWord:'',
persons:[
{id:'001',name:'马冬梅',age:'30',sex:'女'},
{id:'002',name:'周冬雨',age:'31',sex:'女'},
{id:'003',name:'周杰伦',age:'18',sex:'男'},
{id:'003',name:'温兆伦',age:'19',sex:'男'}
],
},
computed:{
filPersons(){
const arr = this.filPersons = this.persons.filter((p)=>{
return p.name.indexOf(this.keyWord)!==-1
})
if(this.sortType ){
arr.sort((p1,p2)=>{
return this.sortType === 1 ? p2.age-p1.age :p1.age-p2.age
})
}
return arr
}
}
})
let arr =[1,3,2,6,4,5]
arr.sort((a,b)=>{
return b-a
})
console.log("@@",arr)
//升序前减后,降序后减前
</script>
</body>
</html>
六.Vue监测数据原理
1.更新时的一个问题
需求:点击时添加一条数据
问题:
操作1:先刷新页面,点击按钮,再打开Vue检测工具。页面没有变,Vue监测工具改变
操作2:先打开Vue监测工具,再刷新页面,点击按钮。页面没有变,Vue监测工具也没有改变
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<title>姓名案例</title>
<script type="text/javascript" src="../js/vue.js">
</script>
</head>
<body>
<!-- 容器 -->
<div id="root">
<!-- 遍历数组(用的多) -->
<button @click="updateMei">更改冬梅信息</button>
<ul>
<li v-for="(p,index) in persons" :key="index">
{{p.name}}-{{p.age}}--{{p.sex}}
</li>
</ul>
</div>
<script type="text/javascript" >
Vue.config.productionTip = false
//用computed实现
const vm = new Vue({
el:'#root',
data:{
persons:[
{id:'001',name:'马冬梅',age:'30',sex:'女'},
{id:'002',name:'周冬雨',age:'31',sex:'女'},
{id:'003',name:'周杰伦',age:'18',sex:'男'},
{id:'003',name:'温兆伦',age:'19',sex:'男'}
],
},
methods:{
updateMei(){
//奏效
//this.persons[0].name="马老师"
//this.persons[0].age="50"
//this.persons[0].sex="男"
//this.persons[0] = {id:'001',name:'马老师',age:'50',sex:'男'}//不奏效
this.persons.splice(0,1,{id:'001',name:'马老师',age:'50',sex:'男'})
}
}
})
//升序前减后,降序后减前
</script>
</body>
</html>
说明:数组没有setter和getter,对数组操作使用Vue包裹后的方法
2.Vue监测数据原理——对象
第一步对data进行加工,第二步vm._data = data。加工完就可以响应式。修改name,就会引起set调用,就重新解析模板,生成新的虚拟DOM,新旧DOM对比,更新页面
模拟一个数据监测,但是只写到了对象的单层
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<title>姓名案例</title>
<script type="text/javascript" src="../js/vue.js">
</script>
</head>
<body>
<!-- 容器 -->
<div id="root">
<!-- <h2>学校名称:{{name}}</h2>
<h2>学校地址:{{address}}</h2> -->
</div>
<script type="text/javascript" >
let data = {
name:"尚硅谷",
address:"北京"
}
//创建一个监视的实例对象,用于监视data中的属性变化
const obs = new Observer(data)
console.log(obs)
//准备一个vm实例对象
let vm ={}
vm._data = data = obs
function Observer(obj){
const keys = Object.keys(obj)
keys.forEach((k)=>{
Object.defineProperty(this,k,{
get(){
return obj[k]
},
set(val){
obj[k]=val
}
})
})
}
</script>
</body>
</html>
3.Vue.set方法
只能给data里面某一个对象追加属性,不能给data追加属性
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<title>姓名案例</title>
<script type="text/javascript" src="../js/vue.js">
</script>
</head>
<body>
<!-- 容器 -->
<div id="root">
<h2>学校名称:{{name}}</h2>
<h2>学校地址:{{address}}</h2>
<hr/>
<h2></h2>
<button @click ="addSex">添加一个性别属性,默认男</button>
<h2>姓名:{{student.name}}</h2>
<h2 v-if ="student.sex">性别:{{student.sex}}</h2>
</div>
<script type="text/javascript" >
Vue.config.productionTip = false
const vm = new Vue({
el:"#root",
data:{
name:"尚硅谷",
address:"beijing",
student:{
name:'tom',
age:{
rage:40,
sage:29
},
friends:[
{name:'jerry',age:'35'},
{name:'tony',age:36}
]
}
},
methods:{
addSex(){
//Vue.set(this.student,'sex','男')
this.$set(this.student,'sex','男')
}
}
})
</script>
</body>
</html>
说明:methods中的this指的就是Vm
4.Vue监测数据原理——数组
Vue不能监测根据数组所有值改变数据,因为数组里面每一个元素不是setter和getter实现
需求:修改数据
操作:
1.Vue包裹的数组方法,除了基本数组功能,还会解析模板......
2.set方法
七.总结Vue数据监测
1.Vue会监视data中所有层次的数据
2.如何监测对象中的数据?
通过setter实现监视,且要在new Vue时就传入要监视的数据。
(1)对象中后追加的属性,Vue默认不做响应式处理
(2)如需给后添加的属性做响应式,请使用如下API
Vue.set(target.propertyname/index/value)或
vm.$set(target.propertyname/index/value)
3.如何监测数组中的数据?
通过包裹数组更新元素的方法实现,本质就是做了两件事:
(1)调用原生对应的方法对数组进行更新
(2)重新解析模板,进而更新页面
4.在Vue修改数组中的某个元素一定要用如下方法:
(1)使用这些API:push(),shift(),unshift(),split(),sort(),reverse()
(2)VUe.set()或vm.$set()
特别注意:Vue.set()和vm.$set()不能给vm或vm的根数据对象添加属性!!!