uniapp踩坑记录

1. 页面路径和文件名大小写问题

// 假设你有一个页面路径是 '/pages/Home/index'
this.$router.push('/pages/home/index'); // 小写的 'home' 会导致找不到页面

2. 小程序平台差异

// 微信小程序中使用
uni.getSystemInfo({
  success: (res) => {
    console.log(res);
  }
});
// 支付宝小程序中使用
if (uni.getSystemInfoSync().platform === 'devtools') {
  // 特殊处理支付宝小程序
}

3.uniapp跨页面传值

  • 使用 URL 参数传值
  • 使用全局状态管理(Vuex)
  • 全局对象传值
  • 本地存储传值
  • 使用事件总线(Event Bus)
  • getOpenerEventChannel 传参
  1. 使用 URL 参数传值
uni.navigateTo({
  url: '/pages/detail/detail?id=123&name=Alice'
});
//接受页面
onLoad(options) {
  const { id, name } = options;
  console.log(id, name); // 输出: 123 'Alice'
}

2. 全局对象传值 ( 可以使用全局对象 getApp() 或全局变量。 )

const app = getApp();
app.globalData.userInfo = { id: 123, name: ‘Alice’ };

uni.navigateTo({
url: ‘/pages/detail/detail’
});
// 接受页

onLoad() {
const app = getApp();
const userInfo = app.globalData.userInfo;
console.log(userInfo); // 输出: { id: 123, name: ‘Alice’ }
}

3. 本地存储传值 ( 适用于需要跨页面、甚至跨应用会话的数据传递。 )

uni.setStorageSync('userInfo', { id: 123, name: 'Alice' });

uni.navigateTo({
  url: '/pages/detail/detail'
});
//接受页面
onLoad() {
  const userInfo = uni.getStorageSync('userInfo');
  console.log(userInfo); // 输出: { id: 123, name: 'Alice' }
}

3. bus传值

// eventBus.js
    import Vue from 'vue';
    export default new Vue();
    

    **传值页面:**

    ```javascript
    import eventBus from '@/eventBus';
    eventBus.$emit('sendUserInfo', { id: 123, name: 'Alice' });
    uni.navigateTo({
      url: '/pages/detail/detail'
    });
    ```

    **接收值页面:**

    ```javascript
    import eventBus from '@/eventBus';

    onLoad() {
      eventBus.$on('sendUserInfo', (userInfo) => {
        console.log(userInfo); // 输出: { id: 123, name: 'Alice' }
      });
    }
    

4. getOpenerEventChannel 传参

组件a给B传

uni.navigateTo({
url: ‘/pages/PageB/PageB’,
events: {
// 事件回调函数
acceptDataFromOpenerPage: function(data) {
console.log(data)
},

ok: function(res) {
if(options.ok) options.ok(res.data);
},


},
success: function(res) {
// 通过eventChannel向被打开页面传递数据
res.eventChannel.emit(‘acceptDataFromOpenerPage’, { data: ‘test data from PageA’ })
}
})

PageB 中,通过 getOpenerEventChannel 获取事件通道,并监听从 PageA 传递的数据。

export default {
onLoad() {
const eventChannel = this.getOpenerEventChannel();

// eventChannel.emit(‘ok’, { data: data }); 这是触发event里面设置的事件回调函数, 返回事件
eventChannel.on(‘acceptDataFromOpenerPage’, function(data) {
console.log(data); // { data: ‘test data from PageA’ } 这里是获取
});
}
}

uni.navigateTo:用于跳转到新页面,同时传递一个 events 对象,用于定义事件回调函数。

eventChannel.emit:在跳转成功后的 success 回调中,通过 eventChannel 发射事件,传递数据给新页面。

getOpenerEventChannel:在新页面中调用,获取事件通道,并通过 eventChannel.on 监听事件,接收数据。

uniapp跳转的几种方式

  1. uni.navigateTo:保留当前页面,跳转到应用内的某个页面,使用 `uni.navigateBack` 可以返回到原页面。 “`javascript uni.navigateTo({ url: ‘/pages/detail/detail?id=123&name=Alice’ });

2. uni.redirectTo:关闭当前页面,跳转到应用内的某个页面。 “`javascript uni.redirectTo({ url: ‘/pages/detail/detail?id=123&name=Alice’ });

3. uni.switchTab:跳转到 `tabBar` 页面,并关闭其他所有非 tabBar页面。 uni.switchTab({ url: '/pages/tabbar/index' });

4. uni.reLaunch:关闭所有页面,打开到应用内的某个页面。 javascript uni.reLaunch({ url: ‘/pages/detail/detail?id=123&name=Alice’ });

5. uni.navigateBack:关闭当前页面,返回上一页面或多级页面。 `javascript uni.navigateBack({ delta: 1 // 返回一级页面 }); `

vue项目权限,路由设计

现在我项目用的方法

路由设计:路由表中会定义两个路由表,一个为公共路由表,一个为动态路由表。动态路由根据登录账户的权限去获取。取到权限后,根据roles中的字段,去遍历动态路由表中的对应的路由表。

最后将获取到的符合权限的路由,通过router.addRouter()合并到固定路由下面,,再用到router.beforeEach()去做路由判断,让权限更牢靠

常用方法

第一种

1.对路由跳转进行判断,如果符合权限就允许,反之就不行

2.对跳转页面进行逻辑请求判断,就是页面数据需要一定的权限才能发送请求(这样需要后端人员给你做,个人感觉不太现实,后端估计想干你)

3.根据权限,动态生成对应的路由,什么权限拥有什么路由(vue-element-admin)就是这么做的,动态生成路由

前端常用方法一般是:  v-if + router.beforeEach()

由于后端管理界面涉及到,对登陆用户的权限判断,可能做的好点的后端管理页面,要么把相对应的跳转事件进行隐藏或判断,或者把跳转页面进行隐藏,我之前也是这样做的,对跳转的路由按钮进行  v-if  判断,然后再在router.beforeEach()进行路由判断,这样就可以防止部分用户,根据请求地址来实现跳转

第二种

对跳转的按钮事件进行权限判断


对跳转页面的路由事件,添加一个方法,然后根据权限判断,if和else,满足就跳转,不满足就return,如果想要提升一下用户体验度,就弹出一个消息提示框,说您暂无权限

但是呢,用户体验度不是很好,而且权限是写死的,不具备灵活性

第三种

根据权限动态生成路由

第一步:

就是在你登陆以后,后端返回token,然后在请求成功的回调里面,又发送token去后端去获取当前用户的详细信息,信息中包括了你这名用户的权限,是否为管理员身份,还是次级管理员身份,然后将token存入cookie,将请求获取到的数据存入vuex!假设这个存储你权限的字段交roles,是个数组,类似:[’admin’] or [‘Secondary’] 

第二步:

这里要说明的是,路由表中会定义两个路由表,一个为公共路由表,一个为动态路由表,公共路由表就是不需要权限也能去访问,动态路由表顾名思义就是需要权限去获取了!然后根据获取到你的权限之后,会根据roles中的字段,去遍历动态路由表中的对应的路由表,然后将符合条件的路由表保存起来

第三步:最后将获取到的符合权限的路由,合并到固定路由下面,通过router.addRouter(),当然了这里还是要用到router.beforeEach()去做路由判断,让权限更牢靠一点

参考文献:

http://events.jianshu.io/p/1bbecc010fae

vuex模块化管理在正式项目中的运用及其注意事项

写下平时在心目中用的比较多的vuex标准化用法和介绍

vuex一般用于中大型项目,其内容有

state 存放状态
mutations state成员操作(处理数据,更改保存到state中。用法this.$store.commit )
getters 加工state成员给外界
actions 异步操作(一般用于处理请求逻辑之后将数据给mutations,用法this.$store.dispatch )
modules 模块化状态管理
modules 的每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割。

简单基础使用就不说了,说重点。

在项目中一般是以模块化管理为主。为了方便每个模块的管理和维护大多使用modules模块化状态管理。

上目录

这里面的actions.js和mutation是公共的方法(我自己的习惯)

getters.js和store.js是让外界得到state,公共数据。

index.js是将所有模块集合到一起。然后挂载到main.js上。

//index.js内容
 
import Vue from 'vue'
import vuex from 'vuex'
 
 
import getters from './getters'
import actions from './modules/actions'
import mutations from './modules/mutation'
import user from './modules/user.js'
import user2 from './modules/user2'
import state from './store'
Vue.use(vuex)
export default new vuex.Store({
 
  getters,
  state,
  //模块vuex
  modules: {
    //公共vuex2个模块
    actions,
    mutations,
 
    //各个单独模块使用的vuex
    user,
    user2
  }
})

使用modules后外面不要再加actions和mutations(会报错)

上其中一个单独模块的代码

//这里是user.js的代码
 
 
//某个模块专门使用的vuex。调用时加上该模块名字。如this.$store.commit('user/方法名')
 
const state = {
  userName:''
}
 
const getters = {
  userName:(state) => state.userName
}
const actions = {
  add_name({commit},name){
    commit('ADD_NAME',name);
    console.log('这里是user1的actions',name)
 
  },
}
const  mutations = {
  ADD_NAME(state,name){
    state.userName=name;
    console.log('这里是user1',name)
    return true;
  }
}
export default {
  namespaced: true,            //记住一定要加这个
 
  state,
  getters,
  actions,
  mutations
}

namespaced是告诉vuex给它搞个看见出来。默认false. 开启后就是提示打开了命名空间。这样2个模块有同样的方法也不会报错。

当你要调用某个模块的方法时记得写法是

this.$store.commit(‘模块名/方法名’)

this.$store.dispatch(‘模块名/方法名’)

一切弄完之后记得挂载到main.js上

import Vue from 'vue'
import App from './App'
import router from './router'
import Vuex from 'vuex'
import store from './store/index'
Vue.config.productionTip = false
Vue.use(Vuex)
 
 
/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  store,    //这就是挂载了
  components: { App },
  template: '<App/>'
})

有时候报错说未找到该模块有这个方法

报错信息为:

[vuex] unknown action type: user/add_name

你可以删除命名空间试试。

下面放其他js的代码

//actions.js代码
 
//公共actions异步方法
 
export default {//在action中可以进行异步操作。
  namespaced: true,
 
  actions:{
    add_book({commit},book){
      commit('ADD_BOOK',book);
    },
    delete_book({commit},book){
      commit('DELETE_BOOK',id);
    }
  }
}
 
 
 
//mutations.js代码
//公共mutation方法
export default {//这里要注意不要在mutations里面进行异步操作
  namespaced: true,
 
  mutations:{
    ADD_BOOK(state,book){
      state.bookList.push(book);
      return true;
    },
    DELETE_BOOK(state,id){
    }
  }
}

我觉得这样写便于管理,有的人喜欢给mutations加一个mutations_type的文件。其实就是将他们的方法名都注册一下。我不喜欢这样。

vue优化,解决bug: Waiting for update signal from WDS…时间过长,keep-alive包裹的navtab切换组件不断切换导致页面卡顿以及浏览器内存过高

keep-alive包裹的navtab切换组件不断切换导致页面卡顿以及浏览器内存过高

当这个navtab不断切换时,js heap size就会慢慢变高。

解决办法:

1:查找一下setTimeout定时器有没有清除

2:keep-alive缓存是否清除

3:是否用了iframe (很大嫌疑)

当你的页面上的iframe是直接引用而不是隐藏在组件弹出框中的话,就会造成:每次切换到这个页面,除非秒切,不然会触发webpack的dev机制,引发 Waiting for update signal from WDS…。
而在 Waiting for update signal from WDS…中时,你必须等待它加载完毕再运行,不然任何操作都会让浏览器内存暴涨,而这个想让它释放掉很困难。