Open kangkai124 opened 5 years ago
$dispatch
和 $broadcast
方法实现以下功能:
dispatch
方法,向上级指定的组件实例(最近的)上触发自定义事件,并传递数据,且该上级组件已预先通过 $on
监听了这个事件;相反,在父组件调用 broadcast
方法,向下级指定的组件实例(最近的)上触发自定义事件,并传递数据,且该下级组件已预先通过 $on
监听了这个事件。
function broadcast(componentName, eventName, params) {
this.$children.forEach(child => {
const name = child.$options.name;
if (name === componentName) {
child.$emit.apply(child, [eventName].concat(params));
} else {
// todo 如果 params 是空数组,接收到的会是 undefined
broadcast.apply(child, [componentName, eventName].concat([params]));
}
});
}
export default {
methods: {
dispatch(componentName, eventName, params) {
let parent = this.$parent || this.$root;
let name = parent.$options.name;
while (parent && (!name || name !== componentName)) {
parent = parent.$parent;
if (parent) {
name = parent.$options.name;
}
}
if (parent) {
parent.$emit.apply(parent, [eventName].concat(params));
}
},
broadcast(componentName, eventName, params) {
broadcast.call(this, componentName, eventName, params);
}
}
};
vue 组件使用 v-model
父组件
<template>
<div>
<Child v-model="list" />
</div>
</template>
<script>
import Child from './Child'
export default {
name: 'Parent',
component: { Child },
data () { return { list: [1,2,3] } }
}
</script>
子组件
<template>
<div class="child" @click="newList">
<img v-for="item in list" />
</div>
</template>
<script>
export default {
name: 'Child',
model: {
prop: 'list',
event: 'new'
},
methods: {
newList () {
this.$emit('new', [4, 5, 6])
}
}
}
</script>
如官方给的例子
var vm = new Vue({
el: '#example',
data: {
message: 'Hello'
},
computed: {
// 计算属性的 getter
reversedMessage: function () {
// `this` 指向 vm 实例
return this.message.split('').reverse().join('')
}
}
})
ivew 组件 Tabs 第一次切换标签内部 Table 卡顿问题
从折线图切换到到表格时,表格会卡顿一下。
<Tabs>
<TabPane label="折线图" name="line-chart">
<SimpleChart :data="data" />
</TabPane>
<TabPane label="表格" name="table">
<SimpleGrid :data="data" :columns="columns" />
</TabPane>
</Tabs>
分析:进到 Modal 时,折线图和表格组件都已经渲染,但此时表格的 TabPane display:none,Table 获取不到宽高,所以渲染出来的数据堆在一条线上。当切换到表格时,display:block,Table 获取宽高撑开盒子,所以有了一瞬间的卡顿。
解决方法:使用 this.$nextTick 控制表格延迟渲染
<Tabs @on-click="onTabClick">
<TabPane label="折线图" name="line-chart">
<SimpleChart :data="data" />
</TabPane>
<TabPane label="表格" name="table">
<SimpleGrid :data="data" :columns="columns" v-if="mount" />
</TabPane>
</Tabs>
export default {
...
data () {
return {
mount: false
}
},
methods: {
onTabClick (name) {
if (name === 'table') {
this.$nextTick(() => {
this.clickTable = true
})
}
}
}
...
}
Uncaught TypeError: timeout.close is not a function
使用了定时器,然后在 beforeDestory
里清除定时器:
beforeDestroy () {
if (this.timer) {
clearInterval(this.timer)
this.timer = null
}
},
但是浏览器提示有错误:
最后,,,发现是 vs code 自动给我加了段引用代码!!
import { clearInterval } from 'timers'
只要把上面那行代码删了就阔以了。
例如,你可能经常看到这种集成一个第三方库的模式:
// 一次性将这个日期选择器附加到一个输入框上
// 它会被挂载到 DOM 上。
mounted: function () {
// Pikaday 是一个第三方日期选择器的库
this.picker = new Pikaday({
field: this.$refs.input,
format: 'YYYY-MM-DD'
})
},
// 在组件被销毁之前,
// 也销毁这个日期选择器。
beforeDestroy: function () {
this.picker.destroy()
}
这里有两个潜在的问题:
picker
,如果可以的话最好只有生命周期钩子可以访问到它。这并不算严重的问题,但是它可以被视为杂物。你应该通过一个程序化的侦听器解决这两个问题:
mounted: function () {
var picker = new Pikaday({
field: this.$refs.input,
format: 'YYYY-MM-DD'
})
this.$once('hook:beforeDestroy', function () {
picker.destroy()
})
}
关于vue