使用Vue开发项目时,通常我们就会遇到如下几种棘手的问题:
问题1:通过路由传递参数,我们会采用params或者query形式,但这两种方式都会在URL上做手脚,如果传递的参数过多,会导致400 Bad Request(如:点击表格某行,携带行数据跳转到新页面进行查看)。
问题2:兄弟组件传值
问题3:多处地方使用同一数据,为节省重复请求(最为常见)
业务场景:
从A页面携带下钻参数(ID)到B页面,然后B页面获取参数(ID)进行数据请求。由于要下钻的ID过长,受浏览器的URL长度限制问题,我们不能采用常规的prams(xxx.com/B/:ID)或query(xxx.com/B?ID=…)形式传递。可以使用Vuex做中间过渡,跳转前存储ID信息,进入B页面后从Vuex获取ID信息。
如果用户在B页面刷新数据,则Vuex的ID状态值会被清空无法获取,这里只能借助localStorage进行持久化进行处理(当然,如果直接使用localstorage进行持久化存储,而不借助Vuex也是可行的,但就是没了响应式的效果了)
一、常见使用问题
1、Vuex,每次调用mutation之后向localstorage存值,防止刷新丢失
export default {
state:{
reportInfo:null
},
getters:{
reportInfo(state){
if(!state.reportInfo){
state.reportInfo = JSON.parse(sessionStorage.getItem(‘reportInfo’))
}
return state.reportInfo
}
},
mutations:{
initReport:(state,data) => {
state.reportInfo = data
sessionStorage.setItem(‘reportInfo’,JSON.stringify(data))
},
changeReportReview:(state,data) => {
state.reportInfo.is_review = data;//改state的reportInfo里的某个值,
同时修改sessionStorage的值,以保证一样
sessionStorage.setItem(‘reportInfo’,JSON.stringify(state.reportInfo))
}
}
}
2、调用时需要追加模块名称
如上的getters,首先从store中获取,如果store中不存在则从localstorage中获取(刷新)
3、页面中如果有用户登出操作,此时一般需要removeItem,如果页面中有userInfo的判断信息,如下一般需要先做个判断userInfo存在才会去取userInfo.roleName的值,这样就会防止页面报错,类似于后台语言空指针的错误
{{userInfo ? (userInfo.account ? userInfo.account : userInfo.phoneNum) : “”}}
添加账户
如果没有removeItem的操作的话,则是不需要这样的。如下面的reportInfo,因为用户登出的时候,不会影响到它
提交审核意见
专家正在审核,请稍后
查看云和恩墨专家团队审核意见
4、state访问状态对象
const state ,这个就是我们说的访问状态对象,它就是我们SPA(单页应用程序)中的共享值。
学习状态对象赋值给内部对象,也就是把stroe.js中的值,赋值给我们模板里data中的值。有三种赋值方式:
(1)通过computed的计算属性直接赋值
computed属性可以在输出前,对data中的值进行改变,我们就利用这种特性把store.js中的state值赋值给我们模板中的data值。
computed:{
count(){
return this.$store.state.count;
}
}
这里需要注意的是return this.$store
.state.count这一句,一定要写this,要不你会找不到$store的。这种写法很好理解,但是写起来是比较麻烦的,那我们来看看第二种写法。
(2)通过mapState的对象来赋值
我们首先要用import引入mapState。
import {mapState} from ‘vuex’;
//然后还在computed计算属性里写如下代码:
computed:mapState({
count:state=>state.count //理解为传入state对象,修改为state.count属性
})
这里我们使用ES6的箭头函数来给count赋值。
(3)通过mapState的数组来赋值
computed:mapState([“count”])
这个算是最简单的写法了,在实际项目开发当中也经常这样使用
5、模板获取Mutations方法
实际开发中我们也不喜欢看到$store.commit( )这样的方法出现,我们希望跟调用模板里的方法一样调用。 例如:@click=”reduce” 就和没引用vuex插件一样。要达到这种写法,只需要简单的两部就可以了:
//1、用import 引入我们的mapMutations:
import {mapGetters,mapMutations} from ‘vuex’
//2、添加methods属性,并加入mapMutations
…mapMutations([‘changeReportReview’]),
mapGetters、`mapActions`,都是一样的用法
methods:{
…mapMutations([
‘add’,‘reduce’
]),
…mapActions([‘addAction’,‘reduceAction’])
},
需要注意的是,(1)调用的时候都是需要加上this才能访问到的;(2)getters/mutations/actions这些如果没带命名空间的话,就算是写在module模块里的这些方法,但是在使用的时候,是不需要加上模块名称的,而state是要加上模块名称的
二、状态管理模式
“单向数据流”理念的极简示意:
-
state,驱动应用的数据源;
-
view,以声明方式将 state 映射到视图;
-
actions,响应在 view 上的用户输入导致的状态变化。
我们在开发中会遇到多个组件共享状态时,单向数据流的简洁性很容易被破坏。
-
多个视图依赖于同一状态。
-
来自不同视图的行为需要变更同一状态。
对于问题一,传参的方法对于多层嵌套的组件将会非常繁琐,并且对于兄弟组件(非父子组件)间的状态传递无能为力;
对于问题二,我们经常会采用父子组件直接引用或者通过事件来变更和同步状态的多份拷贝。以上的这些模式非常脆弱,通常会导致无法维护的代码。
三、Vuex简介
Vuex 和单纯的全局对象有以下两点不同:
-
Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
-
不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。
Vue.use(Vuex);
const store = new Vuex.Store({
// 数据状态
state {…},
// 更改状态 store.commit
mutations: {…},
// 类似于mutation(不能直接变更状态,可以异步操作) store.dispatch
actions: {…},
// 派生状态(如,过滤、计数)
getters: {…}
})
// 将状态从根组件“注入”到每一个子组件中,且子组件能通过 this.$store 访问到。
const app = new Vue({
el: ‘#app’,
store,
data() {}
});
四、State
Vuex 使用单一状态树,这可以让我们能够直接地定位任一特定的状态片段,在调试的过程中也能轻易地取得整个当前应用状态的快照。需要注意,单状态树和模块化并不冲突!
由于 store 中的状态是响应式的,在组件中调用 store 中的状态简单到仅需要在计算属性中返回即可。
computed: {
count () {
return store.state.count // this.$store.state.count
}
}
mapState 辅助函数
当一个组件需要获取多个状态时候,将这些状态都声明为计算属性会有些重复和冗余。为了解决这个问题,我们可以使用 mapState
辅助函数帮助我们生成计算属性。
import { mapState } from ‘vuex’
computed: mapState({
// 映射 this.count 为 store.state.count
‘count’,
// 箭头函数可使代码更简练
count: state => state.count,
// 传字符串参数 ‘count’ 等同于 state => state.count
countAlias: ‘count’,
// 为了能够使用 this
获取局部状态,必须使用常规函数
countPlusLocalState (state) {
return state.count + this.localCount
},
// 使用对象展开运算符将此对象混入到外部对象中
…mapState({
// …
})
})
五、Getter
Getter(state, getters)
可以从 store 中的 state 中派生出一些状态(如,对数据进行过滤操作)。对于多个组件需要用同一属性时,意义重大!类似于计算属性,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。
完整请参照 https://vuex.vuejs.org/zh-cn/getters.html
六、Mutation
mutation 必须是同步函数!!!
更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。
最后
四轮技术面+一轮hr面结束,学习到了不少,面试也是一个学习检测自己的过程,面试前大概复习了 一周的时间,把以前的代码看了一下,字节跳动比较注重算法,面试前刷了下leetcode和剑指offer, 也刷了些在牛客网上的面经。大概就说这些了,写代码去了~
祝大家都能收获大厂offer~
篇幅有限,仅展示部分内容
最后
四轮技术面+一轮hr面结束,学习到了不少,面试也是一个学习检测自己的过程,面试前大概复习了 一周的时间,把以前的代码看了一下,字节跳动比较注重算法,面试前刷了下leetcode和剑指offer, 也刷了些在牛客网上的面经。大概就说这些了,写代码去了~
祝大家都能收获大厂offer~
篇幅有限,仅展示部分内容