1. 父传子、子传父
props、$emit 触发父亲的自定义事件
2. 状态(数据)提升
实际上是子传父、父传子的结合:利用父组件做中转站
<div id="app">
<test-com1 :pmsg="msg"></test-com1>
<test-com2 @mod-msg="handler"></test-com2>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
// 组件1与父组件之间的数据进行父传子
Vue.component('test-com1', {
props: ['pmsg'],
data: function () {
return { msg: '我是组件1中的值' }
},
template: `<div>组件1:{{pmsg}}</div>`
})
// 组件2与父组件之间的数据进行子传父
Vue.component('test-com2', {
data: function () {
return { msg: '我是组件2中的值' }
},
template: `<button @click="$emit('mod-msg',msg)">修改兄弟组件1的值</button>`
})
// 组件2中的数据提升到父组件(状态提升):利用父类来实现兄弟数据传输
const vm = new Vue({
el: '#app',
data: { msg: '我是父组件中的值' },
methods: {
handler(val) {
this.msg = val
}
}
})
</script>
3. 事件中心(EventBus)
利用事件中心实现组件间自由传值:会引起传值紊乱。不知道‘谁’修改了数值
<div id="app">
<test-com1></test-com1>
<test-com2></test-com2>
<button @click="handler">销毁事件</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
// 事件中心
const hub = new Vue()
// 组件1
Vue.component('test-com1', {
name: 'Tom',
data: function () {
return { num: 1 }
},
template: `<div>
<div>Tom{{num}}</div>
<button @click='handler'>操作jerry</button>
</div>`,
methods: {
handler() {
// 在事件中心下挂载tom 这里传的num是Tom
hub.$emit('tom-com', this.num)
}
},
// TODO: 通过hub.$on 去监听并触发事件
created() {
hub.$on('jerry-com', (val) => {
console.log(val)
this.num += val
})
}
})
// 组件2
Vue.component('test-com2', {
name: 'Jerry',
data: function () {
return { num: 2 }
},
template: `<div>
<div>Jerry{{num}}</div>
<button @click='handler'>操作Tom</button>
</div>`,
methods: {
handler() {
// 在事件中心下挂载jerry 这里传的num是Jerry
hub.$emit('jerry-com', this.num)
}
},
// TODO: 通过hub.$on 去监听并触发事件
created() {
hub.$on('tom-com', (val) => {
console.log(val)
this.num += val
})
}
})
// Vue实例对象
const vm = new Vue({
el: '#app',
methods: {
handler() {
hub.$off('jerry-com')
hub.$off('tom-com')
}
}
})
</script>
4. Vuex(状态管理)
实现各组件间数据共享
state:共享数据源;
mutations:修改数据(state中的数据);
actions:异步请求;
getters:对共享数据进行包装(类似计算属性);
modules:模块化
5. ref
vm.$refs 一个对象,持有注册过 ref attribute 的所有 DOM 元素和组件实例。
$refs 只会在组件渲染完成之后生效,并且它们不是响应式的。
<input type="file" hidden ref="imgFile" @change="onUpdateAvatar" />
onUpdateAvatar() {
// this.$refs.imgFile 拿到对应的组件对象
// 拿到文件对象
const file = this.$refs.imgFile.files[0]
// 清空input框
this.$refs.imgFile.value = ''
}
6. $parent / $children
<div id="app">
<p>{{msg}}</p>
<test></test>
<button @click="handleClick">change child</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue-router@3.4.3/dist/vue-router.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuex@3.5.1/dist/vuex.min.js"></script>
<script>
// 儿子
Vue.component('test', {
data() {
return {
age: 18
}
},
template: `
<div>
<p>{{age}}</p>
<button @click="handleClick">click</button>
</div>
`,
methods: {
handleClick() {
this.$parent.changeMsg('ifer');
},
},
});
// 父亲
const vm = new Vue({
el: '#app',
name: 'App',
data: {
msg: 'hello world'
},
methods: {
changeMsg(msg) {
this.msg = msg;
},
handleClick() {
// this.$children[0] 第 1 个子组件
this.$children[0].age = 19;
}
}
});
</script>
7. provide / inject
<div id="app">
<test1></test1>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue-router@3.4.3/dist/vue-router.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuex@3.5.1/dist/vuex.min.js"></script>
<script>
// 父亲
Vue.component('test1', {
template: '<div>test1 <test2></test2></div>'
});
// 儿子
Vue.component('test2', {
// #2 接受数据
inject: ['msg'],
template: '<div>test2 {{msg}}</div>'
});
// 爷爷
const vm = new Vue({
el: '#app',
name: 'App',
data: {},
// #1 提供数据
provide: {
msg: 'hello'
},
});
</script>
8. $attrs / $listeners
vm.attrs 包含了父作用域中不作为 prop 被识别 (且获取) 的 attribute 绑定 (class 和 style除外)。
vm.$listeners 包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。
<div id="app">
<test :msg="msg" @changemsg="changeMsg"></test>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue-router@3.4.3/dist/vue-router.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuex@3.5.1/dist/vuex.min.js"></script>
<script>
// 儿子
Vue.component('test', {
template: `<div>
<p>{{$attrs.msg}}</p>
<button @click="$listeners.changemsg('ifer')">change msg</button>
</div>`,
mounted() {
},
});
// 父亲
const vm = new Vue({
el: '#app',
name: 'App',
data: {
msg: 'hello'
},
methods: {
changeMsg(msg) {
this.msg = msg;
}
},
});
</script>
9. localStorage/sessionStorage
利用浏览器本地存储