class,style绑定
字符串写法,类名不确定
<div id="root">
<div class="basic" :class="mood" @click="changeMood"></div>
</div>
<script>
const vm = new Vue({
el: '#root',
data: {
mood: 'sad'
},
methods: {
changeMood() {
this.mood = 'happy'
}
}
})
</script>
实现点击随机切换颜色
<div id="root">
<div class="basic" :class="mood" @click="changeMood"></div>
</div>
<script>
const vm = new Vue({
el: '#root',
data: {
mood: 'sad'
},
methods: {
changeMood() {
const arr = ['sad', 'happy', 'normal']
const index = Math.floor(Math.random() * 3)
this.mood = arr[index]
}
}
})
</script>
数组写法:类名不确定,个数不确定
<div class="basic" :class="classArr">{{name}}</div>
</div>
<script>
const vm = new Vue({
el: '#root',
data: {
name: 'lyt',
mood: 'sad',
classArr: ['atlyt1', 'atlyt2', 'atlyt3']
}
})
</script>
对象写法:个数确定,名字确定
<div class="basic" :class="classObj">{{name}}</div>
</div>
<script>
const vm = new Vue({
el: '#root',
data: {
name: 'lyt',
mood: 'sad',
classObj: {
atlyt1: false,
atlyt2: false
}
}
})
style绑定
<div class="basic" :style="{fontSize: fsize+'px'}">{{name}}</div>
</div>
<script>
const vm = new Vue({
el: '#root',
data: {
name: 'lyt',
mood: 'sad',
// classArr: ['atlyt1', 'atlyt2', 'atlyt3'],
// classObj: {
// atlyt1: false,
// atlyt2: false
// },
fsize: 40
}
})
对象写法
<div class="basic" :style="styleObj">{{name}}</div>
</div>
<script>
const vm = new Vue({
el: '#root',
data: {
name: 'lyt',
mood: 'sad',
// classArr: ['atlyt1', 'atlyt2', 'atlyt3'],
// classObj: {
// atlyt1: false,
// atlyt2: false
// },
styleObj: {
fontSize: '40px'
}
}
})
条件渲染
v-show
结构还在
v-if
结构直接没了
所以v-if用于变化没那么频繁的
多个判断:else-if, else
<div v-if="n===1">第一个</div>
<div v-else-if="n===2">第二个</div>
<div v-else-if="n===3">第三个</div>
template和v-if配合使用
<template v-if="n===1">
<h2>你好</h2>
<h2>lyt</h2>
<h2>hhhh</h2>
</template>
列表渲染
遍历数组:(用得多)
v-for
:key 作为标识
<div id="root">
<ul>
<li v-for="p in persons" :key="p.id">
{{p.name}}-{{p.age}}</li>
</ul>
</div>
<script>
new Vue({
el: '#root',
data: {
persons: [
{ id: '001', name: '张三', age: '18' },
{ id: '002', name: '李四', age: '19' },
{ id: '003', name: '王五', age: '20' }
]
}
})
</script>
也可这样写
<ul>
<li v-for="(p,index) in persons" :key="index">
{{p.name}}-{{p.age}}</li>
</ul>
遍历对象:
<ul>
<li v-for="(value,k) of car" :key="k">
{{k}}-{{value}}
</li>
</ul>
car: {
name: '奥迪A8',
price: '70万',
color: '黑色'
}
遍历字符串:
<ul>
<li v-for="(char,index) of str" :key="index">
{{index}}-{{char}}
</li>
</ul>
str: 'hello'
遍历指定次数(用得少)
<ul>
<li v-for="(number,index) of 5" :key="index">
{{index}}-{{number}}
</li>
</ul>
key的原理
用index作为key
用p.id (数据的唯一标识)
对比规则:内容不一样就用新的,一样就用旧的
对数据破坏顺序,用index就可能出问题
如果不写key,自动用遍历时的index作为key,所以不写key也会错
列表的过滤
1.另找一个数组来存数据,不要把原数组删掉
2.indexOf(' ')==0 ,所有数据都可以有
所以要用immadiate:true来先执行一次,才会有数据显示
watch实现:
<body>
<div id="root">
<input type="text" placeholder="请输入名字" v-model="keyWord">
<ul>
<li v-for="(p,index) in filPersons" :key="p.id">
{{p.name}}-{{p.age}}-{{p.sex}}
</li>
</ul>
</div>
<script>
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: '004', name: '温兆伦', age: '21', sex: '男' }
],
filPersons: []
},
watch: {
keyWord: {
immediate: true,
handler(val) {
this.filPersons = this.persons.filter((p) => {
return p.name.indexOf(val) !== -1
})
}
}
}
})
</script>
用computed:
<script>
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: '004', name: '温兆伦', age: '21', sex: '男' }
]
},
computed: {
filPersons() {
return this.persons.filter((p) => {
return p.name.indexOf(this.keyWord) !== -1
})
}
}
})
</script>
列表排序
sortType在计算属性里面
计算属性改变,filPersons就会重新赋值
太妙了!!!!!!多看几遍!
<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="p.id">
{{p.name}}-{{p.age}}-{{p.sex}}
</li>
</ul>
</div>
<script>
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: '004', name: '温兆伦', age: '19', sex: '男' }
]
},
computed: {
filPersons() {
const arr = 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
}
}
})
</script>
vue本身就有默认的监视
配置watch就会用到
检测数据的原理:
this.persons[0] = { id: '001', name: '张老师', age: '50' }
先点了更新,但是没更新
自己模拟一个监视,死循环:
模拟数据代理:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../js/vue.js"></script>
</head>
<body>
<script>
let data = {
name: '中南民族大学',
address: '北京',
a: {
b: 1
}
}
const obs = new Observer(data)
console.log(obs)
//创建一个监视实例对象用于监视data中属性变化
//准备一个vm实例对象
let vm = {}
vm._data = data = obs
//底层构造函数,收到一个对象作为参数
function Observer(obj) {
const keys = Object.keys(obj)
//keys是一个数组,有obj的属性
keys.forEach((k) => {
//this是实例对象,k是其中遍历到的一个属性
Object.defineProperty(this, k, {
get() {
return obj[k]
},
set(val) {
console.log(`${k}更改了,我要去解析模板生成虚拟DOM`)
obj[k] = val
}
})
})
}
</script>
</body>
</html>
把obs给vm实例对象,同时也给data,这样这三个都相等
修改值:data和vm._data都绑定在obs上了,只要它们有变化obs调用set,三个都会同时改变
Vue更完善的地方:
可以直接vm.name(做了数据代理)
对象中还有对象,a里面的b没有set
递归,想有多少个对象,就有多少个set
数组的数据监测
但是这样写,在页面中不会有显示,也就是在这个时候添加属性是没有用的
用Vue.set(): 有响应了
vm.$set()
回忆数据代理
所以可以简写