虚拟DOM
.vue文件中的template里写的标签, 都是模板, 都要被vue处理成虚拟DOM对象, 在生成真实DOM片段, 才会渲染显示到真实DOM页面上
虚拟DOM是:本质就是一个JS对象, 保存DOM关键信息
虚拟DOM的好处:提高DOM更新的性能, 不频繁操作真实DOM, 在内存中找到变化部分, 更新真实DOM(打补丁)
_key作用:
子元素或者内容改变会 无key, 就地更新, 有key按照key比较
key值要求是:唯一不重复的字符串或者数值
key应该怎么用: 有id用id, 无id用索引
key的好处: 可以提高更新的性能
v-bind动态class: 用v-bind给标签class设置动态的值
语法:
:class="{类名: 布尔值}"
:class=“{类名: 布尔值}”, true使用, false不用
:动态style 给标签动态设置style的值
语法:
:style="{css属性: 值}"
给style赋值和class区别是:
:class="{类名: 布尔值}”, true使用, false不用
:style="{css属性名: 值}"
计算属性-computed
语法:
computed: {
"计算属性名" () {
return "值"
}
}
计算属性使用场景:当变量的值, 需要通过别人计算而得来
计算属性特点:函数内使用的变量改变, 重新计算结果返回
计算属性注意事项:计算属性名和data里名字不能重复
计算属性好处是:带缓存 。 依赖项不变, 直接从缓存取 依赖项改变。 函数自动执行并重新缓存
计算属性-完整写法
计算属性也是变量, 如果想要直接赋值, 需要使用完整写法
语法:
computed: {
"属性名": {
set(值){
},
get() {
return "值"
}
}
}
set函数和get函数什么时候执行:
set接收要赋予的值 (修改的时候执行)
get里要返回给这个计算属性具体值 (使用的时候执行)
侦听器-watch
可以侦听data/computed属性值改变
语法:
watch: {
"被侦听的属性名" (newVal, oldVal){
}
}
侦听器-深度侦听
侦听复杂类型
语法:
watch: {
"要侦听的属性名": {
deep: true, // 深度侦听复杂类型内变化
handler (newVal, oldVal) {
}
}
}
何侦听一个对象/数组 :把侦听器写成对象形式, 给handler方法和deep:true
品牌管理案例
<template>
<div id="app">
<div class="container">
<!-- 顶部框模块 -->
<div class="form-group">
<div class="input-group">
<h4>品牌管理</h4>
</div>
</div>
<!-- 数据表格 -->
<table class="table table-bordered table-hover mt-2">
<thead>
<tr>
<th>编号</th>
<th>资产名称</th>
<th>价格</th>
<th>创建时间</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr v-for="item in list" :key="item.id">
<td>{{ item.id }}</td>
<td>{{ item.name }}</td>
<!-- 如果价格超过100,就有red这个类 -->
<td :class="{ red: item.price > 100 }">{{ item.price }}</td>
<td>{{ getTime(item.time) }}</td>
<td><a href="#" @click.prevent="del(item.id)">删除</a></td>
</tr>
<tr style="background-color: #eee">
<td>统计:</td>
<td colspan="2">总价钱为: {{ allPrice }}</td>
<td colspan="2">平均价: {{ avgPrice }}</td>
</tr>
</tbody>
<!--
<tfoot >
<tr>
<td colspan="5" style="text-align: center">暂无数据</td>
</tr>
</tfoot>
-->
</table>
<!-- 添加资产 -->
<form class="form-inline">
<div class="form-group">
<div class="input-group">
<input
type="text"
class="form-control"
placeholder="资产名称"
v-model="name"
/>
</div>
</div>
<div class="form-group">
<div class="input-group">
<input
type="text"
class="form-control"
placeholder="价格"
v-model.number="price"
/>
</div>
</div>
<!-- 阻止表单提交 -->
<button class="btn btn-primary" @click.prevent="add">添加资产</button>
</form>
</div>
</div>
</template>
<script>
/*
1. 需求:铺设页面
1.1 从md复制对应的解构过来
1.2 在下载bootstrap
1.3 在mains.js 通过import 导入bootstrap 里面的css
1.4 使用v-for渲染 tr标签
1.5 使用动态 class 处理价格
2.需求:添加数据
2.1找到对应的input标签使用v-modeL实现数据的绑定v-modeL.number=:"price”
2.2找到button按钮注册click事件阻止表单的默认行为,prevent
2.3进行非空判断如果没有填写对应的数据就提示用户A 阻止代码往下执行
2.4将数据push到数组中需要构建对象处理d
2.5将输入框里面的数据重置
3.需求:点击别除按钮将数组中对应的数据别除splice()
3.1找到别除的这个a标签注册点击事件阻止默认行为.prevent传递item.id过去
3.2在methods里面定义对应的方法
3.3别除需要提示用户是否要别除
3.4使用findIndex将数据对应的下标找到
3.5使用splice方法将数组里面对应的元素别除
3.6数组里面的元素有别除了需要将tfoot显示出来v-show
3.7将数组里面的元素都别除了再来添加bug,如果数组里面有元素就取出数组的最后一个元素里面的,id属性如果没有就给一个默认的值
4.需求:将时间进行格式化处理
4.1使用npm或者yarn下载dayjs
4.2在App.vue文件里面引入dayjs
4.3需要在methods定义一个函数
4.4需要使用day5s提供的方法即可
5.需求:计算总价和均价
5.1需要去md文件里面复制对应的结果过来
5.2需要定义计算属性
6.需求:将数据存情到本地存储
6.1使用侦听器侦听到List数组的变化只要这个数组发生了改变就将数组转换为JS0N格式的字符串在存情即可
6.2List变量的数据从本地存情中取出List数据需要将其转换为数组如果没有数据需要给空数组
*/
import dayjs from "dayjs";
export default {
data() {
return {
name: "", // 名称
price: 0, // 价格
// list: [
// { id: 100, name: "外套", price: 199, time: new Date("2010-08-12") },
// { id: 101, name: "裤子", price: 34, time: new Date("2013-09-01") },
// { id: 102, name: "鞋", price: 25.4, time: new Date("2018-11-22") },
// { id: 103, name: "头发", price: 19900, time: new Date("2020-12-12") },
// ],
list:JSON.parse(localStorage.getItem('list') ) || []
};
},
methods: {
add() {
console.log(1);
if (this.name.length === 0 || this.price === 0) return alert("输入内容");
this.list.push({
id: this.list.length ? this.list[this.list.length - 1].id + 1 : 100,
name: this.name,
price: this.price,
time: new Date(),
});
this.name = "";
this.price = 0;
},
del(id) {
if (window.confirm("确定要删除吗?")) {
const index = this.list.findIndex((item) => item.id === id);
this.list.splice(index, 1);
}
},
getTime(val) {
return dayjs(val).format("YYYY--MM--DD");
},
},
computed: {
allPrice() {
//总价钱为
return this.list.reduce((sum, item) => (sum += item.price), 0);
},
avgPrice() {
//平均价 用总价/数组的长度即可
return (this.allPrice / this.list.length || 0).toFixed(2);
}
},
watch: {
list:{
deep:true,
handler(newVal){
localStorage.setItem('list',JSON.stringify(newVal))
}
}
}
}
</script>
<style >
.red {
color: red;
}
</style>
复选框案例
<template>
<div>
<span>全选:</span>
<input type="checkbox" v-model="isAll" />
<button @click="rev">反选</button>
<ul>
<li v-for="(item, index) in arr" :key="index">
<input type="checkbox" v-model="item.c" />
<span>{{ item.name }}</span>
</li>
</ul>
</div>
</template>
<script>
/*
1.需求:小选框都选中了上面的全选框也要一起选中
1.1在Li身上使用v-for指令
1.2任务名使用item.name进行替换
1.3小选框它的选中状态由item.c来决定需要通过v-modeL来绑定数据
1.4定义计算属性 isAll 需要给全选框添加
1.5 使用every 方法
2.需求:全选框的选中状态影啊小选框
2.1改造计算属性将它变成完整写法
2.2需要获取全选框的选中状态
2.3将全选框的选中状态赋值给arr里面的c属性forEach
3.需求:反选效果
3.1需要给反选按钮注册点击事件
3.2需要在methods节点处定义对应的函数
3.3需要遍历数组forEach将c属性值取反即可
*/
export default {
data() {
return {
arr: [
{
name: "猪八戒",
c: false,
},
{
name: "孙悟空",
c: false,
},
{
name: "唐僧",
c: false,
},
{
name: "白龙马",
c: false,
},
],
};
},
computed: {
isAll: {
set(val) {
// 当我们给计算属性 赋值时 set()就会被调用
this.arr.forEach((item) => (item.c = val));
},
get() {
// 如果下面的小选框 都打上勾 return 只要有一个没有打上勾 return false
//遍历数组如果数组里面的c属性都为true则返回true反之有一个为false则返 false
//every()
return this.arr.every((item) => item.c);
},
},
},
methods: {
rev(){
this.arr.forEach(item=>item.c=!item.c)
}
}
};
</script>