可以计算的属性,写法是函数,使用时当做属性来使用,即类似于data中的值
函数运算后的结果(return),就是计算属性的值
多个值改变,影响一个结果的时候
逻辑简单
计算属性要求在data里面没有同名的属性
计算有缓存
this.数据变量名
中this后面的值没有发生变动时,它就不会重复进行计算。值与结果
全写形式:是一个对象,用get函数与set函数,用于在计算属性被修改时调用set函数
computed:{
fullName(){//简写---get
return this.firstName+"--"+this.lastName;
}
}
computed:{
fullName:{//全写
get(){
return this.firstName+"--"+this.lastName;
},
}
}
computed:{
fullName:{//全写
get(){
return this.firstName+"--"+this.lastName;
},
set(newvalue){
let arr=newvalue.split("--");
this.firstName=arr[0];
this.lastName=arr[1];
}
}
}
DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>title>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js">script>
head>
<body>
<div id="app">
<input type="text" v-model="firstName" />
+
<input type="text" v-model="lastName" />
=
<input type="text" v-model="fullName" />
div>
<script>
var vm = new Vue({
el: "#app",
data: {
firstName: "李",
lastName: "丽丽",
},
computed: {
// fullName(){//简写---get
// return this.firstName+"--"+this.lastName;
// }
fullName: {
//全写
get() {
return this.firstName + "--" + this.lastName;
},
set(newvalue) {
let arr = newvalue.split("--");
this.firstName = arr[0];
this.lastName = arr[1];
},
},
},
});
script>
body>
html>
DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>title>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js">script>
<style>
* {
margin: 0;
padding: 0;
}
.box {
box-sizing: border-box;
margin: 0 auto;
width: 480px;
height: 590px;
background-image: url(images/bg.png);
}
/* 按钮 */
.minus,
.add {
display: inline-block;
width: 52px;
height: 44px;
cursor: pointer;
vertical-align: middle;
background-image: url(images/sub.png);
}
.add {
background-image: url(images/add.png);
}
/* 文本框 */
.pronum,
.info {
box-sizing: border-box;
width: 40px;
height: 35px;
line-height: 35px;
background: white;
border-radius: 3px;
text-align: center;
vertical-align: middle;
}
.pronum {
display: inline-block;
}
/* 头部 */
.top {
padding: 50px 20px 0;
height: 387px;
}
.hang {
margin-bottom: 20px;
display: flex;
justify-content: space-between;
align-items: flex-start;
}
.hang .info {
box-sizing: border-box;
padding: 0 10px;
width: 260px;
color: white;
font-size: 14px;
text-align: left;
line-height: 35px;
background: #171818;
}
.bottom {
padding-top: 20px;
color: #878787;
padding-left: 50px;
line-height: 40px;
}
style>
head>
<body>
<div id="app">
<div class="box" id="computedBox">
<div class="top">
<div class="hang" v-for="item in list" :key="item.id">
<i class="minus" @click="change(item.id,'minus')">i>
<span class="pronum">{{item.count}}span>
<i class="add" @click="change(item.id,'add')">i>
<span class="info"
>单价:{{item.price}}元
小计:<em>{{(item.count*item.price).toFixed(2)}}em>元span
>
div>
div>
<div class="bottom">
商品合计:<span class="pronum">{{all.allCount}}span> 件
<br />
共花费了:<span class="pronum">{{all.allCountPrice}}span> 元
<br />
最贵商品单价:<span class="pronum">{{all.highPrice}}span> 元
div>
div>
div>
<script>
var vm = new Vue({
el: "#app",
data: {
list: [
{
id: 0,
count: 2,
price: 20,
},
{
id: 1,
count: 4,
price: 14,
},
{
id: 3,
count: 0,
price: 10,
},
{
id: 4,
count: 0,
price: 16,
},
{
id: 5,
count: 0,
price: 22,
},
],
},
methods: {
change(index, type) {
//先找到,点击的那行数据
let item = this.list.find((item) => item.id == index);
//根据传递的参数,实现 加 减
if (type == "minus") {
//减
if (item.count < 1) {
item.count = 0;
return;
}
item.count--;
} else {
//加
item.count++;
}
},
},
computed: {
// allCount(){
// // let result=this.list.reduce((res,item)=>{
// // return res+item.count;
// // },0)
// let result=0;
// this.list.forEach((item)=>{
// result+=item.count;
// })
// return result;
// },
// allCountPrice(){
// let result=0;
// this.list.forEach((item)=>{
// result+=item.count*item.price;
// })
// return result;
// },
// highPrice(){
// let arr=[0];//初始值
// this.list.forEach((item)=>{
// if(item.count>0){
// arr.push(item.price);
// }
// })
// //如果是空数组,无法比大小,所以数组要设置初始值
// return Math.max(...arr);
// },
all() {
let Cresult = 0;
let Presult = 0;
let arr = [0]; //初始值
this.list.forEach((item) => {
Cresult += item.count;
Presult += item.count * item.price;
if (item.count > 0) {
arr.push(item.price);
}
});
return {
allCount: Cresult,
allCountPrice: Presult,
highPrice: Math.max(...arr),
};
},
},
});
script>
body>
html>
watch是一个对象,它内部具体要监听到的data响应式属性名的写法是函数
一个值变化,影响到多个结果
逻辑介于 computed 和 methods 之间
必须是data里面已有的
没有缓存
只有:一个值变化,影响到多个结果,无法反推
只有watch可以监控路由($route)
全写形式:是一个对象,用于watch监听器的具体属性
之前的函数就写在handler属性里,可以用es的简写
data: {
fullName: "李-丽丽",
},
watch: {
fullName(newValue,oldValue){//简写
console.log(newValue,oldValue);
}
},
watch: {
fullName:{//全写,可以设置属性
handler(newValue,oldValue){
console.log(newValue,oldValue);
},
}
},
immediate:true
是否打开页面就立刻监控1次
data: {
fullName: "李-丽丽",
},
watch: {
fullName(newValue,oldValue){//简写
console.log(newValue,oldValue);
}
},
data: {
fullName: "李-丽丽",
},
watch: {
fullName:{//全写,可以设置属性
handler(newValue,oldValue){
console.log(newValue,oldValue);
},
immediate:true//打开页面,立刻监控1次
}
},
deep:true
是否深度监控,用于监控对象里面内容的变化
data: {
obj: {
n: {
a: 10,
},
},
},
watch: {
obj(newValue, oldValue) {
console.log(newValue, oldValue, "obj简写监控-不深层级");//只有obj.n变化时,不执行
},
"obj.n"(newValue, oldValue) {
console.log(newValue, oldValue, "obj.n简写监控-不够深层级-只具体到对象");//只有obj.n变化时,不执行
},
"obj.n.a"(newValue, oldValue) {
console.log(newValue, oldValue, "obj.n.a简写监控-深层级-具体到非对象值");//只有obj.n变化时,也执行
},
},
data: {
obj: {
n: {
a: 10,
},
},
},
watch: {
obj: {
handler(newValue, oldValue) {
console.log(newValue, oldValue, "obj全写监控-深层级deep为true");//只有obj.n变化时,也执行
},
deep: true,//为true,就可以实现深度监听
},
},
如果要监听对象的某个具体属性,可以加引号
watch: {
"obj.n.a":{//全写,可以设置属性
handler(newValue,oldValue){
console.log(newValue,oldValue);
}
}
},
DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>title>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js">script>
head>
<body>
<div id="app">
<input type="text" v-model="firstName" />
+
<input type="text" v-model="lastName" />
=
<input type="text" v-model="fullName" />
<input type="text" v-model.number="obj.n.a" />
div>
<script>
var vm = new Vue({
el: "#app",
data: {
firstName: "李",
lastName: "丽丽",
fullName: "李-丽丽",
obj: {
n: {
a: 10,
},
},
},
watch: {
// fullName(newValue,oldValue){//简写
// //console.log(newValue,oldValue);
// let arr=newValue.split("-");
// this.firstName=arr[0];
// this.lastName=arr[1];
// }
// fullName:{//全写,可以设置属性
// handler(newValue,oldValue){
// console.log("111");
// let arr=newValue.split("-");
// this.firstName=arr[0];
// this.lastName=arr[1];
// },
// immediate:true//打开页面,立刻监控1次
// }
// obj:{//全写,可以设置属性
// handler(newValue,oldValue){
// console.log(newValue,oldValue);
// },
// deep:true//默认 无法深度监控,对象里面内容的变化
// //为true,就可以实现深度监听
// }
//复杂内容监控的时候,必须加引号
// "obj.n.a": {
// //全写,可以设置属性
// handler(newValue, oldValue) {
// console.log(newValue, oldValue);
// },
// },
obj(newValue, oldValue) {
console.log(newValue, oldValue, "obj简写监控-不深层级");//不执行
},
"obj.n"(newValue, oldValue) {
console.log(newValue, oldValue, "obj.n简写监控-不够深层级-只具体到对象");//不执行
},
"obj.n.a"(newValue, oldValue) {
console.log(newValue, oldValue, "obj.n.a简写监控-深层级-具体到非对象值");//执行
},
obj: {
handler(newValue, oldValue) {
console.log(newValue, oldValue, "obj全写监控-深层级deep为true");//执行
},
deep: true,//为true,就可以实现深度监听
},
},
});
script>
body>
html>
computed
(多个值变化,影响到一个结果) 属性的结果会被缓存,除非依赖的响应式属性变化才会重新计算。他虽然是函数但主要当作属性来使用,逻辑简单。methods
方法表示一个具体的操作,主要书写业务逻辑,是函数并且以函数的方式来调用。watch
(一个值变化,影响到多个结果改变)一个对象,键是需要观察的表达式,值是对应回调函数。
computed
和methods
的结合体;watch监控自身属性变化(重新编译,性能差),只要调用就会调用回调。 vm.$watch()
watch监控路由对象(一个值变化,影响到多个结果改变),数据变化时来执行异步操作,这时watch是非常有用的。
计算属性computed的特点(多个值变化,影响到一个结果)
DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js">script>
head>
<body>
<div id="app">
<p>num1: {{num1}}p>
<p>num2: {{num2}}p>
<p>num3: {{num3}}p>
<p>num1AddNum2Methods: {{num1AddNum2Methods()}}p>
<p>num1AddNum2Computed: {{num1AddNum2Computed}}p>
<p>num1AddNum2Watch: {{num1AddNum2Watch}}p>
<button v-on:click="num1++">num1++button>
<button v-on:click="num2++">num2++button>
<button v-on:click="num3++">num3++button>
div>
<script>
let vm = new Vue({
el: "#app",
data: {
num1: 1,
num2: 2,
num3: 88,
num1AddNum2Watch: 0,
},
computed: {
num1AddNum2Computed() {
console.log("num1AddNum2Computed-computed计算属性,依赖的值变动才调用一次");
return this.num1 + this.num2;
},
},
watch: {
num1: {
handler(value) {
console.log("num1AddNum2Watch-num1-watch回调函数,监听的值变动就调用一次");
this.num1AddNum2Watch = this.num1 + this.num2;
},
immediate: true, //打开页面,立刻监控1次
},
num2: {
handler(value) {
console.log("num1AddNum2Watch-num2-watch回调函数,监听的值变动就调用一次");
this.num1AddNum2Watch = this.num1 + this.num2;
},
immediate: true, //打开页面,立刻监控1次
},
},
methods: {
num1AddNum2Methods() {
//每次更新页面的时候就会执行
console.log("num1AddNum2Methods-methods函数,页面刷新时就会触发");
return this.num1 + this.num2;
},
},
});
script>
body>
html>
过滤器使用场景:对数据进行统一处理,得到一个统一规范的结果
第一个形参就是要进行过滤处理的数据
第二及后面的形参,就是过滤器要传的参数
return 过滤器的新结果
filters: {
//局部过滤器
currency(val, a = "¥", b = 2) {
//val:过滤处理的数据
//a:过滤器函数调用传递的第一个参数
//b:过滤器函数调用传递的第二个参数
return a + val.toFixed(b);
},
},
可以使用过滤器的是 {{}} 和 v-bind,其余的指令基本都不可以
{{msg|capitalize}}
111
过滤器使用的方式为在值后面用|接上过滤器名称及传参
{{n|currency}}
{{m|currency("$",3)}}
可以给过滤器传参
{{m|currency("$",3)}}
DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>title>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js">script>
head>
<body>
<div id="app">
{{n|currency}} {{m|currency("$",3)}}
<script>
var vm = new Vue({
el: "#app",
data: {
n: 100,
m: 200,
msg: "hello",
},
filters: {
//局部过滤器
currency(val, a = "¥", b = 2) {
//val:过滤处理的数据
//a:过滤器函数调用传递的第一个参数
//b:过滤器函数调用传递的第二个参数
return a + val.toFixed(b);
},
},
});
script>
body>
html>
全局过滤器与局部过滤器
全局过滤器,项目中常用的方式。建议用全局函数代替。
Vue.filter("capitalize",function(val){//全局过滤器
let startNum=val.slice(0,1).toUpperCase();
let endNum=val.slice(1);
return startNum+endNum;
})
局部过滤器,只能在当前配置的vue实例中使用。
var vm = new Vue({
el: "#app",
filters: {
//局部过滤器
currency(val, a = "¥", b = 2) {
//val:过滤处理的数据
//a:过滤器函数调用传递的第一个参数
//b:过滤器函数调用传递的第二个参数
return a + val.toFixed(b);
},
},
});
DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>title>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js">script>
head>
<body>
<div id="app">
{{n|currency}} {{m|currency("$",3)}}
{{msg|capitalize}}
<h1 :title="msg|capitalize">111h1>
div>
<div class="appa">
{{nn|currency}} {{mm|currency("$",3)}} {{msga|capitalize}}
div>
<script>
Vue.filter("capitalize", function (val) {
//全局过滤器
let startNum = val.slice(0, 1).toUpperCase();
let endNum = val.slice(1);
return startNum + endNum;
});
var vm = new Vue({
el: "#app",
data: {
n: 100,
m: 200,
msg: "hello",
},
filters: {
//局部过滤器
currency(val, a = "¥", b = 2) {
//val:过滤处理的数据
//a:过滤器函数调用传递的第一个参数
//b:过滤器函数调用传递的第二个参数
return a + val.toFixed(b);
},
},
});
var vma = new Vue({
el: ".appa",
data: {
nn: 101,
mm: 202,
msga: "world",
},
});
script>
body>
html>
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
head>
<body>
<div id="app">
<div>msg: {{msg}}div>
<div>obj: {{obj}}div>
<div>number: {{number}}div>
<button @click="handleAdd">组件内number++button>
div>
body>
<button id="addNumber">组件外number++button>
<button id="handleDestroy">卸载vue组件button>
html>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js">script>
<script>
let vm = new Vue({
name: "componentName",
el: "#app",
data: {
msg: "data-msg-李",
obj: {
name: "lili",
},
number: 5,
},
methods: {
handleAdd() {
console.log(`vue实例内部this-->`, this.number, this);
this.number++;
},
},
beforeCreate() {
console.log("初始化前beforeCreate: ", this, this.$attrs, [
this.$nextTick,
this.$emit,
this.$slots,
]); //已经可以访问this及它的一些实例方法如$nextTick及$attrs等了,但this里面的数据和方法还不能访问;
// debugger;
// console.log("beforeCreate---this.$el: ", this.$el); //还没生成,也没赋值;
// console.log("beforeCreate---this.$data: ", this.$data); //还没生成,也没赋值;
// console.log("beforeCreate---this.msg: ", this.msg); //还没生成,也没赋值;
// 一般这个阶段用不着,一般也就不与模板有数据的ajax时用到,如统计类ajax、数据埋点、单纯地操作全局变量之类的。
//this.obj["ageb"]=182;//报错
},
created() {
console.log("初始化后created: ", this.$el); //已经生成,也没赋值;
// console.log("created: ", this.$data); //已经生成,已经赋值;
console.log("created: ", this.msg); //已经生成,已经赋值;
// 一般用于发送与页面相关的ajax。
this.obj["createdAge"] = 2;
},
beforeMount() {
console.log("挂载前beforeMount: ", this.$el); //已经生成,就是el对应的模版变成了虚拟DOM对象了,已经赋值,但没把模版替换到页面上;
this.obj["beforeMountAge"] = 3;
},
mounted() {
console.log("挂载后mounted: ", this.$el);
this.obj["mountedAge"] = 4;
},
beforeUpdate() {
console.log("更新前beforeUpdate: ", this.number, this.$el.innerHTML);
},
updated() {
console.log("更新后updated: ", this.number, this.$el.innerHTML);
},
beforeDestroy() {
console.log("卸载前beforeDestroy: ", this.number);
},
destroyed() {
console.log("卸载后destroyed: ", this.number, this.number);
},
});
let addNumber = document.querySelector("#addNumber");
addNumber.onclick = function () {
// vm.number++;
vm.handleAdd()
console.log(`vue实例外部vm.number-->`, vm.number, vm);
};
let handleDestroy = document.querySelector("#handleDestroy");
handleDestroy.onclick = function () {
vm.$destroy();
};
script>