Vue.js 计算属性的基本使用,复杂使用 ,set 和 get,计算属性与methods的对比 和 计算属性与侦听器

发布于:2023-02-11 ⋅ 阅读:(666) ⋅ 点赞:(0)

🚗个人主页:最好的人啊

🚌系列专栏:HTML/CSS

🚐推荐一款模拟面试、刷题神奇、从基础到大厂的面试题库,要想走上人生巅峰迎娶白富美赶快点击这个网站⚡不要犹豫,白富美在向你招手,快来注册吧!

 

目录

前言

我们为什么要引用计算属性?

计算属性的基本使用

计算属性的复杂使用 

计算书本的总价的几种方法

第一种  for循环遍历

第二种   for in  循环遍历

第三种  for of  遍历

第四种  foreach   遍历

第五种  Map   遍历

第六种  filter  遍历

第七种   reduce 遍历

第八种   some 遍历

完整代码

计算属性中的set和get

computed 的  getter/setter

计算属性与methods的对比

计算属性与侦听事件



前言

我们为什么要引用计算属性?

模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的。在模板中放入太多的逻辑会让模板过重且难以维护

表达式的计算逻辑可能会比较复杂,使用计算属性可以使模板内容看起来更加的整洁

例如

<div id="app">
  {{ message.split('').reverse().join('') }}
</div>2>

计算属性的基本使用

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title></title>
		<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
	</head>
	<body>
		<div id="app">
			<h2>您的firstname:{{firstName}}</h2>
			<h2>您的lastname:{{lastName}}</h2>
			<h2>您的fullname是从计算属性中得到:{{fullName}}</h2>
			<h2>您的fullname是从方法中得到:{{getFullName()}}</h2>
			
		</div>
		<script>
			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>
	</body>
</html>

计算属性的复杂使用 

		<div id="app">
			<h2>您的总价:{{totalPrice}}</h2>
		</div>

计算书本的总价的几种方法

						books: [	
						{id: 110,name: "JavaScript从入门到入土",price: 119},
						{id: 111,name: "Java从入门到放弃",price: 80},
						{id: 112,name: "编码艺术",price: 99},
						{id: 113,name: "代码大全",price: 150},
						]

第一种  for循环遍历

          
                // for循环遍历
                totalPrice(){
                    let total=0;
                    for (let i = 0; i < this.books.length; i++) {
                        total+=this.books[i].price                       
                    }
                    return total
                }
 
            }

第二种   for in  循环遍历


                totalPrice(){
                    let total = 0;
                    for (const item in this.books) {
                        total+=this.books[item].price
                    }
                    return total
                }

第三种  for of  遍历

                
                totalPrice() {
                    let total = 0;
                    for (let index of this.books) {
                        total += index.price
                    }
                    return total
                }

第四种  foreach   遍历

                
                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
                }

完整代码

<!DOCTYPE html>
<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="./vue.js"></script>
</head>

<body>
    <div id="app">
        <h3>您的总价为:{{totalPrice}}</h3>
    </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: {
                // for循环遍历
                // totalPrice(){
                //     let total=0;
                //     for (let i = 0; i < this.books.length; i++) {
                //         total+=this.books[i].price                       
                //     }
                //     return total
                // }

                // for in  循环遍历
                // totalPrice(){
                //     let total = 0;
                //     for (const item in this.books) {
                //         total+=this.books[item].price
                //     }
                //     return total
                // }

                // for of  遍历
                // totalPrice() {
                //     let total = 0;
                //     for (let index of this.books) {
                //         total += index.price
                //     }
                //     return total
                // }

                // foreach   遍历
                // 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>
</body>

</html>

实现的结果如下图:

计算属性中的set和get

​ 在计算属性中其实是由这样两个方法settergetter。

      computed: {
        fullName:{
          //计算属性一般没有set方法,只读属性
          set:function(newValue){
            console.log("-----")
            const names = newValue.split(" ")
            this.firstName = names[0]
            this.lastName = names[1]
          },
          get:function(){
            return this.firstName + " " + this.lastName
          }
        }
      }

注意:但是计算属性一般没有set方法,只读属性,只有get方法,但是上述中newValue就是新的值,也可以使用set方法设置值,但是一般不用。

computed 的  getter/setter

<!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计算属性的getter和setter</title>
        <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
    </head>
    <body>
        <div id="app">
            <h1>计算属性:computed的getter/setter</h1>
            <h2>fullName</h2>
            {{fullName}}
            <h2>firstName</h2>
            {{firstName}}
            <h2>lastName</h2>
            {{lastName}}
        </div>
        <script>
            var app = new Vue({
                el:"#app",
                data:{
                firstName:"zhang",
                lastName:"san",
                },
                computed: {
                    fullName:{
                        get:function(){
                            return this.firstName+" "+this.lastName
                        },
                        set:function(value){
                            var list = value.split(' ');
                            this.firstName=list[0]
                            this.lastName=list[1]
                        }
                    }
                },
            });
        </script>
    </body>
    </html>

初始化时如下图 

 当在控制台 修改fullName值是如下图

小结: 通过这种方式,我们可以在改变计算属性值的同时也改变和计算属性相关联的属性值。

计算属性与methods的对比

分别使用计算属性和方法获得fullName的值

<!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>计算属性和methods的对比</title>
</head>
<body>
  <div id="app">
    <!-- methods,即使firstName和lastName没有改变,也需要再次执行 -->
    <h2>{{getFullName()}}</h2>
    <h2>{{getFullName()}}</h2>
    <h2>{{getFullName()}}</h2>
    <h2>{{getFullName()}}</h2>
    <!-- 计算属性有缓存,只有关联属性改变才会再次计算 -->
    <h2>{{fullName}}</h2>
    <h2>{{fullName}}</h2>
    <h2>{{fullName}}</h2>
    <h2>{{fullName}}</h2>


  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
  <script>
    const app = new Vue({
      el:"#app",
      data:{
        firstName:"skt t1",
        lastName:"faker"
      },
      computed: {
        fullName(){
          console.log("调用了计算属性fullName");

          return this.firstName + " " + this.lastName
        }
      },
      methods: {
        getFullName(){
          console.log("调用了getFullName");

          return this.firstName + " " + this.lastName
        }
      },
    })
  </script>
</body>
</html>

分别使用方法和计算属性获取四次fullName

如下图

 小结:

​ 由此可见计算属性有缓存,在this.firstName + " " + this.lastName的属性不变的情况下,methods调用了四次,而计算属性才调用了一次,性能上计算属性明显比methods好。而且在改动firstName的情况下,计算属性只调用一次,methods依然要调用4次。

计算属性与侦听事件

<!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/vue@2.6.10/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>

测试结论:

  1. 使用computed计算了fullName属性,值为firstName+lastName。计算属性具有缓存功能,当firstName和lastName都不改变的时候,fullName不会重新计算,比如我们改变age的值,fullName的值是不需要重新计算的。
  2. methods并没有缓存特性,比如我们改变age的值,fullName2()方法会被执行一遍。
  3. 当一个功能可以用上面三个方法来实现的时候,明显使用computed更合适,代码简单也有缓存特性。
  4. 计算属性范围在vue实例内,修改vue实例外部对象,不会重新计算渲染,但是如果先修改了vue实例外对象,在修改vue计算属性的对象,那么外部对象的值也会重新渲染。

计算属性:computed

计算属性范围在Vue实例的fullName内所管理的firstName和lastName,通常监听多个变量 1111

侦听器:watch

监听数据变化,一般只监听一个变量或数组

使用场景

watch(异步场景),computed(数据联动) 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/vue@2.6.10/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>

当在输入框中输入数据时, 可以发现fullName的值并没有随之改变 这是因为vue无法检测到对象内部属性值的变化,比如person.firstname的变化

所以此时 需要用到vue的深度监听(deep)

此时加上代码 deep: true

可以发现 每次输入框数据变化 fullname随之改变

上面的可以发现handler监听的新值和老值是一样的 这是有vue2.0的坑 犹豫同源导致的 可以用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/vue@2.6.10/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>

结束语:

搏一搏单车变摩托🏍

前端面试神器(不只有前端嗷)----->​​​​​​ 好兄弟,为了梦想

让我们一起进步,拿到自己想要的offer

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到