10.计算属性和计算缓存
computed:{
方法名(){
this.message是获取当前的实例
return this.message.split("").reverse().join("")
}}
使用直接写方法名 不加()
计算缓存:
先计算结果 放入缓存 再用计算属性会直接从缓存中获取
计算属性中依赖的data数据发送变化 计算会再次计算 再次放入缓存
计算属性会缓存计算的结果 --保证数据的智能更新
computed:{
allPrice(){
let price=0
遍历list数组的所有项 得到所有项的价格 计算总价
this.list.forEach((item)=>{
price+=item.price
return price //这里返回的就是总价格
}
svgPrice(){
return this.allPrice/this.list.length
}
计算属性 是为了-缓存
封装逻辑-实现复用
计算属性和方法的区别:形式的区别 methods computed 方法需要写()
智能更新 计算一次将结果放入缓存
计算属性中依赖的数据:this.list/this.message 计算属性会重新计算 计算一级
}
11.计算属性案例:
多选框影响全选框
1.下方有若干个单选 如果所有单选选择 全选选中状态
2.有一个没选中 全选 未选中状态
全选框的值依赖下面列表单选的值的变化 可以采用计算属性
结构:
span 全选
input type='checkbox'
button 反选
ul
li v-for='(item,index) in arr' :key='index'
input type checkbox v-model='item.c'
span v-text='item.name'
arr:[
{name:'猪八戒',c:false},
{name:'猪八戒',c:false},
{name:'猪八戒',c:false}
]
全选框的值依赖下面列表单选的值的变化
计算属性声明全选框的值
computed:{
isAll(){
确定所有的arr的 c状态 的全部选中 every()方法会返回一个布尔值
return this.arr.every((item)=> item.c===true)
}}
给全选框绑定 isAll计算属性 如果全部的单选框都选中 isAll方法返回true 那么全选框选中
input type='checkbox' v-model='isAll'
全选影响 小选框
v-model绑定计算属性
计算属性默认的写法 只有 getter
需要写完整的写法
computed:{
isAll:{
set是得到值再重新赋值 set的value的形参是get方法返回的参数
set(value){
//value/true/false
this.arr.forEach(item=>item.c=value)
},
get是得到值
get(){
return this.arr.every((item)=>item.c)
}}}
当计算属性需要双向绑定--需要写完整的写法
计算属性中能否做异步操作?
同步:先执行同步的代码 吧异步代码放入任务对列 等到主线程闲置,才会从队列中顺序取出异步代码来执行
异步:
计算属性中可以做异步 但是没有意义
13.侦听器 watch 使用异步做请求
可以监听 data/computed/props/路由的数据变化
watch:{
"要监听的属性名(必须要在data中定义的 不然监听谁啊)"(newValue,oldValue){
this指向当前实例
this.属性
}}
methods:{
test(){
this指向当前实例
}}
computed:{
test(){
this指向当前实例
}},
filters:{
这里没有this 就是一个纯函数
}
14.watch侦听器的深度监听
侦听对象类型的时候 正常无法监听对象的属性
user:{
hobbey:"吃饭"
}
watch:{
user(){
这里监听不到数据变化
},
第一种方式监听对象的属性 这里只是监听对象的某个属性字段
吧对象的属性使用引号包裹 可以监听到对象的属性变化
"user.personal.hobby":(newValue)=>{
log(newValue)
},
第二种方法 开启deep深度监听模式 只要对象内部的任何字段发送变化都会引起handler的触发
user:{
deep:true,//深度监听
immediate:false,//是否初始化之后 立即执行马上
handler(newValue,oldValue){
log(newValue)
}
}
}
要考虑防抖和节流 影响浏览器的性能 因为hanlder里面的log会不断的输出新值newValue的变化
15.props单向数据流
父组件流向子组件 数据在子组件中是只读 在子组件不推荐直接修改传递过来的值
应该在父组件中修改
父传子 props
子传父 自定义事件 $emit('事件名称',参数1...)
16.子传父的几种方式
1.非官方写法
父组件的函数传递给子组件 props
父:
父组件定义的data数据
list:[
{name:"苹果",price:20,intro:'护发素'},
{name:"苹果",price:20,intro:'护发素'},
{name:"苹果",price:20,intro:'护发素'}
]
父组件的方法
cutPrice(){
log("砍价")
}
父组件引用子组件
food-item v-for='(item,index) in list" :key='index' :abc='item' :index="index" :cutPrice='cutPrice'
子:
接受父组件传递过来的属性 ,方法
props:['abc','index','cutPrice'],//字符串的数组形式 里面的字符串是父组件传递的属性名
在子组件可以使用父组件传递的方法
button ='cutPrice(index,1)'//这里在子组件使用父组件的方法
父:
cutPrice(index,p){//接受子组件传递的两个参数
log("砍价",index,p)
更新数组中的价格 props单向数据流
index是索引 所以1是第二项
[1,2,3].find(item,index)=>index===1 // [2]
let item=this.list.find((item,i)=> i===index);
if(item){
item.price-=p 这里的p是接受子组件的button传递过来的参数
}
}
子传父: 如上
定义父组件的函数 这是非官方的用法 react就是这种写法 nb
传统意义的this指向调用者 在这里的this指向父组件 子组件调用了父组件的函数 (只有vue可以这样,vue特殊处理了这里)
call/apply 改变this的指向 并且立即调用
v-bind 改变this的指向并且返回这个函数
16.官方推荐 --自定义事件 这是第二种方法 官方的
自定义事件 可以使用 v-on:自定义事件名称 @自定义事件名称='方法'
监听谁的自定义事件 就在谁的标签上写@
父组件引用子组件
food-item v-for='(item,index) in list" :key='index' :abc=item' :index="index" :cutPrice='cutPrice' @updatePrice='cutPrice' 我这里就是自定义事件@自定义事件名称='父组件定义的方法' 将定义的方法重命名一个名称传递给子组件
子组件触发父组件
1-.在子组件可以使用父组件传递的方法 非官方
button ='cutPrice(index,1)'//这里在子组件使用父组件的方法
2-.官方写法
button @click='officialCut'
子组件的方法
methods:{
officialCut(){
//触发事件 所有$开头都是vue定义的方法
这里通过$emit方法 传递一个自定义事件名称给父组件 传递两个参数
this.$emit("updatePrice",this.index,2)
}}
1.父组件监听事件 @abc='方法'
2.子组件触发事件 this.$emit('abc',参数)
17.
子组件传父
子组件的this是子组件的实例 最终目的是调用到父组件的方法
parentCut(){
this.$parent 当前实例的父实例
这特么直接得到父组件的方法 传值 一步到胃 不推荐使用
this.$parent.cutPrice(this.index,3)
}
为什么不推荐$parent呢?
因为有时候会引入elementUI吧<food-item>组件放到 <el-dialog>elementUI的组件里面 这时候的子组件的实例不是真正的父实例 而是el-dialog了 这是第三方组件 层次非常多 容易混乱父子关系