VUE学习(二)、计算属性vs侦听属性——基于案例的对比

VUE学习(二)、计算属性vs侦听属性——基于案例的对比

一、姓名案例——计算属性

1、插值语法实现

<body>
	
	<div id="root">
		
		
		姓:<input type="text" v-model="firstName"> <br/><br/>
		名:<input type="text" v-model="lastName"> <br/><br/>
		全名:<span>{{firstName}}--{{lastName}}span>
	div>
body>

<script type="text/javascript">
	Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。

	new Vue({
		el:'#root',
		data:{
			firstName:'张',
			lastName:'三'
		}
	})
script>

2、methods实现

<body>
	
	<div id="root">
		姓:<input type="text" v-model="firstName" /> <br /><br />
		名:<input type="text" v-model="lastName" /> <br /><br />
		全名:<span>{{fullName()}}span>
		
	div>
body>

<script type="text/javascript">
	Vue.config.productionTip = false; //阻止 vue 在启动时生成生产提示。

	new Vue({
		el: "#root",
		data: {
			firstName: "张",
			lastName: "三"
		},
		methods: {
			fullName() {
				//因为页面数据会发生变化,所这个函数会被多次调用
				console.log("fullName被调用了");
				return this.firstName + "-" + this.lastName;
			}
		}
	});
script>

3、计算属性实现

<body>
	
	
	<div id="root">
		姓:<input type="text" v-model="firstName" /> <br /><br />
		名:<input type="text" v-model="lastName" /> <br /><br />
		测试:<input type="text" v-model="x" /> <br /><br />
		
		全名:<span>{{fullName}}span> <br /><br />
		
	div>
body>

<script type="text/javascript">
	Vue.config.productionTip = false; //阻止 vue 在启动时生成生产提示。

	const vm = new Vue({
		el: "#root",
		data: {
			firstName: "张",
			lastName: "三",
			x: "你好"
		},
		methods: {
			demo() {}
		},
		//计算属性
		computed: {
			//定义一个fullName属性并给这个属性添加了set 和 get两个方法
			fullName: {
				//get有什么作用?当有人读取fullName时,get就会被调用,且返回值就作为fullName的值
				//get什么时候调用?1.初次读取fullName时。
				//                2.所依赖的数据发生变化时。
				get() {
					console.log("get被调用了");
					// console.log(this) //此处的this是vm
					return this.firstName + "-" + this.lastName;
				},
				//set什么时候调用? 当fullName被修改时。如果不定义则这个计算属性的值不能被修改
				set(value) {
					console.log("set fullName=", value);
					const arr = value.split("-");
					this.firstName = arr[0];
					this.lastName = arr[1];
				}
			},
			//fullName:{}在属性fullName中定义了两个方法set,get
			//当调用fullName属性时会自动调用 set 或 get

			//而 fullName() 是一个函数属性,调用时相当于直接调用一个方法,唯一不同的是
			//插值语法调用computed中的属性或方法时不需要加上 () ,而 methods中的方法在插值语法中调用时需要 加上 ()

			//如果只需要get方法则可以使用这个简写,否则别简写
			/* fullName(){
				console.log('get被调用了')
				return this.firstName + '-' + this.lastName
			} */
		}
	});
script>

三个案例都能实现如下功能:
VUE学习(二)、计算属性vs侦听属性——基于案例的对比_第1张图片

二、天气案例——侦听属性

1、methods实现

<body>
	
	<div id="root">
		<h2>今天天气很{{info}}h2>
		
		
		<button @click="changeWeather">切换天气button>
	div>
body>

<script type="text/javascript">
	Vue.config.productionTip = false; //阻止 vue 在启动时生成生产提示。

	const vm = new Vue({
		el: "#root",
		data: {
			isHot: true
		},
		computed: {
			info() {
				return this.isHot ? "炎热" : "凉爽";
			}
		},
		methods: {
			changeWeather() {
				this.isHot = !this.isHot;
			}
		}
	});
script>

2、侦听器实现

<body>
	
	
	<div id="root">
		<h2>今天天气很{{info}}h2>
		<button @click="changeWeather">切换天气button>
	div>
body>

<script type="text/javascript">
	Vue.config.productionTip = false; //阻止 vue 在启动时生成生产提示。

	const vm = new Vue({
		el: "#root",
		data: {
			isHot: true
		},
		computed: {
			info() {
				return this.isHot ? "炎热" : "凉爽";
			}
		},
		methods: {
			changeWeather() {
				this.isHot = !this.isHot;
			}
		}
		/* watch:{
			//监视isHot
			isHot:{
				immediate:true, //初始化时让handler调用一下
				//handler什么时候调用?当isHot发生改变时。
				handler(newValue,oldValue){
					console.log('isHot被修改了',newValue,oldValue)
				}
			}
		} */
	});

	//侦听器(不能手动调用)专门侦听数据变化
	//侦听器针对某一个数据指向性更强
	//侦听器可以监测 data中的属性值 和计算属性computed 中的值
	vm.$watch("isHot", {
		immediate: true, //初始化时让handler调用一下
		//handler什么时候调用?当isHot发生改变时。
		handler(newValue, oldValue) {
			console.log("isHot被修改了", newValue, oldValue);
		}
	});
script>

VUE学习(二)、计算属性vs侦听属性——基于案例的对比_第2张图片
以上两种方式都能实现相同的功能——即侦听数据变化

3、深度侦听

<body>
	
	
	<div id="root">
		<h2>今天天气很{{info}}h2>
		<button @click="changeWeather">切换天气button>
		<hr />
		<h3>a的值是:{{numbers.a}}h3>
		<button @click="numbers.a++">点我让a+1button>
		<h3>b的值是:{{numbers.b}}h3>
		<button @click="numbers.b++">点我让b+1button>
		<button @click="numbers = {a:666,b:888}">用新对象彻底替换掉numbersbutton>
		
		{{numbers.c.d.e}}
	div>
body>

<script type="text/javascript">
	Vue.config.productionTip = false; //阻止 vue 在启动时生成生产提示。

	const vm = new Vue({
		el: "#root",
		data: {
			isHot: true,
			numbers: {
				//多级数据
				a: 1,
				b: 1,
				c: {
					d: {
						e: 100
					}
				}
			}
		},
		computed: {
			info() {
				return this.isHot ? "炎热" : "凉爽";
			}
		},
		methods: {
			changeWeather() {
				this.isHot = !this.isHot;
			}
		},
		/* 
			说明:Vue能监测到多层级数据
					但是提供的watch默认不能监测到多层级数据。默认不开启是为了效率
		*/
		watch: {
			isHot: {
				// immediate:true, //初始化时让handler调用一下
				//handler什么时候调用?当isHot发生改变时。
				handler(newValue, oldValue) {
					console.log("isHot被修改了", newValue, oldValue);
				}
			},
			//监视多级结构中(某个)属性的变化----针对我只想监听多级属性中的某一个
			/* 'numbers.a':{  //这里必须使用真实写法,其实如上边 isHot 真实写法为 'isHot'
				handler(){
					console.log('a被改变了')
				}
			} */
			//监视多级结构中所有属性的变化
			numbers: {
				deep: true, //如果不配置此项 比如d,e变化时 watch 不能监视到
				handler() {
					console.log("numbers改变了");
				}
			}
		}
	});
script>

VUE学习(二)、计算属性vs侦听属性——基于案例的对比_第3张图片

4、监听的简写

<script type="text/javascript">
	Vue.config.productionTip = false; //阻止 vue 在启动时生成生产提示。

	const vm = new Vue({
		el: "#root",
		data: {
			isHot: true
		},
		computed: {
			info() {
				return this.isHot ? "炎热" : "凉爽";
			}
		},
		methods: {
			changeWeather() {
				this.isHot = !this.isHot;
			}
		},
		// 简写的前提是你所需的配置项都是默认的
		watch: {
			//正常写法
			/* isHot:{
				// immediate:true, //初始化时让handler调用一下
				// deep:true,//深度监视
				handler(newValue,oldValue){
					console.log('isHot被修改了',newValue,oldValue)
				}
			}, */
			//简写
			/* isHot(newValue,oldValue){
				console.log('isHot被修改了',newValue,oldValue,this)
			} */
		}
	});

	//正常写法
	/* vm.$watch('isHot',{
		immediate:true, //初始化时让handler调用一下
		deep:true,//深度监视
		handler(newValue,oldValue){
			console.log('isHot被修改了',newValue,oldValue)
		}
	}) */

	//简写
	/* vm.$watch('isHot',(newValue,oldValue){
		console.log('isHot被修改了',newValue,oldValue,this)
	}) */

	/* 
		忠告:vue管理的函数最好都不要写成箭头函数(this会造成很多不必要的麻烦)
	*/
script>

简写的前提是你所需的配置项都是默认的!!!!

三、姓名案例——计算属性VS侦听属性

上面已经给出了姓名案例计算属性的实现,下面给出侦听属性的实现

<body>
	
	
	<div id="root">
		姓:<input type="text" v-model="firstName" /> <br /><br />
		名:<input type="text" v-model="lastName" /> <br /><br />
		全名:<span>{{fullName}}span> <br /><br />
	div>
body>

<script type="text/javascript">
	Vue.config.productionTip = false; //阻止 vue 在启动时生成生产提示。

	const vm = new Vue({
		el: "#root",
		data: {
			firstName: "张",
			lastName: "三",
			fullName: "张-三" //watch必须已经存在fullName,而计算属性实现可以不用
		},
		watch: {
			firstName(val) {
				//相当于(newValue,oldValue)去掉oldValue只要用newValue
				//this.fullName = val + "-" + this.lastName;

				//特殊需求:当我修改名字时,全名延迟一秒改变
				setTimeout(() => {  
					//正因为这不是vue管理的函数,所以在这里必须用this
					//这里如果用普通函数(function(){})则this指向window对象,但是
					//换成箭头函数后箭头函数没有了自己的this就会往外找,而找到的正是我们
					//需要的 vm 做为this
					console.log(this);  //()并不是vue管理的函数
					this.fullName = val + "-" + this.lastName;
				}, 1000);
			},
			lastName(val) {
				this.fullName = this.firstName + "-" + val;
			}
		}
	});
script>

在实现上述代码中全名延迟一秒改变的需求时

计算属性并不能实现这样的功能-------计算属性里面不能开启异步任务去维护数据

fullName(){
	console.log('get被调用了')
	// setTimeout(() => {
	// 	console.log(this)
	// 	//这里的返回返回给()函数去了,并没有返回给fullName
	// 	return this.firstName + '-' + this.lastName
	// }, 1000);
	//-------计算属性里面不能开启异步任务去维护数据
	return this.firstName + '-' + this.lastName
}

总结:当侦听器和计算属性都能完成时更推荐使用计算属性,当计算属性不能完成时考虑用侦听器去实现

你可能感兴趣的:(VUE,vue.js,前端,javascript,前端框架,大前端)