vue computed watch区别
1:computed 是计算一个新的属性(不能监听data已有属性,,会报错),并将该属性挂载到 vm(Vue 实例)上,而 watch 是监听已经存在且已挂载到 vm上的数据,所以用 watch 同样可以监听 computed 计算属性的变化(其它还有 data props)
2:computed 本质是一个惰性求值的观察者,具有缓存性,只有当依赖变化后,第一次访问 computed 属性,才会计算新的值,而watch 则是当数据发生变化便会调用执行函数
3:从使用场景上说,computed 适用一个数据被多个数据影响,而 watch 适用一个数据影响多个数据;
vue computed watch应用
- 常应用:
{{fullName}}
new Vue({
data: {
firstName: 'Xiao',
lastName: 'Ming'
},
computed: {
fullName: function () {
return this.firstName + ' ' + this.lastName
}
}
})
注意:fullName是新的属
- 解决vue 子组件改变父组件的值报错:
父组件:
<level-select :level="form.level" @change="changeValue" />
<script>
import LevelSelect from '@/components/LevelSelect'
export default {
components: { LevelSelect },
data() {
return {
form: {
level: 1
}
}
},
methods: {
changeValue(val) {
this.form.level = val
}
}
}
</script>
子组件:
<template>
<div>
<label style="display: inherit;">权限</label>
<el-select v-model="levelSelected" placeholder="请选择" style="width:100%" size="medium">
<el-option
v-for="item in levels"
:key="item.level"
:label="item.name"
:value="item.level"
/>
</el-select>
</div>
</template>
<script>
export default {
props: {
level: {
type: Number,
default: 0
}
},
data() {
return {
levels: [
{ name: '公开', level: 0 },
{ name: '会员可见', level: 1 },
{ name: '需要密码', level: 2 },
]
}
},
computed: {
levelSelected: {
get() {
return this.level
},
set(val) {
this.$emit('change', val)
}
}
}
</script>
<style>
</style>
3:解决父子组件传值,子组件未接受到值:
问题:当父组件传值给子组件echarts时,发现子组件获取的props为空,刚开始以为是钩子函数放错了地方,后来发现从mounted和created都不行。当在父组件data定义传递的数据的时候子组件显示正常
原因:父组件还没渲染完,子组件已经更新.
//父组件
<div class="chart-wrapper">
<pie-chart v-if="flag" :pie-data="piedata"></pie-chart>
</div>
...
import {getPie} from '@/api/status'
export default {
name: 'device',
data() {
return {
flag:false,
piedata:{},
...
},
created(){
this.init()
},
methods:{
init(){
getPie().then(this.getInfoSucc)
},
getInfoSucc(res){
res = res.data;
if(res.code ==0){
const values = res.values;
this.piedata = values.piedata;
this.flag = true
}
}
//子组件
<template>
<div :class="className" :style="{height:height,width:width}"></div>
</template>
<script>
import echarts from 'echarts'
require('echarts/theme/macarons') // echarts theme
import { debounce } from '@/utils'
export default {
props: {
pieData: {
type: Object
},
msg: {
type:Number
},
className: {
type: String,
default: 'chart'
},
width: {
type: String,
default: '100%'
},
height: {
type: String,
default: '300px'
}
},
data() {
return {
chart: null
}
},
watch: {
piedata: {
deep: true,
handler(val) {
console.log(val)
this.setOptions(val)
}
}
},
mounted() {
console.log("pieData:"+JSON.stringify(this.pieData))
this.initChart()
this.__resizeHanlder = debounce(() => {
if (this.chart) {
this.chart.resize()
}
}, 100)
window.addEventListener('resize', this.__resizeHanlder)
},
beforeDestroy() {
if (!this.chart) {
return
}
window.removeEventListener('resize', this.__resizeHanlder)
this.chart.dispose()
this.chart = null
},
methods: {
setOptions({ text, arrtype, arrdata } = {}) {
this.chart.setOption({
title: {
text: text
},
tooltip: {
trigger: 'item',
formatter: '{a} <br/>{b} : {c} ({d}%)'
},
legend: {
left: 'center',
bottom: '10',
data: arrtype
},
calculable: true,
series: [
{
name: '',
type: 'pie',
roseType: 'radius',
radius: [15, 95],
center: ['50%', '42%'],
data: arrdata,
animationEasing: 'cubicInOut',
animationDuration: 2600
}
]
})
},
initChart() {
this.chart = echarts.init(this.$el, 'macarons')
this.setOptions(this.pieData);
}
}
}
</script>