https://juejin.cn/post/7061588533214969892#heading-91
面试介绍
推荐一个面试经验,觉得讲的挺透彻的。
除此之外还有自己的内容自己补充一下。
第一个:vue父子组件信息传递
首先是:父传子:是通过属性的方式 传值,传的值可以是任意类型,甚至可以是父组件的方法或者父组件对象本身。
- 在父组件中引入子组件;并在components中注册子组件;.通过属性向子组件中传值。
<template>
<div>
<!-- 使用子组件,通过属性向子组件传值,可以是任意值,方法,甚至是父组件对象this -->
<child title="父组件传过来的title" :parent-fun="parentFun" :parent="this"></child>
</div>
</template>
<script>
//1\. 引入子组件
import child from './child.vue' export default {
data() { return {
}
}, //2.在父组件的components中注册子组件
components: {
child
},
methods: {
parentFun() {
console.log("这是父组件的方法");
}
}
} </script>
<style></style>
2,在子组件中通过props属性接收父组件串过来的数据。
<template>
<div>
<div>父组件通过字符串方式传过来的title --- {{title}}</div>
<button @click="parentFun()">调用父组件的方法</button>
<div>通过父组件传过来的父组件对象调用的父组件的属性msg --- {{parent.msg}}</div>
</div>
</template>
<script>
export default {
data() { return {}
},
props: { /* 4\. 通过属性接收父组件传过来的数据,属性是parent-fun, props中可以使用parentFun变量接收 */ title,
parentFun,
parent
}
} </script>
<style></style>
接下来是子传父:
1, 在子组件中通过子组件的$emit方法自定义事件向父组件传数据。
<template>
<div>
<div>父组件通过字符串方式传过来的title --- {{title}}</div>
<button @click="parentFun()">调用父组件的方法</button>
<div>通过父组件传过来的父组件对象调用的父组件的属性msg --- {{parent.msg}}</div>
<button @click="sendMsgToParent()">点击向父组件传值</button>
</div>
</template>
<script>
export default {
data() { return {
msg: '这是子组件的msg' }
},
props: { /* 4.通过属性接收父组件传过来的数据,属性是parent-fun, props中可以使用parentFun变量接收 */ title,
parentFun,
parent
},
methods: {
sendMsgToParent() { //1.子组件通过子定义事件child-msg的方式将msg传给父组件
this.$emit('child-msg', this.msg)
}
}
}
</script>
<style></style>
2,父组件通过监听子组件自定义的事件获取子组件传的值,
<template>
<div>
<!-- 使用子组件,通过属性向子组件传值 -->
<!-- 2.父组件通过监听子组件自定义的@child-msg事件获取子组件传过来的数据 -->
<child @child-msg="getChildMsg" title="父组件传过来的title" :parent-fun="parentFun" :parent="this"></child>
</div>
</template>
<script>
//1\. 引入子组件
import child from './child.vue'
export default {
data() { return {
parentMsg: '这是父组件的msg' }
},
//2.在父组件的components中注册子组件
components: {
child
},
methods: {
parentFun() {
console.log("这是父组件的方法");
},
getChildMsg(msg) {
console.log("这就是子组件传过来的msg" + msg)
}
}
} </script>
<style></style>
有一个很好的接受方法:父向子传值:
父向子传值,可以比喻父亲给儿子说媒:
父亲先物色小姐姐;(引入子组件)
然后小姐姐信息记录下来(components中注册子组件)
将小姐姐信息发给儿子。(属性向子组件中传值)
儿子这边:
通过props属性(可以理解为接收到短信),收到父亲发来的信息。
然后就交往了。
子向父传值:
子向父传值,可以比喻儿子自由恋爱:
儿子有出息,媳妇自己搞定,写email告诉父亲好消息(子组件的$emit方法自定义事件向父组件传数据)
父亲收到信,拆开信得到儿子的好消息(父组件通过监听子组件自定义的事件获取子组件传的值)
除此之外,调用属性:
父组件在使用子组件时可以通过Vue的ref属性获取到子组件对象,从而调用子组件的属性或方法。
子组件调用父组件的方法或属性可以直接通过子组件对象的$parent属性获取父组件对象,从而调用父组件的属性或方法。
Vuex:
Vuex 是一个专为 Vue.js 应用程序开发的状态管理插件。它采用集中式存储管理应用的所有组件的状态,而更改状态的唯一方法是提交mutation。
什么时候用?
多个组件依赖于同一状态时,对于多层嵌套的组件的传参将会非常繁琐,并且对于兄弟组件间的状态传递无能为力。
来自不同组件的行为需要变更同一状态。以往采用父子组件直接引用或者通过事件来变更和同步状态的多份拷贝。以上的这些模式非常脆弱,通常会导致无法维护的代码。
怎么用?
先安装依赖nnpm install vuex --save
在项目目录src中建立store文件夹
在store文件夹下新建index.js文件,写入
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
//不是在生产环境debug为true
const debug = process.env.NODE_ENV !== 'production';
//创建Vuex实例对象
const store = new Vuex.Store({
strict:debug,//在不是生产环境下都开启严格模式
state:{
},
getters:{
},
mutations:{
},
actions:{
}
})
export default store;
然后就在main.js文件中引入Vuex,这么写
import Vue from 'vue';
import App from './App.vue';
import store from './store';
const vm = new Vue({
store:store,
render: h => h(App)
}).$mount('#app')
五大核心属性:state、getters、mutations、actions、modules 。
状态存储在state中,改变Vuex中的状态的唯一途径就是显式地提交 (commit) mutation。
其中vuex的状态是对象时,因为对象是引用类型,复制后改变属性还是会影响原始数据,这样会改变state里面的状态,是不允许,所以先用深度克隆复制对象,再修改才可以。
组件中批量使用Vuex的state状态:
使用mapState辅助函数, 利用对象展开运算符将state混入computed对象中。
import {mapState} from 'vuex'
export default{
computed:{
...mapState(['price','number'])
}
}
Vuex中要从state派生一些状态出来,且多个组件使用它,该怎么做,?
使用getter属性,相当Vue中的计算属性computed,只有原状态改变派生状态才会改变。
getter接收两个参数,第一个是state,第二个是getters(可以用来访问其他getter)。
const store = new Vuex.Store({
state: {
price: 10,
number: 10,
discount: 0.7,
},
getters: {
total: state => {
return state.price * state.number
},
discountTotal: (state, getters) => {
return state.discount * getters.total
}
},
});
然后在组件中可以用计算属性computed通过this.$store.getters.getTodoById(2)这样来访问这些派生转态。
computed: {
getTodoById() {
return this.$store.getters.getTodoById
},
}
mounted(){
console.log(this.getTodoById(2).done)//false
}
组件中批量使用Vuex的getter属性使用mapGetters辅助函数, 利用对象展开运算符将getter混入computed 对象中
import {mapGetters} from 'vuex'
export default{
computed:{
...mapGetters(['total','discountTotal'])
}
}
Vuex的state中有个状态number表示货物数量,在组件怎么改变它。
首先要在mutations中注册一个mutation
const store = new Vuex.Store({
state: {
number: 10,
},
mutations: {
SET_NUMBER(state,data){
state.number=data;
}
},
});
复制代码在组件中使用this.$store.commit提交mutation,改变number
this.$store.commit('SET_NUMBER',10)
Vuex中有两个action,分别是actionA和actionB,其内都是异步操作,在actionB要提交actionA,需在actionA处理结束再处理其它操作,怎么实现?
利用ES6的async和await来实现。
actions:{
async actionA({commit}){
//...
},
async actionB({dispatch}){
await dispatch ('actionA')//等待actionA完成
// ...
}
}
有用过Vuex模块吗,为什么要使用,怎么使用。
有,因为使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。
所以将 store 分割成模块(module)。每个模块拥有自己的 state、mutations、actions、getters,甚至是嵌套子模块,从上至下进行同样方式的分割。
在module文件新建moduleA.js和moduleB.js文件。在文件中写入
const state={
//...
}
const getters={
//...
}
const mutations={
//...
}
const actions={
//...
}
export default{
state,
getters,
mutations,
actions
}
复制代码然后再index.js引入模块
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
import moduleA from './module/moduleA'
import moduleB from './module/moduleB'
const store = new Vuex.Store({
modules:{
moduleA,
moduleB
}
})
export default store
在模块中,getter和mutation接收的第一个参数state,是全局的还是模块的?
第一个参数state是模块的state,也就是局部的state。
要访问全局的state和get怎么办?
在getter中可以通过第三个参数rootState访问到全局的state,可以通过第四个参数rootGetters访问到全局的getter。
在mutation中不可以访问全局的satat和getter,只能访问到局部的state。
在action中第一个参数context中的context.rootState访问到全局的state,context.rootGetters访问到全局的getter。
在v-model上怎么用Vuex中state的值?
需要通过computed计算属性来转换。
<input v-model="message">
// ...
computed: {
message: {
get () {
return this.$store.state.message
},
set (value) {
this.$store.commit('updateMessage', value)
}
}
}