Vue2:基础入门2

Vue2:基础入门2

Date: July 29, 2023
Sum: Computed计算属性、watch侦听器、水果车


计算属性

基础及案例:

概念

基于现有的数据,计算出来的新属性依赖的数据变化,自动重新计算。

计算属性本质上就是一个 function 函数,它可以实时监听 data 中数据的变化,并 return 一个计算后的新值,供组件渲染 DOM 时使用。

应用场景

表单中的数据变化,会导致结果也跟着变化

Vue2:基础入门2_第1张图片

语法:先声明后使用

1-声明在 computed 配置项中,一个计算属性对应一个函数

2-使用起来和普通属性一样使用 {{ 计算属性名}}

案例: 小黑的礼物清单

需求:礼物总数与表单中的数量之和同步

Vue2:基础入门2_第2张图片

  • Code:

    
    
    
      
      
      
      Document
      
    
    
    
      

    小黑的礼物清单

    名字 数量
    {{ item.name }} {{ item.num }}个

    礼物总数:{{ plus }} 个

reduce参考:https://blog.csdn.net/qq_38970408/article/details/121018660

注意:计算属性侧重于得到一个计算的结果,因此计算属性中必须有 return 返回值!

使用注意点:

① 计算属性必须定义在 computed 节点中

② 计算属性必须是一个 function 函数

③ 计算属性必须有返回值

④ 计算属性必须当做普通属性使用

比如 {{plus}}, 而非是这样用:{{plus()}}



计算属性 vs 方法

1-computed计算属性

作用:封装了一段对于数据的处理,求得一个结果

语法:

  1. 写在computed配置项中
  2. 作为属性,直接使用js中使用计算属性: this.计算属性模板中使用计算属性:{{计算属性}}

2-methods计算属性

作用:给Vue实例提供一个方法,调用以处理业务逻辑

语法:

  1. 写在methods配置项中
  2. 作为方法调用
    1. js中调用:this.方法名()
    2. 模板中调用 {{方法名()}} 或者 @事件名=“方法名”

计算属性的优势

1-缓存特性:(提升性能)计算属性会对计算出来的结果缓存,再次使用直接读取缓存,依赖项变化了,会自动重新计算 → 并再次缓存

2-methods没有缓存特性

案例:

理解:计算属性会对计算的结果缓存,下一次直接提缓存结果即可,如图计算属性就仅计算了一次,而methods是调用几次就计算几次。很明显,前者资源开销更低。

Vue2:基础入门2_第3张图片

  • Code:

    
    
    
    

注意:

计算属性的结果会被缓存,性能好

方法的计算结果无法被缓存,性能低



计算属性完整写法:

计算属性也是属性,能访问,也应能修改

  1. 计算属性默认的简写,只能读取访问,不能 “修改”
  2. 如果要 “修改” → 需要写计算属性的完整写法

注:建议结合以下例子理解

Vue2:基础入门2_第4张图片

computed: {
	计算属性名: {
		get(): {
			代码逻辑
			return res
		},
		set(修改的值): {
			代码逻辑
		}
	}
}

案例:通过改名卡,能够修改姓和名

Vue2:基础入门2_第5张图片

  • Code:

    
    
    
      
      
      
      Document
      
    
    
    
      
    姓: + 名: = {{ fullName }}


计算属性案例:

案例需求,使用计算属性动态计算:

① 已勾选的商品总个数 ② 已勾选的商品总价 ③ 结算按钮的禁用状态

Vue2:基础入门2_第6张图片

  • Code:

    computed: {
        //动态计算出勾选水果的总数量
        total() {
          let t = 0
          this.fruitlist.forEach(x => {
            if(x.state) {
              t += x.count
            }
          })
          return t
        },
        amount() {
          let a = 0
          this.fruitlist
            .filter(x => x.state)
            .forEach(x => {
              a += x.price * x.count
            })
          return a
        },
        isDisabled() {
          this.total === 0
        }
      },
    

效果:

注意:

这里的this指的是当前组件实例

computed: {
	isDisabled() {
		this.toal === 0
	}
}

个人总结:

计算属性

概念:计算属性本质上就是一个 function 函数,它可以实时监听 data 中数据的变化,并 return 一个计算后的新值,供组件渲染 DOM 时使用。

export default {
  name: 'MyCounter',
  data() {
    return {
      count: 1,
    }
  },
  computed: {
    // 计算属性:监听data中count值的变化,自动计算出count*2之后的新值
    plus() {
      return this.count * 2
    }
  }
}



watch 侦听器

概念及使用:

概念

监视数据变化,执行一些业务逻辑或异步操作。

应用场景

1-监视用户名的变化并发起请求,判断用户名是否可用。

2-实时翻译

Vue2:基础入门2_第7张图片

语法

在 watch 节点下,定义自己的侦听器。

export default {
  data() {
    return {
      username: ''
    }
  },
  watch: {
		// 监听 username 的值的变化
		// 形参列表中,第一个值是“变化后的新值”,第二个值是“变化之前的旧值”
		// 注:oldVal 可以不传
   username(newVal, oldVal) {
      console.log(newVal, oldVal);
    }
  }
}

进一步:如果你想要监视某个复杂数据类型中的子属性

const app = new Vue({
  el: '#app',
  data: {
    // words: ''
    obj: {
      words: ''
    }
  },
  watch: {
    'obj.words' (newValue) {
      console.log('变化了', newValue)
    }
  }

案例:实时翻译

Vue2:基础入门2_第8张图片

  • Code:

    
    
      
        
        
        
        Document
        
      
      
        
    翻译成的语言:
    ⌨️文档翻译
    mela

补充案例:使用 watch 检测用户名是否可用

  • 特点:采用解构获取数据

    监听 username 值的变化,并使用 axios 发起 Ajax 请求,检测当前输入的用户名是否可用:

    Vue2:基础入门2_第9张图片

    复习并理解:

    返回promise对象:

    const res = axios.get('http://www.escook.cn/api/finduser/' + newVal)
    

    Vue2:基础入门2_第10张图片

    若返回promise对象,我们可以通过await/async进行简化,返回的则是一个数据对象,

    async username(newVal, oldVal) {
          console.log(newVal, oldVal);
          const res = await axios.get('http://www.escook.cn/api/finduser/' + newVal)
          console.log(res);
        }
    

    Untitled



防抖优化处理:

案例:实时翻译

需求:防止一直输入,一直及时翻译,而是等输入完,再翻译,以提高性能

Vue2:基础入门2_第11张图片

  • Code:

    
    
      
        
        
        
        Document
        
      
      
        
    翻译成的语言:
    ⌨️文档翻译
    {{ result }}

注意:如果你想使用一些非响应式的数据,你可以通过this把它们挂载到对象身上,而非存到data中



watch侦听器完整写法

如果结果需要受到多个条件来查询控制,我们通常会把它放入到一个obj对象中进行控制。

比如下面:翻译的结果受到 语言 与 被翻译的内容 两方面控制

Vue2:基础入门2_第12张图片

问题:如果结果会受到多方面的控制,该怎么办?

解决方案:添加额外配置项

(1) deep: true 对复杂类型进行深度件事

(2) immediate: true 初始化立刻执行一次handler方法

采用deep:翻译结果会受到 语言与被翻译内容 二者影响

watch:  {
  // 该方法会在数据变化时调用执行
  // newValue新值, oldValue老值(一般不用)
  // words (newValue) {
  //   console.log('变化了', newValue)
  // }
  obj: {
    deep: true,
    async handler(newValue) { // newValue指obj
      clearTimeout(this.timer)
      // 你可以把上面data中的timer清除,下面依然可以执行
      // 因为this会把timer挂载到obj身上
      this.timer = setTimeout(async() => {
        const res = await axios({
        url: 'https://applet-base-api-t.itheima.net/api/translate',
        params: newValue
      })
        this.result = res.data.data
        console.log(res.data.data);
      }, 200) 
    }
  },
}

注:以上我直接把obj作为对象以参数的方式传入,axios会把obj转成参数(用&拼接对象属性)

Vue2:基础入门2_第13张图片

采用immediate: 文本框中预留内容,页面一加载就会被自动翻译。原理上讲,就是一进页面就会执行一次下面的 handler 方法

watch: {
  obj: {
    deep: true, // 深度监视
    immediate: true, // 立刻执行,一进入页面handler就立刻执行一次
    handler (newValue) {
      clearTimeout(this.timer)
      this.timer = setTimeout(async () => {
        const res = await axios({
          url: 'https://applet-base-api-t.itheima.net/api/translate',
          params: newValue
        })
        this.result = res.data.data
        console.log(res.data.data)
      }, 300)
    }
  }
}

结合以上二者的案例效果

Vue2:基础入门2_第14张图片

  • Code:

    
    
      
        
        
        
        Document
        
      
      
        
    翻译成的语言:
    ⌨️文档翻译
    {{ result }}
  1. immediate 选项

默认情况下,组件在初次加载完毕后不会调用 watch 侦听器。如果想让 watch 侦听器立即被调用,则需要使用 immediate 选项。实例代码如下:

Vue2:基础入门2_第15张图片

  1. deep 选项

当 watch 侦听的是一个对象,如果对象中的属性值发生了变化,则无法被监听到。此时需要使用 deep 选项,代码示例如下:

data() {
    return {
      username: 'admin',
      info: {
        username: 'zs' //info中包含 username 属性
      }
    }
  },
  watch: {
    info: { //直接监听 info 对象的变化
      async handler(newVal) {
        const { data: res } = await axios.get('https://www.escook.cn/api/finduser' + newVal.username)
        console.log(res);
      },
      deep: true // 需要使用 deep 选项, 否则 username 值的变化无法被监听到
    }
  }
  1. 监听对象单个属性的变化

如果只想监听对象中单个属性的变化,则可以按照如下的方式定义 watch 侦听器:

Vue2:基础入门2_第16张图片

  1. 计算属性 vs 侦听器

计算属性和侦听器侧重的应用场景不同:

计算属性侧重于监听多个值的变化,最终计算并返回一个新值

计算属性侧重于得到最后的一个结果

侦听器侧重于监听单个数据的变化,最终执行特定的业务处理,不需要有任何返回值

侦听器侧重于去执行某个业务逻辑,业务逻辑执行完,侦听器的目的就达到了



个人总结:

watch 侦听器:

概念:watch 侦听器允许开发者监视数据的变化,从而针对数据的变化做特定的操作

简单写法:

watch: {
	数据属性名(newVal, oldVal) {
	  业务逻辑 或 异步操作  
	}
	‘对象.属性名’(newVal, oldVal) {
	  业务逻辑 或 异步操作  
	}
}

完整写法:

watch: {
	数据属性名:{
		deep: true, // 深度件事
		immediate: true, // 是否立刻执行一次 handler
		handler (newValue) {
			业务逻辑 或 异步操作 
		}
	}
}

注意:

组件在初次加载完毕后不会调用 watch 侦听器。如果想让 watch 侦听器立即被调用,则需要使用 immediate 选项。

当 watch 侦听的是一个对象,如果对象中的属性值发生了变化,则无法被监听到。此时需要使用 deep 选项




综合案例-水果车

需求与思路:

需求说明

  1. 渲染功能
  2. 删除功能
  3. 修改个数
  4. 全选反选
  5. 统计 选中的 总价 和 总数量
  6. 持久化到本地

Vue2:基础入门2_第17张图片

实现思路

1.基本渲染: v-for遍历、:class动态绑定样式

2.删除功能 : v-on 绑定事件,获取当前行的id

3.修改个数 : v-on绑定事件,获取当前行的id,进行筛选出对应的项然后增加或减少

4.全选反选

4-1 必须所有的小选框都选中,全选按钮才选中 → every

4-2 如果全选按钮选中,则所有小选框都选中

4-3 如果全选取消,则所有小选框都取消选中

声明计算属性,判断数组中的每一个checked属性的值,看是否需要全部选

5.统计 选中的 总价 和 总数量 :通过计算属性来计算选中的总价和总数量

6.持久化到本地: 在数据变化时都要更新下本地存储 watch

参考:day2


心得:

实现渲染功能

对于表单数据,一般采用v-mode处理。

比如处理勾选框

Vue2:基础入门2_第18张图片

div class="td">

对于处理图片地址,一般用 v-bind ,而不能这样用:

以上这样会报错

插值表达式一般用于渲染标签内内容,用法如下:

姓名:{{username}}

  • Code: 已实现渲染功能

    
    
      
        
        
        
        
        
        购物车
      
      
        
    选中
    图片
    单价
    个数
    小计
    操作
    {{ item.price }}
    {{ item.num }}
    {{ item.price * item.num }}
    总价  :  ¥ 24
    空空如也

实现删除、修改与全选反选

正反选问题:

采用computed来实现正选:即如果上面都勾上,那么下面的全选也勾上

Vue2:基础入门2_第19张图片

问题是反选,如果我在下面勾上反选,会报计算属性的错误,也就是计算属性没设置全的问题

Vue2:基础入门2_第20张图片

完整的计算属性

computed: {
	计算属性名: {
		get(): {
			代码逻辑
			return res
		},
		set(修改的值): {
			代码逻辑
		}
	}
}

解决方案:

computed: {
  isAll: {
    get() {
      return this.fruitList.every(item => item.isChecked === true)
    },
    set(value) {
	    this.fruitList.forEach(item => item.isChecked = value)
    }
  }
},
  • Code:

    
    
      
        
        
        
        
        
        购物车
      
      
        
    选中
    图片
    单价
    个数
    小计
    操作
    {{ item.price }}
    {{ item.num }}
    {{ item.price * item.num }}
    总价  :  ¥ 24
    空空如也

实现总价

问题:

reduce与箭头的使用方式:如果里面箭头函数{}包含多行代码,记得要return

let total = this.fruitList.reduce((sum, item) => {
  if(item.isChecked === true){
    return sum += item.num
  }else {
    return sum
  }
}, 0)
  • Code:

    
    

持久化到本地

问题:任何数据的变化,都需要监视并存取

策略:通过watch的deep: true以及 localStorage来进行处理

watch: {
  fruitList: {
    deep: true,
    handler(newValue) {
      localStorage.setItem('list', JSON.stringify(newValue))
    }
  }
}

通过浏览器开发者模式查看信息:

Vue2:基础入门2_第21张图片

补充:通过这个键清空本地缓存

Vue2:基础入门2_第22张图片

所有代码

  • Code:

    
    
      
        
        
        
        
        
        购物车
      
      
        
    选中
    图片
    单价
    个数
    小计
    操作
    {{ item.price }}
    {{ item.num }}
    {{ item.price * item.num }}
    总价  :  ¥ {{ totalPrice }}
    空空如也

业务总结

  1. 渲染功能:v-if/v-else v-for :class
  2. 删除功能:点击传参 filter过滤覆盖原数组
  3. 修改个数:点击传参find找对象
  4. 全选反选:计算属性computed 完整写法 get/ set
  5. 统计选中的总价和总数量:计算属性computed reduce条件求和
  6. 持久化到本地:watch监视,localStorage, JSON.stringify, JSON.parse



你可能感兴趣的:(Vue,javascript,开发语言,ecmascript)