Vue学习篇(四)—计算属性(+面试题_let和var区别)

Vue Day 04——计算属性

概述

  • 什么是计算属性?
  • 计算属性的复杂操作
  • 计算属性的setter和getter
  • 计算属性的缓存
  • let和var的区别
  • 对象自变量-增强写法

4.1. 什么是计算属性?

在模板中可以直接通过插值语法显示一些data中的数据。
但是在某些情况,我们可能需要对数据进行一些转化后再显示,或者需要将多个数据结合起来进行显示

  • 比如我们有firstNamelastName两个变量,我们需要显示完整的名称。
  • 但是如果多个地方都需要显示完整的名称,我们就需要写多个{{firstName}} {{lastName}}

我们可以将上面的代码换成计算属性:
OK,我们发现计算属性是写在实例的computed选项中的。

<div id="app">
    <h2>{{firstname+' '+lastname}}</h2>
    <h2>{{getfullName()}}</h2>
    <h2>{{fullName}}</h2>
</div>

<script src="../js/vue.js"></script>
<script>
    const app = new Vue({
        el: '#app',
        data: {
            firstname: 'Lebanon',
            lastname: 'james'
        },
        computed: { //04计算属性,定义的函数,尽量函数名字像属性
            fullName: function () {
                return this.firstname + ' ' + this.lastname
            }
        },
        methods: {
            getfullName: function () {
                return this.firstname + ' ' + this.lastname
            }
        }
    })


    // const 基本使用,保持不被修改的性质,定义标志符必须赋值,
    // 常量指向的对象不能被修改,但是可以改变对象内部的属性
    //

</script>

在这里插入图片描述

4.2. 计算属性的复杂操作

计算属性中也可以进行一些更加复杂的操作,比如下面的例子:

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

<script src="../js/vue.js"></script>
<script>
    const app = new Vue({
        el: '#app',
        data: {
            books: [
                {
                    id: 110,name: 'Unix编程艺术', price: 119
                },
                {
                    id: 111,name: '代码大全', price: 105
                },
                {
                    id: 112,name: '深入理解计算机原理', price: 139
                },
                {
                    id: 113,name: '现代操作系统', price: 89
                },
            ]
        },
        computed: {
            totalPrice: function () {
                //fiter
                let result=0;
                for(let i=0;i<this.books.length;i++){
                    result += this.books[i].price
                }
                return result

                // for(let i in this.books){
                //     this.books[i]
                // }
                //
                // for(let book of this.books){
                //
                // }
            }
        }
    })
</script>

在这里插入图片描述

4.3. 计算属性的setter和getter

每个计算属性都包含一个getter和一个setter

  • 在上面的例子中,我们只是使用getter来读取。
  • 在某些情况下,你也可以提供一个setter方法(不常用)。
  • 在需要写setter的时候,代码如下:
<div id="app">
  <h2>{{fullName}}</h2>
</div>

<script src="../js/vue.js"></script>
<script>
  const app = new Vue({
    el: '#app',
    data: {
      firstname: 'kobe',
      lastname: 'Bryant'
    },
    computed: {
      // fullName: function () {
      //     return this.firstname +' '+ this.lastname
      // }计算属性一般没有set方法,只读属性
      fullName: {
      //   set: function (newValue) {//实际上就是构造set
      //     console.log('----',newValue);
      //     const names = newValue.split(' ');
      //     this.firstname = names[0];
      //     this.lastname = names[1];
      //   },
        get: function () {
          return this.firstname + ' ' + this.lastname
        }
      },
      //下面是计算属性get方法的简写
      // fullName: function () {
      //   return this.firstname + ' ' + this.lastname
      // }
    }

  })
</script>

4.4. 计算属性的缓存

我们可能会考虑这样的一个问题:

  • methods和computed看起来都可以实现我们的功能,
  • 那么为什么还要多一个计算属性这个东西呢?
  • 原因:计算属性会进行缓存,如果多次使用时,计算属性只会调用一次。

我们来看下面的代码:

<div id="app">
<!--  直接拼接-->
<!--  利用方法,调用多少次,方法就执行多少次-->
  <h2>{{getFullname()}}</h2>
<!--  利用计算属性,然而计算属性中的方法无论调用多少次,都执行一次-->
  <h2>{{fullName}}</h2>
</div>

<script src="../js/vue.js"></script>
<script>
  const app = new Vue({
    el: '#app',
    data: {
      firstname: 'Kode',
      lastname: 'Brody'
    },
    computed: {
      fullName: function () {
        console.log('---');
        return this.firstname +' ' + this.lastname
      }
    },
    methods: {
      getFullname: function () {
        console.log('---');
        return this.firstname +' ' + this.lastname
      }
    }
  })
</script>

4.5. let和var

ES6 新增了let命令,用来声明局部变量。它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效,而且有暂时性死区的约束。

先看个var的常见变量提升的面试题目:

题目1var a = 99;            // 全局变量a
f();                   // f是函数,虽然定义在调用的后面,但是函数声明会提升到作用域的顶部。 
console.log(a);        // a=>99,  此时是全局变量的a
function f() {
  console.log(a);      // 当前的a变量是下面变量a声明提升后,默认值undefined
  var a = 10;
  console.log(a);      // a => 10
}

// 输出结果:
undefined
10
99
4.5.1. ES6可以用let定义块级作用域变量

在ES6之前,我们都是用var来声明变量,而且JS只有函数作用域和全局作用域,没有块级作用域,所以{}限定不了var声明变量的访问范围。
例如:

{ 
  var i = 9;
} 
console.log(i);  // 9

ES6新增的let,可以声明块级作用域的变量。

{ 
  let i = 9;     // i变量只在 花括号内有效!!!
} 
console.log(i);  // Uncaught ReferenceError: i is not defined
4.5.2. let 配合for循环的独特应用

let非常适合用于 for循环内部的块级作用域。JS中的for循环体比较特殊,每次执行都是一个全新的独立的块作用域,用let声明的变量传入到 for循环体的作用域后,不会发生改变,不受外界的影响。看一个常见的面试题目:

for (var i = 0; i <10; i++) {  
  setTimeout(function() {  // 同步注册回调函数到 异步的 宏任务队列。
    console.log(i);        // 执行此代码时,同步代码for循环已经执行完成
  }, 0);
}
// 输出结果
1010// 这里面的知识点: JS的事件循环机制,setTimeout的机制等

如果把 var改成 let声明:

// i虽然在全局作用域声明,但是在for循环体局部作用域中使用的时候,变量会被固定,不受外界干扰。
for (let i = 0; i < 10; i++) { 
  setTimeout(function() {
    console.log(i);    //  i 是循环体内局部作用域,不受外界影响。
  }, 0);
}
// 输出结果:
0  1  2  3  4  5  6  7  8 9
4.5.3. let没有变量提升与暂时性死区

ES6 明确规定,如果区块中存在let和const命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。
总之,在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称 TDZ)。

let声明的变量,不存在变量提升。而且要求必须 等let声明语句执行完之后,变量才能使用,不然会报Uncaught ReferenceError错误。
例如:

console.log(aicoder);    // 错误:Uncaught ReferenceError ...
let aicoder = 'aicoder.com';
// 这里就可以安全使用aicoder
4.5.4. let变量不能重复声明

let不允许在相同作用域内,重复声明同一个变量。否则报错:Uncaught SyntaxError: Identifier 'XXX' has already been declared

例如:

let a = 0;
let a = 'sss';
// Uncaught SyntaxError: Identifier 'a' has already been declared
ES6的let让js真正拥有了块级作用域,也是向这更安全更规范的路走,虽然加了很多约束,但是都是为了让我们更安全的使用和写代码。
4.5.5. 实际自己演练

详情则看代码

<div id="app">
  {{message}}
</div>
<button>按钮3</button>
<button>按钮3</button>
<button>按钮3</button>
<button>按钮3</button>

<script src="../js/vue.js"></script>
<script>
  const app = new Vue({
    el: '#app',
    data: {
      message: '你好啊'
    }
  });
  //ES5之前if和for没有块级作用域的概念,所以主要结束function的作用图
  //但是在
  //1.变量作用域 var 不存在块级作用域的限制(if的块级没有作用域,for的块级也没有作用域
  //使用 闭包可以解决for块级作用域的问题,但是实际上闭包相当于5个不同函数
  var btns = document.getElementsByTagName('button');
  for(var i=0; i<btns.length;i++){
    (function (i) {
      btns[i].addEventListener('click', function () {
        console.log('第'+ i+ '个按钮被点击');
      })
    })(i)
    // btns[i].addEventListener('click', function () {
    //   console.log('第'+ i+ '个按钮被点击');
    // })
  }
  //在ES6 的let中 不需要使用闭包,使用let,具有自己的作用域,
  const btn = document.getElementsByTagName('button');
  for(let i=0;i<btn.length;i++){
    btn[i].addEventListener('click', function () {
      console.log('第'+ i + '个按钮被点击');
    })
  }
</script>

4.6. 对象自变量-增强写法

代码详述:

<script>
  //const obj={}   其中{}就是自变量
  // const obj = {
  //   name: 'whil',
  //   age: 12,
  //   run: function () {
  //     console.log('dddd')
  //   }
  // }
  //属性的增强写法
  const name = 'whe';
  const age = 12;
  const height = 1.88;
  // ES5写法
  // const obj = {
  //   name: name,
  //   age: age,
  //   height: height
  // }
  // S 6增强写法
  // const obj = {
  //   name,
  //   age,
  //   height,
  // }
  //2.函数的增强写法
  //ES 5
  // const obj = {
  //   run: function () {
  //
  //   }
  // }
  // ES 6增强写法
  // const obj = {
  //   run(){
  //
  //   }
  // }
</script>
12;
  const height = 1.88;
  // ES5写法
  // const obj = {
  //   name: name,
  //   age: age,
  //   height: height
  // }
  // S 6增强写法
  // const obj = {
  //   name,
  //   age,
  //   height,
  // }
  //2.函数的增强写法
  //ES 5
  // const obj = {
  //   run: function () {
  //
  //   }
  // }
  // ES 6增强写法
  // const obj = {
  //   run(){
  //
  //   }
  // }
</script>
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值