Vue - computed properties and listeners

Table of contents

1. Calculated properties

1. Basic use

2. Complicated use

3.getter和setter

4. Comparing properties and methods

Two, the listener

1. Usage of watch


1. Calculated properties

1. Basic use

​ Now there are variables surname and first name, to get the full name.

   <div id="app">

        <h2>您的firstname:{
   
   {firstName}}</h2>
        <h2>您的lastname:{
   
   {lastName}}</h2>
        
        <h2>您的fullname是从计算属性中得到:{
   
   {fullName}}</h2>

        <h2>您的fullname是从方法中得到:{
   
   {getFullName()}}</h2>

    </div>
    <script>
        Vue.config.productionTip = false;  //阻止 vue 在启动时生成生产提示。
        const vm = new Vue({
            el: '#app',
            data(){
                return{
                    firstName:'zhang',
                    lastName:'san'
                }
            },
            methods: {
                getFullName(){
                    return this.firstName + this.lastName
                }
            },
            computed:{//计算属性 一定要有一个返回值 在页面中渲染时是不需要加小括号的
                fullName(){
                    return this.firstName + this.lastName
                }
            }
        })
    </script>

  Splicing using Mastache syntax<h2>{ {firstName}}{ {lastName}}</h2>

  How to use methods<h2>{ {getFullName()}}</h2>

  Using the computed property computed<h2>{ {fullName}}</h2>

In the example, the computed attribute looks the same as the method, except that method calls need to use (), while computed attributes do not. The name of the method is generally a verb, and the name of the computed attribute is a noun, but this is just a basic use. 

2. Complicated use

   Now there is an array data books, which contains many book objects, the data structure is as follows:

books:[ 
          {id:110,name:"JavaScript from entry to entry",price:119}, 
          {id:111,name:"Java from entry to abandonment",price:80}, 
          {id:112,name: "The Art of Coding",price:99}, 
          {id:113,name:"Code Encyclopedia",price:150}, 
        ]

    ​ It is required to calculate the total price of all books totalPrice.

<div id="app">
			<h2>您的总价:{
   
   {totalPrice}}</h2>
		</div>
		<script>
			const vm = new Vue({
				el: '#app',
				data() {
					return {
						books: [{
								id: 110,
								name: "JavaScript从入门到入土",
								price: 119
							},
							{
								id: 111,
								name: "Java从入门到放弃",
								price: 80
							},
							{
								id: 112,
								name: "编码艺术",
								price: 99
							},
							{
								id: 113,
								name: "代码大全",
								price: 150
							},
						]
					}
				},
				computed: {
					/* totalPrice() {
						let total = 0
						for (let i = 0; i < this.books.length; i++) {
                              total += this.books[i].price
						}
						return total
					} */
					
					/* totalPrice() {
						let total = 0
						for (let index in this.books) {
							total += this.books[index].price
						}
						return total
					} */
					
					/* totalPrice() {
						let total = 0;
						for(let item of this.books){
							total += item.price
						}
						return total
					} */
					
					/* totalPrice() {
						let total = 0;
						this.books.forEach(item=>{
							total += item.price
						})
						return total
					} */
					
					/* map */
					/* totalPrice() {
						let total = 0;
						this.books.map(item=>{
							total += item.price
						})
						return total
					} */
					
					/* filter */
					/* totalPrice() {
						let total = 0;
						this.books.filter(item=>{
							total += item.price
						})
						return total
					} */
					
					/* reduce */
					/* totalPrice() {
						return this.books.reduce((total,item)=>{
							 return total + item.price 
						},0)
					} */
					
					/* totalPrice() {
						return this.books.reduce((total,item)=>total + item.price,0)
					} */
					
					/* some */
					totalPrice() {
						let total = 0;
						this.books.some(item=>{
							total += item.price
						})
						return total
					}
					
				}
			})
		</script>

​ Obtain the price accumulation of each book object. When the price of one of the books changes, the total price will change accordingly.

3.getter和setter

​ In the computed property, there are actually two methods setter and getter.

​ However, computed properties generally do not have a set method, and read-only properties only have a get method. However, newValue in the above is a new value. You can also use the set method to set a value, but it is generally not used.

       <div id="app">
			<input type="text" v-model="firstName"/><br>
			<input type="text" v-model="lastName"/><br>
			<input type="text" v-model="fullName"/>
			<!-- v-model实现数据的双向绑定 -->
			<!-- 2.双向绑定(v-model):数据不仅能从data流向页面,还可以从页面流向data。
						备注:
								1.双向绑定一般都应用在表单类元素上(如:input、select等)
								2.v-model:value 可以简写为 v-model,因为v-model默认收集的就 
                                   是value值。 -->
		</div>
		<script>
			const vm = new Vue({
				el: '#app',
				data() {
					return {
						firstName: 'zhang',
						lastName: 'san'
					}
				},
				computed: { //计算属性 一定要有一个返回值 在页面中渲染时是不需要加小括号的
					/* fullName(){
						return this.firstName + this.lastName
					} */

					 fullName: {
						get: function() {
							return this.firstName +','+ this.lastName
						},
						set:function(val){
							var list = val.split(',')
							console.log(list);
							this.firstName = list[0]
							this.lastName = list[1]
						}
					} 
				}
			})
		</script>

 

 In this way, we can change the property value associated with the computed property while changing the value of the computed property.

4. Comparing properties and methods

       <div id="app">
			<h2>您的fullname是从计算属性中得到:{
   
   {fullName}}</h2>
			<h2>您的fullname是从计算属性中得到:{
   
   {fullName}}</h2>
			<h2>您的fullname是从计算属性中得到:{
   
   {fullName}}</h2>
			<h2>您的fullname是从计算属性中得到:{
   
   {fullName}}</h2>
			
			<h2>您的fullname是从方法中得到:{
   
   {getFullName()}}</h2>
			<h2>您的fullname是从方法中得到:{
   
   {getFullName()}}</h2>
			<h2>您的fullname是从方法中得到:{
   
   {getFullName()}}</h2>
			<h2>您的fullname是从方法中得到:{
   
   {getFullName()}}</h2>
		</div>
		<script>
			const vm = new Vue({
				el:'#app',
				data(){
					return {
						firstName:'zhang',
						lastName:'san'
					}
				},
				methods:{
					getFullName(){
						console.log('这里调用了方法getFullName');
						return this.firstName + this.lastName
					}
				},
				computed:{//计算属性 一定要有一个返回值 在页面中渲染时是不需要加小括号的
					fullName(){
						console.log('这里调用了计算属性fullName');
						return this.firstName + this.lastName
					}
				}
			})
			
			/* 总结:计算属性的性能是优于方法的 因为计算属性是具有缓存特性的 */
		</script>

It can be seen that the computed attribute has a cache. In this.firstName + " " + this.lastNamethe case of the same attribute, methods are called four times, while the computed attribute is called only once. The performance of computed attributes is obviously better than methods. And in the case of changing firstName, the calculated property is only called once, and the methods still need to be called 4 times.

Two, the listener

1. Usage of watch

<!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Vue计算属性/侦听器/方法比较</title>
        <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
    </head>
    <body>
        <div id="app">
            <h1>计算属性:computed</h1>
            {
   
   {fullName}}
            <h1>方法:methods</h1>
            {
   
   {fullName2()}}
            <h1>侦听器:watch</h1>
            {
   
   {watchFullName}}
            <h1>年龄</h1>
            {
   
   {age}}
        </div>
        <script>
            var other = 'This is other';
            var app = new Vue({
                el:"#app",
                data:{
                firstName:"zhang",
                lastName:"san",
                watchFullName:"zhangsan",
                age:18,
                },
                watch: {
                    firstName:function(newFirstName, oldFirstName){
                        console.log("firstName触发了watch,newFirstName="+newFirstName+",oldFirstName="+oldFirstName)
                        this.watchFullName = this.firstName+this.lastName+","+other
                    },
                    lastName:function(newLastName, oldLastName){
                        console.log("lastName触发了watch,newLastName="+newLastName+",oldLastName="+oldLastName)
                        this.watchFullName = this.firstName+this.lastName+","+other
                    }  
                },
                computed: {
                    fullName:function(){
                    console.log("调用了fullName,计算了一次属性")
                    return this.firstName+this.lastName+","+other;
                    }
                },
                methods: {
                    fullName2:function(){
                        console.log("调用了fullName,执行了一次方法")
                        fullName2 = this.firstName+this.lastName+","+other;
                        return fullName2;
                    }
                }
            });
        </script>
    </body>
    </html>

initialization:

 Modify firstName/lastName/both

 Modify the age that is not calculated in computed

 Modify objects outside the Vue instance

 After modifying the object outside the Vue instance, modify the object inside the Vue instance

Test conclusion:

  1. The fullName attribute is calculated using computed, and the value is firstName+lastName. Computational properties have 缓存功能, when firstName and lastName do not change, fullName will not be recalculated, for example, if we change the value of age, the value of fullName does not need to be recalculated.
  2. Methods do not have caching features. For example, if we change the value of age, the fullName2() method will be executed again.
  3. When a function can be realized by the above three methods, it is obviously more appropriate to use computed, the code is simple and has caching features.
  4. The scope of the computed attribute is within the Vue instance, modifying the external object of the Vue instance will not recalculate the rendering, but if the object outside the Vue instance is modified first, and then the object of the Vue computed attribute is modified, the value of the external object will also be re-rendered.

Computed property: computed

     The firstName and lastName managed by the calculated attribute range in the fullName of the Vue instance usually listen to multiple variables 1111

Listener: watch

     Monitor data changes, generally only monitor a variable or array

scenes to be used

      watch( 异步场景), computed( 数据联动) watch can directly add the method name in string form after the monitored data

<!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Vue计算属性/侦听器/方法比较</title>
        <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
    </head>
    <body>
        <div id="app">
            <h1>计算属性:computed</h1>
            {
   
   {fullName}}
            <h1>方法:methods</h1>
            {
   
   {fullName2()}}
            <h1>侦听器:watch</h1>
            {
   
   {watchFullName}}
            <h1>年龄</h1>
            {
   
   {age}}
        </div>
        <script>
            var other = 'This is other';
            var app = new Vue({
                el:"#app",
                data:{
                firstName:"zhang",
                lastName:"san",
                watchFullName:"zhangsan",
                age:18,
                },
                watch: {
                    firstName:function(newFirstName, oldFirstName){
                        console.log("firstName触发了watch,newFirstName="+newFirstName+",oldFirstName="+oldFirstName)
                        this.watchFullName = this.firstName+this.lastName+","+other
                    },
                    lastName:function(newLastName, oldLastName){
                        console.log("lastName触发了watch,newLastName="+newLastName+",oldLastName="+oldLastName)
                        this.watchFullName = this.firstName+this.lastName+","+other
                    },
                    watchFullName:"change"

                },
                computed: {
                    fullName:function(){
                    console.log("调用了fullName,计算了一次属性")
                    return this.firstName+this.lastName+","+other;
                    }
                },
                methods: {
                    fullName2:function(){
                        console.log("调用了fullName,执行了一次方法")
                        fullName2 = this.firstName+this.lastName+","+other;
                        return fullName2;
                    },
                    change(){
                        console.log("调用了change,触发了watch")
                        return this.watchFullName='111'
                    }
                }
            });
        </script>
    </body>
    </html>

 The handler method is equivalent to an event triggered by a normal listener. From the results, we can see that when the component is initialized, the listener does not have a handler method, so fullName has no value.

When modifying the above code, add immediate: true, immediate: true means that after the watch is declared, the function in the handler will be executed immediately. Execute the corresponding logic. When the component is initialized, the listener will immediately trigger the handler method

<!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Vue计算属性/侦听器/方法比较</title>
        <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
    </head>
    <body>
        <div id="app">
          <div>
            <p>FullName: {
   
   {person.fullname}}</p>
            <p>FirstName: <input type="text" v-model="person.firstname"></p>
          </div>
        </div>
        <script>
            var other = 'This is other';
            var app = new Vue({
              el: '#app',
               data(){
                return {
                    person: {
                        firstname: 'Menghui',
                        lastname: 'Jin',
                        fullname: ''
                    }
                }
              },
             watch: {
              person: {
                  handler(n,o){
                      this.person.fullname = n.firstname + '' + this.person.lastname;
                  },
                   immediate: true,  //刷新加载 立马触发一次handler
                  deep: true  // 可以深度检测到 person 对象的属性值的变化
              }
              }
            })
        </script>
    </body>
    </html>

When entering data in the input box, it can be found that the value of fullName has not changed. This is because Vue cannot detect the change of the internal property value of the object, such as the change of person.firstname

So at this time, you need to use vue's deep monitoring (deep)

At this time, add the code deep: true

It can be found that the fullname changes every time the input box data changes

From the above, it can be found that the new value monitored by the handler is the same as the old value. This is caused by the vue2.0 pit hesitation and homology, which can be repaired with computed

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>

	</head>
	<body>
		<div id="app">
             <p>FullName: {
   
   {person.fullname}}</p>
             <p>FirstName: <input type="text" v-model="person.firstname"></p>
		</div>
		<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
		<script>
			const app = new Vue({
				el: "#app",
				data() {
					return {
						person: {
							firstname: 'Menghui',
							lastname: 'Jin',
							fullname: ''
						}
					}
				},
				methods: {

				},
				computed: {
                   person2(){
					    return JSON.parse(JSON.stringify(this.person));
				   }//解决深度监听新老值同源问题
				},
				watch:{
				   person2:{
					     handler(n,o){
							 console.log(this.person);
							 console.log(n.firstname);
					                 console.log(o.firstname);
							
							 /* this.person.fullname = this.person.firstname + this.person.lastname */
						 },
						/* immediate: true, */
						 deep: true  // 可以深度检测到 person 对象的属性值的变化
				   }
				}
			})
		</script>
	</body>
</html>

Guess you like

Origin blog.csdn.net/m0_46461853/article/details/126019079