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


    目录

    前言

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

    计算属性的基本使用

    计算属性的复杂使用 

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

    第一种  for循环遍历

    第二种   for in  循环遍历

    第三种  for of  遍历

    第四种  foreach   遍历

    第五种  Map   遍历

    第六种  filter  遍历

    第七种   reduce 遍历

    第八种   some 遍历

    完整代码

    计算属性中的set和get

    computed 的  getter/setter

    计算属性与methods的对比

    计算属性与侦听事件



    前言

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

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

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

    例如

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

    计算属性的基本使用

    1. html>
    2. <html>
    3. <head>
    4. <meta charset="utf-8" />
    5. <title>title>
    6. <script src="js/vue.js" type="text/javascript" charset="utf-8">script>
    7. head>
    8. <body>
    9. <div id="app">
    10. <h2>您的firstname:{{firstName}}h2>
    11. <h2>您的lastname:{{lastName}}h2>
    12. <h2>您的fullname是从计算属性中得到:{{fullName}}h2>
    13. <h2>您的fullname是从方法中得到:{{getFullName()}}h2>
    14. div>
    15. <script>
    16. const vm = new Vue({
    17. el:'#app',
    18. data(){
    19. return {
    20. firstName:'zhang',
    21. lastName:'san'
    22. }
    23. },
    24. methods:{
    25. getFullName(){
    26. return this.firstName + this.lastName
    27. }
    28. },
    29. computed:{//计算属性 一定要有一个返回值 在页面中渲染时是不需要加小括号的
    30. fullName(){
    31. return this.firstName + this.lastName
    32. }
    33. }
    34. })
    35. script>
    36. body>
    37. html>

    计算属性的复杂使用 

    1. <div id="app">
    2. <h2>您的总价:{{totalPrice}}h2>
    3. div>

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

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

    第一种  for循环遍历

    1. // for循环遍历
    2. totalPrice(){
    3. let total=0;
    4. for (let i = 0; i < this.books.length; i++) {
    5. total+=this.books[i].price
    6. }
    7. return total
    8. }
    9. }

    第二种   for in  循环遍历

    1. totalPrice(){
    2. let total = 0;
    3. for (const item in this.books) {
    4. total+=this.books[item].price
    5. }
    6. return total
    7. }

    第三种  for of  遍历

    1. totalPrice() {
    2. let total = 0;
    3. for (let index of this.books) {
    4. total += index.price
    5. }
    6. return total
    7. }

    第四种  foreach   遍历

    1. totalPrice(){
    2. let total = 0;
    3. this.books.forEach(item => {
    4. total+= item.price
    5. })
    6. return total
    7. }

    第五种  Map   遍历

    1. totalPrice(){
    2. let total = 0;
    3. this.books.map(item => {
    4. total+= item.price
    5. })
    6. return total
    7. }

    第六种  filter  遍历

    1. totalPrice(){
    2. let total = 0;
    3. this.books.filter(item => {
    4. total+= item.price
    5. })
    6. return total
    7. }

    第七种   reduce 遍历

    1. totalPrice() {
    2. return this.books.reduce((total,item)=>{
    3. return total + item.price
    4. },0)
    5. }
    6. // 简写
    7. // totalPrice() {
    8. // return this.books.reduce((total, item) => total + item.price, 0)
    9. // }

    第八种   some 遍历

    1. totalPrice() {
    2. let total = 0;
    3. this.books.some(item => {
    4. total += item.price
    5. })
    6. return total
    7. }

    完整代码

    1. html>
    2. <html lang="en">
    3. <head>
    4. <meta charset="UTF-8">
    5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
    6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
    7. <title>Documenttitle>
    8. <script src="./vue.js">script>
    9. head>
    10. <body>
    11. <div id="app">
    12. <h3>您的总价为:{{totalPrice}}h3>
    13. div>
    14. <script>
    15. const vm = new Vue({
    16. el: '#app',
    17. data() {
    18. return {
    19. books: [{
    20. id: 110,
    21. name: "JavaScript从入门到入土",
    22. price: 119
    23. },
    24. {
    25. id: 111,
    26. name: "Java从入门到放弃",
    27. price: 80
    28. },
    29. {
    30. id: 112,
    31. name: "编码艺术",
    32. price: 99
    33. },
    34. {
    35. id: 113,
    36. name: "代码大全",
    37. price: 150
    38. },
    39. ]
    40. }
    41. },
    42. computed: {
    43. // for循环遍历
    44. // totalPrice(){
    45. // let total=0;
    46. // for (let i = 0; i < this.books.length; i++) {
    47. // total+=this.books[i].price
    48. // }
    49. // return total
    50. // }
    51. // for in 循环遍历
    52. // totalPrice(){
    53. // let total = 0;
    54. // for (const item in this.books) {
    55. // total+=this.books[item].price
    56. // }
    57. // return total
    58. // }
    59. // for of 遍历
    60. // totalPrice() {
    61. // let total = 0;
    62. // for (let index of this.books) {
    63. // total += index.price
    64. // }
    65. // return total
    66. // }
    67. // foreach 遍历
    68. // totalPrice(){
    69. // let total = 0;
    70. // this.books.forEach(item => {
    71. // total+= item.price
    72. // })
    73. // return total
    74. // }
    75. // Map 遍历
    76. // totalPrice(){
    77. // let total = 0;
    78. // this.books.map(item => {
    79. // total+= item.price
    80. // })
    81. // return total
    82. // }
    83. // filter 遍历
    84. // totalPrice(){
    85. // let total = 0;
    86. // this.books.filter(item => {
    87. // total+= item.price
    88. // })
    89. // return total
    90. // }
    91. // reduce 遍历
    92. // totalPrice() {
    93. // return this.books.reduce((total,item)=>{
    94. // return total + item.price
    95. // },0)
    96. // }
    97. // 简写
    98. // totalPrice() {
    99. // return this.books.reduce((total, item) => total + item.price, 0)
    100. // }
    101. // some 遍历
    102. totalPrice() {
    103. let total = 0;
    104. this.books.some(item => {
    105. total += item.price
    106. })
    107. return total
    108. }
    109. }
    110. })
    111. script>
    112. body>
    113. html>

    实现的结果如下图:

    计算属性中的set和get

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

    1. computed: {
    2. fullName:{
    3. //计算属性一般没有set方法,只读属性
    4. set:function(newValue){
    5. console.log("-----")
    6. const names = newValue.split(" ")
    7. this.firstName = names[0]
    8. this.lastName = names[1]
    9. },
    10. get:function(){
    11. return this.firstName + " " + this.lastName
    12. }
    13. }
    14. }

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

    computed 的  getter/setter

    1. html>
    2. <html lang="en">
    3. <head>
    4. <meta charset="UTF-8">
    5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
    6. <meta http-equiv="X-UA-Compatible" content="ie=edge">
    7. <title>Vue计算属性的getter和settertitle>
    8. <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js">script>
    9. head>
    10. <body>
    11. <div id="app">
    12. <h1>计算属性:computed的getter/setterh1>
    13. <h2>fullNameh2>
    14. {{fullName}}
    15. <h2>firstNameh2>
    16. {{firstName}}
    17. <h2>lastNameh2>
    18. {{lastName}}
    19. div>
    20. <script>
    21. var app = new Vue({
    22. el:"#app",
    23. data:{
    24. firstName:"zhang",
    25. lastName:"san",
    26. },
    27. computed: {
    28. fullName:{
    29. get:function(){
    30. return this.firstName+" "+this.lastName
    31. },
    32. set:function(value){
    33. var list = value.split(' ');
    34. this.firstName=list[0]
    35. this.lastName=list[1]
    36. }
    37. }
    38. },
    39. });
    40. script>
    41. body>
    42. html>

    初始化时如下图 

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

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

    计算属性与methods的对比

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

    1. html>
    2. <html lang="en">
    3. <head>
    4. <meta charset="UTF-8">
    5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
    6. <meta http-equiv="X-UA-Compatible" content="ie=edge">
    7. <title>计算属性和methods的对比title>
    8. head>
    9. <body>
    10. <div id="app">
    11. <h2>{{getFullName()}}h2>
    12. <h2>{{getFullName()}}h2>
    13. <h2>{{getFullName()}}h2>
    14. <h2>{{getFullName()}}h2>
    15. <h2>{{fullName}}h2>
    16. <h2>{{fullName}}h2>
    17. <h2>{{fullName}}h2>
    18. <h2>{{fullName}}h2>
    19. div>
    20. <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js">script>
    21. <script>
    22. const app = new Vue({
    23. el:"#app",
    24. data:{
    25. firstName:"skt t1",
    26. lastName:"faker"
    27. },
    28. computed: {
    29. fullName(){
    30. console.log("调用了计算属性fullName");
    31. return this.firstName + " " + this.lastName
    32. }
    33. },
    34. methods: {
    35. getFullName(){
    36. console.log("调用了getFullName");
    37. return this.firstName + " " + this.lastName
    38. }
    39. },
    40. })
    41. script>
    42. body>
    43. html>

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

    如下图

     小结:

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

    计算属性与侦听事件

    1. html>
    2. <html lang="en">
    3. <head>
    4. <meta charset="UTF-8">
    5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
    6. <meta http-equiv="X-UA-Compatible" content="ie=edge">
    7. <title>Vue计算属性/侦听器/方法比较title>
    8. <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js">script>
    9. head>
    10. <body>
    11. <div id="app">
    12. <h1>计算属性:computedh1>
    13. {{fullName}}
    14. <h1>方法:methodsh1>
    15. {{fullName2()}}
    16. <h1>侦听器:watchh1>
    17. {{watchFullName}}
    18. <h1>年龄h1>
    19. {{age}}
    20. div>
    21. <script>
    22. var other = 'This is other';
    23. var app = new Vue({
    24. el:"#app",
    25. data:{
    26. firstName:"zhang",
    27. lastName:"san",
    28. watchFullName:"zhangsan",
    29. age:18,
    30. },
    31. watch: {
    32. firstName:function(newFirstName, oldFirstName){
    33. console.log("firstName触发了watch,newFirstName="+newFirstName+",oldFirstName="+oldFirstName)
    34. this.watchFullName = this.firstName+this.lastName+","+other
    35. },
    36. lastName:function(newLastName, oldLastName){
    37. console.log("lastName触发了watch,newLastName="+newLastName+",oldLastName="+oldLastName)
    38. this.watchFullName = this.firstName+this.lastName+","+other
    39. }
    40. },
    41. computed: {
    42. fullName:function(){
    43. console.log("调用了fullName,计算了一次属性")
    44. return this.firstName+this.lastName+","+other;
    45. }
    46. },
    47. methods: {
    48. fullName2:function(){
    49. console.log("调用了fullName,执行了一次方法")
    50. fullName2 = this.firstName+this.lastName+","+other;
    51. return fullName2;
    52. }
    53. }
    54. });
    55. script>
    56. body>
    57. 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可以在所监听的数据后面直接加字符串形式的方法名

    1. html>
    2. <html lang="en">
    3. <head>
    4. <meta charset="UTF-8">
    5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
    6. <meta http-equiv="X-UA-Compatible" content="ie=edge">
    7. <title>Vue计算属性/侦听器/方法比较title>
    8. <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js">script>
    9. head>
    10. <body>
    11. <div id="app">
    12. <h1>计算属性:computedh1>
    13. {{fullName}}
    14. <h1>方法:methodsh1>
    15. {{fullName2()}}
    16. <h1>侦听器:watchh1>
    17. {{watchFullName}}
    18. <h1>年龄h1>
    19. {{age}}
    20. div>
    21. <script>
    22. var other = 'This is other';
    23. var app = new Vue({
    24. el:"#app",
    25. data:{
    26. firstName:"zhang",
    27. lastName:"san",
    28. watchFullName:"zhangsan",
    29. age:18,
    30. },
    31. watch: {
    32. firstName:function(newFirstName, oldFirstName){
    33. console.log("firstName触发了watch,newFirstName="+newFirstName+",oldFirstName="+oldFirstName)
    34. this.watchFullName = this.firstName+this.lastName+","+other
    35. },
    36. lastName:function(newLastName, oldLastName){
    37. console.log("lastName触发了watch,newLastName="+newLastName+",oldLastName="+oldLastName)
    38. this.watchFullName = this.firstName+this.lastName+","+other
    39. },
    40. watchFullName:"change"
    41. },
    42. computed: {
    43. fullName:function(){
    44. console.log("调用了fullName,计算了一次属性")
    45. return this.firstName+this.lastName+","+other;
    46. }
    47. },
    48. methods: {
    49. fullName2:function(){
    50. console.log("调用了fullName,执行了一次方法")
    51. fullName2 = this.firstName+this.lastName+","+other;
    52. return fullName2;
    53. },
    54. change(){
    55. console.log("调用了change,触发了watch")
    56. return this.watchFullName='111'
    57. }
    58. }
    59. });
    60. script>
    61. body>
    62. html>

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

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

    此时加上代码 deep: true

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

    上面的可以发现handler监听的新值和老值是一样的 这是有vue2.0的坑 犹豫同源导致的 可以用computed来修改

    1. html>
    2. <html>
    3. <head>
    4. <meta charset="utf-8">
    5. <title>title>
    6. head>
    7. <body>
    8. <div id="app">
    9. <p>FullName: {{person.fullname}}p>
    10. <p>FirstName: <input type="text" v-model="person.firstname">p>
    11. div>
    12. <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js">script>
    13. <script>
    14. const app = new Vue({
    15. el: "#app",
    16. data() {
    17. return {
    18. person: {
    19. firstname: 'Menghui',
    20. lastname: 'Jin',
    21. fullname: ''
    22. }
    23. }
    24. },
    25. methods: {
    26. },
    27. computed: {
    28. person2(){
    29. return JSON.parse(JSON.stringify(this.person));
    30. }//解决深度监听新老值同源问题
    31. },
    32. watch:{
    33. person2:{
    34. handler(n,o){
    35. console.log(this.person);
    36. console.log(n.firstname);
    37. console.log(o.firstname);
    38. /* this.person.fullname = this.person.firstname + this.person.lastname */
    39. },
    40. /* immediate: true, */
    41. deep: true // 可以深度检测到 person 对象的属性值的变化
    42. }
    43. }
    44. })
    45. script>
    46. body>
    47. html>

  • 相关阅读:
    设计模式-观察者模式
    电脑自动开机win11设置教程
    Android build.gradle读取String中文件及gradle.properties数据
    LrC 13 & ACR 16:镜头模糊
    PAT A1016 Phone Bills
    Java Reflection中如何访问私有变量和私有方法呢?
    Scala中文unicode互转
    抽象类和接口
    c# 多线程
    U-boot(二):主Makefile
  • 原文地址:https://blog.csdn.net/qq_52499703/article/details/126019459