v-for不会移动DOM,而是尝试复用,就地更新,如果需要v-for移动DOM,你需要用特殊属性 key 来提供一个排序提示
新DOM里数据的key存在,去旧的虚拟DOM结构里找到key标记的标签,复用标签
新DOM里数据的key存在,去旧的虚拟DOM结构里没有找到key标记的标签,创建
旧DOM结构的key,在新的DOM结构里没有, 就移除key所在的标签
一个数据,依赖另外一些数据计算而来的结果
语法
computed:{
'计算属性名'(){
return 值
}
}
计算属性是基于他们的依赖项的值结果进行缓存的,只要依赖的变量不变,就直接从缓存取结果
计算属性也是变量,如果想要直接赋值,需要使用完整写法
语法
computed:{
'属性名':{
set(值){ //给属性赋值触发set方法
},
get(){ //使用属性的值触发get方法
}
}
}
可以侦听data/computed属性值改变
语法
watch:{
'被侦听的属性名'(newValue,oldValue){
}
}
代码
想要侦听一个属性变化,使用侦听属性watch
侦听复杂类型,或者立即执行侦听函数
语法
watch:{
'被侦听的属性名':{
immediate:true,//立即执行
deep:true, //深度侦听复杂类型变化
handler(newValue,oldValue){
}
}
}
<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 src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<!--1处理日期的工具模块 -->
<script src="http://cdn.staticfile.org/moment.js/2.24.0/moment.min.js"></script>
<style>
#app {
width: 600px;
margin: 50px auto;
}
.tb {
border-collapse: collapse;
width: 100%;
}
.tb th {
background-color: aquamarine;
color: white;
}
.tb td,
.tb th {
padding: 5px;
border: 1px solid black;
text-align: center;
}
.col {
color: red;
}
</style>
</head>
<body>
<div id="app">
<!--
1:数据
- 把默认数据显示在表格上
- 注意资产超过100的, 都用红色字体标记出来
2:增
- 实现表单数据新增进表格
- 判断用户输入是否为空给提示
步骤:
- 新增按钮 绑定点击事件
- 给表单v-model 绑定value变量 收集用户输入内容
- 判断用户内容是否符合规定
- 添加数据到数组中
3:删除
- 点击删除按钮,删除数据
- 删除没数据,提示暂无数据
步骤:
- 删除按钮 绑定点击事件
- 给事件方法传id
- 通过id 找到对象的数据删除
- 删除完毕 暂无数据的tr显示
4:数据缓存
把数据实时同步到本地缓存
- watch侦听list变化,把最新的数组list转成json字符串存入到localStorage本地
- data里默认把list变量从本地取值,如果取不到赋给 默认的空数组
-->
<table class="tb">
<tr>
<th>编号</th>
<th>名称</th>
<th>价格</th>
<th>创建时间</th>
<th>操作</th>
</tr>
<tr v-for="obj in list" :key="obj.id">
<td>{{obj.id}}</td>
<td>{{obj.name}}</td>
<td :class="{'col':obj.price>100}">{{obj.price}}</td>
<td>{{obj.time}}</td>
<td>
<button @click="delFn(obj.id)">删除</button>
</td>
</tr>
<tr v-if="list.length===0">
<td colspan="5">暂无数据</td>
</tr>
</table>
<p>
<label for=""> 名称:<input type="text" v-model="name" /> </label>
<label for="">价格:<input type="text" v-model.number="price" /></label>
<button @click="addFn">新增</button>
</p>
</div>
</body>
<script>
var vm = new Vue({
el: '#app',
data: {
name: '',
price: 0,
// list: [
// { id: 100, name: '外套', price: 199, time: new Date('2022-8-30') },
// { id: 101, name: '裤子', price: 299, time: new Date('2022-9-02') },
// { id: 102, name: '鞋', price: 89, time: new Date('2022-9-14') },
// { id: 103, name: '头套', price: 23, time: new Date('2022-9-18') },
// ],
list: JSON.parse(localStorage.getItem('plist') || '[]'),
},
methods: {
// 新增
addFn () {
// 判断用户输入是否为空给提示
if (this.name.trim().length === 0 || this.price == 0) {
return alert('不能为空')
}
// 把值以对象形式插入list
this.list.push({
// 数组最后一个对象的id+1 为新对象的id值
id:
this.list.length == 0
? 100
: this.list[this.list.length - 1].id + 1,
name: this.name,
price: this.price,
time: new Date(),
})
},
// 删除
delFn (id) {
// 根据id找到这条数据在数组中的下标
let index = this.list.findIndex((obj) => obj.id === id)
this.list.splice(index, 1)
},
},
watch: {
list: {
handler () {
// 存入本地
localStorage.setItem('plist', JSON.stringify(this.list))
},
deep: true,
},
},
})
</script>
</html>