Die Anforderung besteht darin, eine Backend-Verwaltungsschnittstelle mit zugehörigen Berechtigungsverwaltungsfunktionen zu erstellen. Die entsprechenden Ideen basieren auf dem Artikel „addRoutes implementiert Backend-Verwaltungsfunktionen“. Die spezifische Methode besteht darin, die Berechtigungen der Rolle im Backend zurückzugeben Durch Aufrufen der addRoutes-Methode beim dynamischen Laden verwaltet vuex den Routenladestatus und die geladenen Routen und speichert sie während des Festschreibungsvorgangs im SessionStorage. Unter normalen Umständen wird das Menü nach der Anmeldung normal angezeigt und die entsprechende Schnittstelle kann angeklickt werden. Nachdem die F5-Seite aktualisiert wurde, wird die Route aus sessionStorage entfernt und neu geladen. Das Menü kann zu diesem Zeitpunkt noch normal angezeigt werden, beim Klicken wird jedoch ein Fehler ausgegeben:
vue.esm.js?65d7:431 [Vue warn]: Error in beforeCreate hook: "TypeError: Cannot read property 'call' of null"
Ich bin ein Neuling, bitte helfen Sie mir herauszufinden, wo das Problem liegt
login.vue-Code-Snippet
computed:{
...mapGetters([
'menuitems',
'isLoadRoutes'
// ...
])
},
methods: {
rememberPwd(){
if(this.checked){
localStorage.setItem('account',this.ruleForm2.account);
localStorage.setItem('password',this.ruleForm2.checkPass );
}
},
removePwd(){
if(this.checked){
localStorage.removeItem('account');
localStorage.removeItem('password');
}
},
handleReset2() {
this.$refs.ruleForm2.resetFields();
this.removePwd();
},
handleSubmit2(ev) {
var _this = this;
this.$refs.ruleForm2.validate((valid) => {
if (valid) {
//_this.$router.replace('/table');
this.logining = true;
//NProgress.start();
var loginParams = { username: this.ruleForm2.account, password: this.ruleForm2.checkPass };
requestLogin(loginParams).then(res => {
this.logining = false;
//NProgress.done();
if (res.data.resultCode !== "SUCCESS") {
this.$message({
message: res.data.resultDesc,
type: 'error'
});
} else {
this.loginUser=res.data.userProfile;
this.routes=res.data.routes;
if(this.loginUser.doRemove){
this.removePwd();
}else{
this.rememberPwd();
}
sessionStorage.setItem('user', JSON.stringify(res.data.userProfile));
sessionStorage.setItem('security', JSON.stringify(this.routes));
this.addMenu(this.routes);
/*this.$router.push(this.routes);*/
if (!this.isLoadRoutes) {
this.$router.addRoutes(this.routes);
for(let route of this.routes){
console.info(JSON.stringify(route));
this.$router.options.routes.push(route);
}
this.loadRoutes();
}
console.info('push to home')
this.$router.push({ path: '/' });
}
});
} else {
console.log('error submit!!');
return false;
}
});
},
...mapActions([
'addMenu',
'loadRoutes'
])
}
store.js-bezogener Code
import {ADD_MENU,LOAD_ROUTES,INIT_FROM_LS} from './mutations_type'
export const state = {
items: [
],
isLoadRoutes: false
}
export const mutations = {
[ADD_MENU] (state, menuItems) {
console.info('addmenu mutations');
if (menuItems.length === 0) {
state.items = []
} else {
state.items = menuItems;
sessionStorage.setItem('state.items',JSON.stringify(state.items));
}
},
[LOAD_ROUTES] (state) {
state.isLoadRoutes = !state.isLoadRoutes;
sessionStorage.setItem('state.isLoadRoutes',JSON.stringify(state.isLoadRoutes));
console.info('change load routes states ' +state.isLoadRoutes);
},
[INIT_FROM_LS](state){
if (sessionStorage.getItem('state.items')) {
state.items = JSON.parse(localStorage.getItem('state.items'));
}
if (sessionStorage.getItem('state.isLoadRoutes')) {
state.isLoadRoutes = JSON.parse(localStorage.getItem('state.isLoadRoutes'));
}
console.info('init from ls '+JSON.stringify(state));
}
}
getters.js
const menuitems = state => state.items
const isLoadRoutes = state => state.isLoadRoutes
export {
menuitems,
isLoadRoutes
}
action.js
import {ADD_MENU,LOAD_ROUTES,INIT_FROM_LS} from './mutations_type'
export const addMenu = ({ commit }, menuItems) => {
if (menuItems.length > 0) {
commit(ADD_MENU, menuItems)
}
}
export const loadRoutes = ({commit}) => {
commit(LOAD_ROUTES)
}
export const initFromLs=({commit})=>{
commit(INIT_FROM_LS)
}
store.js
import Vue from 'vue'
import Vuex from 'vuex'
import * as actions from './actions'
import * as getters from './getters'
import {mutations,state} from './menu'
Vue.use(Vuex)
// 创建 store 实例
export default new Vuex.Store({
state,
actions,
getters,
mutations
})
main.js
import Vue from 'vue'
import App from './App'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-default/index.css'
import VueRouter from 'vue-router'
import store from './vuex/store'
import Vuex from 'vuex'
import 'font-awesome/css/font-awesome.min.css'
import {state} from './vuex/menu'
import Login from './views/Login.vue'
import NotFound from './views/404.vue'
import Home from './views/Home.vue'
Vue.use(ElementUI)
Vue.use(VueRouter)
Vue.use(Vuex)
const router = new VueRouter({
routes:[
{
path: '/login',
component: Login,
name: '',
hidden: true
},
{
path: '/404',
component: NotFound,
name: '',
hidden: true
},
{
path: '/',
component: Home,
hidden: true
},
...generateRoutesFromMenu()
]
})
// Menu should have 2 levels.
function generateRoutesFromMenu (routes = []) {
store.dispatch('initFromLs');
for (let i = 0, l = state.items.length; i < l; i++) {
let item = state.items[i]
if (item.path) {
routes.push(item);
}
}
console.info('generate menu = '+state.items +' routes = '+routes);
return routes
}
router.beforeEach((to, from, next) => {
//NProgress.start();
if (to.path == '/login') {
sessionStorage.removeItem('user');
sessionStorage.removeItem('security');
sessionStorage.removeItem('state.items');
sessionStorage.removeItem('state.isLoadRoutes');
}
let user = JSON.parse(sessionStorage.getItem('user'));
if (!user && to.path != '/login') {
next({ path: '/login' })
} else {
next();
}
})
new Vue({
store,
router,
render: h => h(App)
}).$mount('#app')
Nachdem Sie sich zum ersten Mal angemeldet haben, klicken Sie wie gewohnt auf das linke Menü
Nach dem Aktualisieren mit F5 löst ein Klick auf das Menü einen Fehler aus
.]
Fehlercode
vue.esm.js?65d7:520 TypeError: Cannot read property 'call' of null
at callHook (eval at <anonymous> (app.js:770), <anonymous>:2533:20)
at VueComponent.Vue._init (eval at <anonymous> (app.js:770), <anonymous>:3969:5)
at new VueComponent (eval at <anonymous> (app.js:770), <anonymous>:4140:12)
at createComponentInstanceForVnode (eval at <anonymous> (app.js:770), <anonymous>:3495:10)
at init (eval at <anonymous> (app.js:770), <anonymous>:3329:45)
at createComponent (eval at <anonymous> (app.js:770), <anonymous>:4871:9)
at createElm (eval at <anonymous> (app.js:770), <anonymous>:4814:9)
at VueComponent.patch [as __patch__] (eval at <anonymous> (app.js:770), <anonymous>:5309:9)
at VueComponent.Vue._update (eval at <anonymous> (app.js:770), <anonymous>:2300:19)
at VueComponent.updateComponent (eval at <anonymous> (app.js:770), <anonymous>:2416:10)
handleError @ vue.esm.js?65d7:520
callHook @ vue.esm.js?65d7:2534
Vue._init @ vue.esm.js?65d7:3968
VueComponent @ vue.esm.js?65d7:4139
createComponentInstanceForVnode @ vue.esm.js?65d7:3494
init @ vue.esm.js?65d7:3328
createComponent @ vue.esm.js?65d7:4870
createElm @ vue.esm.js?65d7:4813
patch @ vue.esm.js?65d7:5308
Vue._update @ vue.esm.js?65d7:2299
updateComponent @ vue.esm.js?65d7:2415
get @ vue.esm.js?65d7:2754
run @ vue.esm.js?65d7:2824
flushSchedulerQueue @ vue.esm.js?65d7:2591
(anonymous) @ vue.esm.js?65d7:652
nextTickHandler @ vue.esm.js?65d7:599
vue.esm.js?65d7:431 [Vue warn]: Failed to mount component: template or render function not defined.
found in
---> <Home> at C:\Users\Dio\git\vue-admin\src\views\Home.vue
<App> at C:\Users\Dio\git\vue-admin\src\App.vue
<Root>
经过测试下来,发现发生这种问题的根本原因在于路由component参数在被json转换成字符串之后,然后转回对象的时候无法解析,我尝试了一下直接使用import Home from ‘xxx’ 来替代component的值之后便正常显示路由信息了。但是依然没从根本上解决该问题,头疼
大概看了一下 我觉得你没必要把路由信息都存到sessionStorage中去的 只要存登录获取的信息就行了吧
我觉得可以参考一下这篇文章/a/11...