一.访问根实例$root
- Vue 子组件可以通过 $root 属性访问父组件实例的属性和方法
写入根组件的数据
<div id="app">
{{msg}}
<root-obj></root-obj>
</div>
<script>
Vue.component("root-obj",{
data () {
return {
}
},
template:`
<div>
<button @click="getRoot">点击改变</button>
</div>
`,
methods: {
getRoot: function(){
//获取根组件的数据this.$root.msg
console.log(this.$root.msg=4);
}
}
})
var vm = new Vue({
el:"#app",
data:{
msg:'Root'
}
}
)
</script>
点击将4写入根组件:
二.访问父级组件实例$parent
<div id="app">
<root-obj></root-obj>
</div>
<script>
Vue.component("root-obj",{
data () {
return {
msg: "root-obj"
}
},
template:`
<div>
<button @click="getRoot">子组件</button>
<child-component></child-component>
</div>
`,
methods: {
getRoot: function(){
console.log("$root:" + " " + this.$root.msg)
console.log("$parent:" + " " + this.$parent.msg)
}
}
})
Vue.component("child-component",{
data () {
return {
}
},
template:`
<div>
<button @click="getRoot">子子组件</button>
</div>
`,
methods: {
getRoot: function(){
console.log("$root:" + " " + this.$root.msg)
console.log("$parent:" + " " + this.$parent.msg)
}
}
})
var vm = new Vue({
el:"#app",
data:{
msg:'Root'
}
}
)
</script>
点击子组件,root-obj
的父组件和根组件都是vm
,即msg:'Root'
点击子子组件,child-component
的父组件是root-obj
,即msg: "root-obj"
;
而根组件依然是vm
,即msg:'Root'
三.root
和parent
异同
相同点:都能实现访问父组件的属性和方法
不同点:如果存在多级子组件,parent访问到的是最近一级的父组件,root得到的是它的根组件
四.$refs
访问子组件实例或子元素
通过 ref 这个 attribute 为子组件赋予一个 ID 引用
通过在子组件标签定义 ref 属性,在父组件中可以使用$refs 访问子组件实例
<div id="app">
<input type='text' ref="input1"/>
<button @click="add">添加</button>
</div>
<script>
var vm = new Vue({
el:"#app",
data:{
msg:'Root'
},
methods: {
add: function(){
this.$refs.input1.value ="22";
}
}
});
</script>
点击添加,
父组件vm中可以使用$refs
访问在子组件标签定义 的ref 属性,
此例是将子组件的ref=input1
,通过父组件的$refs
,将input
的值改为22
五.依赖注入
弥补了 this.$parent
获取父类实例方法的不足,
实际上,你可以把依赖注入看作一部分“大范围有效的 prop”,除了
1. 祖先组件不需要知道哪些后代组件使用它提供的属性
2. 后代组件不需要知道被注入的属性来自哪里
<div id="app">
{{message}}
<google-map></google-map>
</div>
<script>
Vue.component("google-map",{
methods:{
getMap: function ()
{
console.log("获取地图资源!")
}
},
provide: function () {
return {
getMap: this.getMap
}
},
template: `
<div>
<google-map-region></google-map-region>
</div>
`
})
Vue.component("google-map-region",{
inject:["getMap"],//与provide raturn 返回的方法key一致
methods:{
rightMap: function ()
{
console.log("渲染Map!调用父类方法,依赖注入");
this.getMap();
}
},
template:`
<div>
<button @click="rightMap">获取父类方法</button>
<google-map-markers title="你好"></google-map-markers>
</div>
`
})
Vue.component("google-map-markers",{
inheritAttrs:false,
props:{"title":String},
inject:["getMap"],
methods:{
markerMap:function () {
console.log("获取 父类的父类方法 getMap");
this.getMap()
}
},
template:`
<button v-bind="$attrs" @click="markerMap">{{title}}</button>
`
})
var app=new Vue({
el:"#app",
data:function () {
return{
message:"hahhhahhah"
}
}
})
</script>
点击获取父类方法:
点击你好:
六.程序化的事件侦听器
- 通过
$on(eventName, eventHandler)
侦听一个事件 - 通过
$once(eventName, eventHandler)
一次性侦听一个事件 - 通过
$off(eventName, eventHandler)
停止侦听一个事件
<div id="app">
<div v-if="isShow">嘻嘻嘻</div>
<button @click="des">销毁</button>
<button @click="show">点击</button>
<div id="toast"></div>
</div>
<script>
var Toast = Vue.extend({
template: '<div> <button @click="show">打印</button> </div>',
created() {
this.$on('print', () => {
console.log('打印好东西,哈哈哈');
});
},
methods: {
show() {
this.$emit('print');
}
}
});
var toast = new Toast();
var vm = new Vue({
el: '#app',
data: function() {
return {
isShow: true
};
},
created() {
this.$on('show', () => {
console.log('嘻嘻嘻');
});
this.$once('hook:beforeDestroy', () => {
toast.$destroy();
console.log(1)
});
},
methods: {
show() {
this.$emit('show');
this.isShow = this.isShow ? false : true; //变量取反
if (!toast.$el) {
toast.$mount('#toast');
}
},
des() {
vm.$destroy();
console.log(3)
}
},
destroyed() {
console.log('实例已经销毁了');
console.log(2)
}
});
</script>
点击销毁:
点击点击:
嘻嘻嘻
不显示
this.isShow = this.isShow ? false : true; //变量取反
点击打印: