不可以,同名会报错:The computed property "xxxx" is already defined in data
因为不管是计算属性还是data还是props 都会被挂载在vm实例上,因此 这三个都不能同名
Vue.prototype[key] = tools[key]
new Vue({
mixins: [mixin],
store,
router,
render: h => h(App),
}).$mount('#app')
// 创建全局方法
this.$root.$on('test', function(){
console.log('test');
})
// 销毁全局方法
this.$root.$off('test');
// 调用全局方法
this.$root.$emit('test');
Vue.use(plugin)
EventBus 又称为事件总线。在Vue中可以使用 EventBus 来作为沟通桥梁的概念,就像是所有组件共用相同的事件中心,可以向该中心注册发送事件或接收事件,所以组件都可以上下平行地通知其他组件,但也就是太方便所以若使用不慎,就会造成难以维护的灾难,因此才需要更完善的Vuex作为状态管理中心,将通知的概念上升到共享状态层次。
新建 eventBus.js
import Vue from 'vue'
export default new Vue()
<!-- 父组件 -->
<template>
<div class="home">
<Child1 />
<Child2 />
</div>
</template>
A组件使用 $emit
发起事件
<template>
<div @click="handleClick">
Child-1
</div>
</template>
import eventBus from '@/plugin/eventBus'
// ...
handleClick() {
eventBus.$emit('handleClick', '兄弟组件通信')
}
B组件使用 $on
接收
<template>
<div>
Child-2
</div>
</template>
import eventBus from '@/plugin/eventBus'
// ...
created() {
eventBus.$on('handleClick', (res) => {
console.log(res)
})
}
以上写法要在每个组件调用 eventBus.js
,我们可以在 vue
对象上绑定一个全局属性:
main.js
Vue.prototype.$eventBus = new Vue()
在组件中使用
this.$eventBus.$emit('handleClick', '兄弟组件通信')
this.$eventBus.$on('handleClick', (res) => {
console.log(res)
})
或者,我们还可以将 eventBus
注册成插件,利用 vue.use()
进行调用:
const install = function (Vue) {
const eventBus = new Vue({
methods: {
emit (event, ...args) {
this.$emit(event, ...args)
},
on (event, callback) {
this.$on(event, callback)
},
off (event, callback) {
this.$off(event, callback)
}
}
})
Vue.prototype.$eventBus = eventBus
};
export default install;
在 main.js
中使用插件
import eventBus from './eventBus'
Vue.use(eventBus)
在组件中则可以直接使用
this.$eventBus.emit('handleClick', '兄弟组件通信')
this.$eventBus.on('handleClick', (res) => {
console.log(res)
})
$eventBus.on
应该在created
钩子内使用,如果在mounted
使用,它可能接收不到其他组件来自created
钩子内发出的事件;
使用了
$eventBus.on
, 在beforeDestroy
钩子里应该再使用$eventBus.off
解除,因为销毁后,就没必要把监听的句柄存储在eventBus.js
中。
beforeDestroy () {
this.$eventBus.off('handleClick')
}
组件A中,调用 $root.$emit
发起通信
eventClick() {
this.$root.$emit('handleClick', '发起通信')
}
组件B中,调用 $root.$on
进行接收
created() {
this.$root.$on('handleClick', res => {
console.log(res)
})
}
原理与 eventBus
类似
props
$attrs
/ $listeners
, 使用 $attrs
时,需要保证组件未使用 props
接收该属性eventBus
$parent
/ $children
, 可通过 $refs
获取指定组件$root.$emit
/ $root.$on
, 与 eventBus
类似vuex
我们希望调用自定义组件时:
<ModelTest v-model="text" />
此时我们需要用 model
属性来定制 prop
和 event
<template>
<div>
<!-- 允许自定义组件在使用 v-model 时定制 prop 和 event。 -->
<input type="text" :value="text" @input="$emit('changeVal', $event.target.value)">{{text}}
</div>
</template>
<script>
export default {
model: {
prop: 'text', // 指定props中对应的字段
event: 'changeVal' // 事件触发时指定自定义事件
},
props: {
text: {
type: String,
default: ''
}
}
}
</script>
activated
: 页面第一次进入的时候,钩子触发的顺序是created
-> mounted
-> activated
deactivated
: 页面退出的时候会触发deactivated
,当再次前进或者后退的时候只触发activated
Object.assign(this.$data, this.$options.data())
event.currentTarget指向事件所绑定的元素,而event.target始终指向事件发生时的元素。
this.$forceUpdate()
1、组件外部加修饰符.navtive
2、组件内部声明$emit('自定义事件')
当前注册一个vue组件定义 name 为 'node-tree' ,在组件 template 内部调用自身,实现递归。
this.$children
this.$refs.xxx
this.$root
this.$parent
const timer = setInterval(() =>{
// 某些定时器操作
}, 500);
// 通过$once来监听定时器,在beforeDestroy钩子可以被清除。
this.$once('hook:beforeDestroy', () => {
clearInterval(timer);
})
<ul>
<li is='my-component'></li>
</ul>
使用深度作用选择器 /deep/
.text-box {
/deep/ input {
width: 166px;
text-align: center;
}
}
/** 简写 **/
.a >>> .b { /* ... */ }
vue的DOM渲染是异步操作,当修改data时,并不会立即渲染DOM
<template>
<div>
<ul ref="ul">
<li v-for="li in list" :key="li">{{li}}</li>
</ul>
<button @click="addItem">添加li,当前li长度{{num}}</button>
</div>
</template>
<script>
export default {
data() {
return {
num: 0,
list: ['a'] // 默认渲染数据
}
},
methods: {
addItem() {
this.list.push(Math.random())
this.list.push(Math.random())
this.list.push(Math.random())
// // 此时获取的li长度是上一次渲染后的长度 1, 4, ...
// const ul = this.$refs.ul
// this.num = ul.childNodes.length
// dom为异步渲染
// 1. $nextTick是DOM渲染完成后的回调
// 2. 页面渲染时会将data进行整合,多次data修改,DOM只会渲染一次
this.$nextTick(() => {
const ul = this.$refs.ul
this.num = ul.childNodes.length
})
}
}
}
</script>
vue中slot分为3种类型,插槽的概念简单来说,就是父组件向子组件插入内容
<!-- 子组件 -->
<div>
<slot></slot>
</div>
<!-- 父组件 -->
<SlotTest>
普通插槽
<SlotTest>
<!-- 子组件 -->
<div>
<slot name="header"></slot>
</div>
<!-- 父组件 -->
<SlotTest>
<template v-slot:header>
<!-- v-slot:header 可简写 #header -->
具名插槽
</template>
<SlotTest>
常见场景如倒计时组件,父组件传入秒数,子组件处理成时分秒返回给父组件,父组件自定义样式
<!-- 子组件 -->
<div>
<slot :slotData="info"></slot>
</div>
data() {
return { info: { title: "作用域插槽" } }
}
<!-- 父组件 -->
<SlotTest>
<template v-slot="props">
{{props.slotData}}
</template>
<SlotTest>
<!-- name:需要渲染的组件名 -->
<!-- 动态组件可使用keep-alive对组件状态进行缓存 -->
<component :is="name">
使用import异步加载组件,可以使用v-if进行渲染的控制,只有在使用到该组件时才会渲染该组件
components: {
AsyncComponent: () => import("@/components/AsyncComponent")
},
v-show
和v-if
的区别
v-show
通过display
控制显示隐藏v-if
是渲染与销毁v-show
,否则使用v-if
为何在v-for
中使用key
?
key
tag
和key
来判断节点是否相同何时使用beforeDestroy
?
event.$off
Vuex中action
与mutation
的区别
action
中可以处理异步,mutation
不可以mutation
中只做原子操作(即单一功能)action
可以整合多个mutation
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。