提交 ab605e22 编写于 作者: VK1688's avatar VK1688

1.4.6

上级 94ee1606
### uniCloud云函数路由框架研究Q群:22466457 如有问题或建议可以在群内讨论。
### 插件名称:`vk-unicloud-router`
### 作者:VK
### 更新时间:2020-10-21
### 更新时间:2020-10-23
## 主要功能 以及 对开发者的价值
#### 1、实现云函数路由模式
......@@ -46,9 +46,11 @@
#### 11、【1.3.8 新增】 `商品SKU选择器组件`(打造uni插件市场功能最全的SKU选择器组件)
#### 12、【1.4.3 新增】 全网首家云函数临时缓存功能(数据储存在内存中,不依赖云数据库,也不依赖redis等缓存数据库)
#### 13、作者亲自在群内解答框架使用问题,让你轻松上手`uniCloud云开发`
#### 13、【1.4.6 新增】对 `Vuex` 进行了深度封装(支持持久化),现在可以很方便的使用Vuex进行读取和储存
#### 14、其他好处…
#### 14、作者亲自在群内解答框架使用问题,让你轻松上手`uniCloud云开发`。
#### 15、其他好处…
##### 插件首页体验地址
......
### uniCloud 云函数路由研究群:22466457 如有问题或建议可以在群内讨论。
##### gitee公共仓库地址:https://gitee.com/vk-uni/vk-uni-cloud-router.git
### 更新内容 针对1.4.4的演示页面重新优化了下。
#### 1、【优化】`vk.callFunctionUtil.uploadFile` 上传文件到unicloud云存储API `/pages_template/uni-id/util/util`下有使用示例
#### 2、【新增】`/pages_template/uni-id/util/util` 页面下的上传文件使用示例
#### 3、【新增】集成了 `Vuex` 做全局状态管理(选择性集成,不影响插件使用)(详情请见根目录下的`store`目录)
#### 4、【优化】Vuex演示页面 `pages_template/vuex/vuex`
### 你也可以在评论区发布留言交流心得。
\ No newline at end of file
### uniCloud 云函数路由研究群:22466457 如有问题或建议可以在群内讨论。
##### gitee公共仓库地址:https://gitee.com/vk-uni/vk-uni-cloud-router.git
### 更新内容
##### 1、【优化】`vk.userCenter.setAvatar` 增加参数`deleteOldFile` 为 `true` 时 上传新头像会自动删除旧头像的云储存文件
##### 2、【优化】对 `Vuex` 进行了深度封装(支持持久化),现在可以很方便的使用Vuex进行读取和储存。(选择性集成,不影响插件使用)(详见演示页面`pages_template/vuex/vuex`)
### 你也可以在评论区发布留言交流心得。
\ No newline at end of file
......@@ -5,21 +5,21 @@
"requires": true,
"dependencies": {
"@alicloud/pop-core": {
"version": "1.7.9",
"resolved": "https://registry.npmjs.org/@alicloud/pop-core/-/pop-core-1.7.9.tgz",
"integrity": "sha512-WKeil0O51ee1EbCcYt65vPYo6eWcDn7dfmXlCMb/GbNDq0MvVheQVS/uAeeUipRXt8jGMc58FXeQxXfsFqlRZg==",
"version": "1.7.10",
"resolved": "https://registry.npmjs.org/@alicloud/pop-core/-/pop-core-1.7.10.tgz",
"integrity": "sha512-9/aLWgmgaAdB1ERNTpdOvF7wueLY5CDTRxKZr93x542iuYRA1NDpcKslFqLOy5CUOa0CbopET3JGaHSAz5qv9g==",
"requires": {
"debug": "^3.1.0",
"httpx": "^2.1.2",
"json-bigint": "^0.2.3",
"json-bigint": "^1.0.0",
"kitx": "^1.2.1",
"xml2js": "^0.4.17"
}
},
"@types/node": {
"version": "12.12.67",
"resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.67.tgz",
"integrity": "sha512-R48tgL2izApf+9rYNH+3RBMbRpPeW3N8f0I9HMhggeq4UXwBDqumJ14SDs4ctTMhG11pIOduZ4z3QWGOiMc9Vg=="
"version": "12.19.1",
"resolved": "https://registry.npmjs.org/@types/node/-/node-12.19.1.tgz",
"integrity": "sha512-/xaVmBBjOGh55WCqumLAHXU9VhjGtmyTGqJzFBXRWZzByOXI5JAJNx9xPVGEsNizrNwcec92fQMj458MWfjN1A=="
},
"asynckit": {
"version": "0.4.0",
......@@ -27,9 +27,9 @@
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
},
"bignumber.js": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-4.1.0.tgz",
"integrity": "sha512-eJzYkFYy9L4JzXsbymsFn3p54D+llV27oTQ+ziJG7WFRheJcNZilgVXMG0LoZtlQSKBsJdWtLFqOD0u+U0jZKA=="
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.1.tgz",
"integrity": "sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA=="
},
"combined-stream": {
"version": "1.0.8",
......@@ -66,9 +66,9 @@
}
},
"httpx": {
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/httpx/-/httpx-2.2.4.tgz",
"integrity": "sha512-looS7tQlnLtXCxV5s/L9hshrrFiY/8IDQ2mIt7FnK/Bll2qDEjWPLsuRmZ6ZOXJZZZ1turs5Pf0d9vzUrPkqOw==",
"version": "2.2.6",
"resolved": "https://registry.npmjs.org/httpx/-/httpx-2.2.6.tgz",
"integrity": "sha512-7tAcdbpR7xbYP/4aon0QTwT1TVHQs1TK66fRYzPomLavHSB9VEeoZstZqa0k4rzj2/4MAM9syfJ8k0/JOAtqmA==",
"requires": {
"@types/node": "^12.0.2",
"debug": "^4.1.1"
......@@ -85,11 +85,11 @@
}
},
"json-bigint": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-0.2.3.tgz",
"integrity": "sha1-EY1/b/HThlnxn5TPc+ZKdaP5iKg=",
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz",
"integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==",
"requires": {
"bignumber.js": "^4.0.0"
"bignumber.js": "^9.0.0"
}
},
"kitx": {
......@@ -116,9 +116,9 @@
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
},
"nodemailer": {
"version": "6.4.13",
"resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.4.13.tgz",
"integrity": "sha512-XmtiiKza2Cqtr+ZRMchMZn9s2nmwQDeakbf+yL0ODsIXOv58UZgk/MKPOkDKqY+mvxHs87PrJK7Nf/tcpKHqYQ=="
"version": "6.4.14",
"resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.4.14.tgz",
"integrity": "sha512-0AQHOOT+nRAOK6QnksNaK7+5vjviVvEBzmZytKU7XSA+Vze2NLykTx/05ti1uJgXFTWrMq08u3j3x4r4OE6PAA=="
},
"sax": {
"version": "1.2.4",
......@@ -129,9 +129,9 @@
"version": "file:../common/uni-id"
},
"vk-unicloud": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/vk-unicloud/-/vk-unicloud-1.5.0.tgz",
"integrity": "sha512-dsN0KtLdeocSxvSx5rep+n9kibmSEexdQkfs3oKePwrXMmeeflzFC4cJ5OKasx6yNTosfjsw3yuBf7whTC6kcw==",
"version": "1.6.8",
"resolved": "https://registry.npmjs.org/vk-unicloud/-/vk-unicloud-1.6.8.tgz",
"integrity": "sha512-pTjCYrRFNkBjNaX3laK/Ck/an7JlnJcLfh9NK/2G80jsLcxVGEQCPL5DXxzl5oazCMZnS8jB1996LNj0SWhKRg==",
"requires": {
"@alicloud/pop-core": "^1.7.9",
"form-data": "^3.0.0",
......
......@@ -12,7 +12,7 @@
"dependencies": {
"config": "file:../common/config",
"uni-id": "file:../common/uni-id",
"vk-unicloud": "^1.6.7"
"vk-unicloud": "^1.6.8"
},
"private": true
}
......@@ -9,15 +9,32 @@ module.exports = {
* data 请求参数 说明
* @params {String} uid 用户Id,可以通过checkToken返回
* @params {String} avatar 用户头像URL
* @params {Boolean} deleteOldFile 是否同时删除云储存内的头像文件
* res 返回参数说明
* @params {Number} code 错误码,0表示成功
* @params {String} msg 详细信息
*/
main: async (event) => {
let {uniID} = event.util;
let res = {};
let { data = {}, userInfo, util, originalParam } = event;
let { customUtil, uniID, config, pubFun, vk , db, _ } = util;
let { uid } = data;
let res = { code : 0, msg : '' };
// 业务逻辑开始-----------------------------------------------------------
let { avatar, deleteOldFile } = data;
// 设置头像
res = await uniID.setAvatar(event.data);
// 判断是否需要删除旧头像的云储存文件
if(res.code ===0 && deleteOldFile && userInfo.avatar){
try {
await uniCloud.deleteFile({
fileList: [
userInfo.avatar
]
});
}catch(err){
res.deleteFileErr = err;
}
}
// 业务逻辑结束-----------------------------------------------------------
return res;
}
......
......@@ -8,6 +8,10 @@ Vue.use(uView);
import vk from 'vk-unicloud-page';
Vue.use(vk);
// 引入vk实例提供的对vuex的简写法文件
import mixin from './store/mixin/mixin.js'
Vue.mixin(mixin);
// 自定义云函数路由配置
Vue.prototype.vk.callFunctionUtil.setConfig({
debug:true,
......
......@@ -113,6 +113,7 @@
vk.userCenter.setAvatar({
data: {
avatar: res.fileID,
deleteOldFile:true
},
success() {
that.avatar = res.fileID;
......
......@@ -4,14 +4,28 @@
Vuex可以用来做全局状态管理。
而此例子是演示将当前登录用户信息存入Vuex,以便于在其他页面中也能直接渲染或获取用户信息
</view>
<view v-if="$store.state.user.userInfo" style="color: red;margin-top: 20rpx;font-size: 36rpx;">
当前登录用户:{{ $store.state.user.userInfo.nickname || $store.state.user.userInfo.username}}
<view style="margin-top: 10rpx;">
说明:
<view style="margin-top: 10rpx;">
1、<text>$user</text> 对应 store/modules 目录下的js文件,同理,你可以在store/modules目录下新建一个$cart.js文件来专门储存购物车信息<br/>
2、页面上直接渲染Vuex数据:<br/>
$user.userInfo<br/>
3、js 内获得Vuex数据:<br/>
let userInfo = vk.state('$user').userInfo;<br/>
4、js 内更新Vuex数据:<br/>
vk.vuex('$user.userInfo.avatar', avatar);<br/>
</view>
</view>
<view v-if="$user.userInfo" style="color: red;margin-top: 10rpx;font-size: 36rpx;">
当前登录用户:{{ $user.userInfo.nickname || $user.userInfo.username}}
<u-avatar :src="$user.userInfo.avatar" size="70"></u-avatar>
</view>
<view style="margin-top: 20rpx;">
<input type="text" v-model="form1.username" placeholder="用户名/邮箱/手机号" />
<input type="text" v-model="form1.password" password="true" placeholder="密码" />
<button type="default" @tap="register">注册</button>
<button type="default" @tap="login">登录</button>
<button type="default" @tap="uploadAvatar">上传到云储存(并设置为头像)</button>
<button type="default" @tap="logout">退出</button>
</view>
</view>
......@@ -52,7 +66,7 @@
data:form1,
success:function(data){
// 登录成功后将用户信息写入$store
that.$store.dispatch('user/setUserInfo',data.userInfo);
vk.vuex('$user.userInfo', data.userInfo);
vk.alert("登陆成功!");
}
});
......@@ -62,11 +76,43 @@
vk.userCenter.logout({
success:function(data){
// 退出成功后清楚$store的用户信息
that.$store.dispatch('user/setUserInfo',"");
vk.vuex('$user.userInfo', '');
vk.alert("退出成功");
}
});
},
// 上传头像到云储存,并设置为头像
uploadAvatar(){
// 选择图片
uni.chooseImage({
count: 1,
sizeType: ['compressed'],
success: function (res) {
// 上传图片到云储存
vk.callFunctionUtil.uploadFile({
title:"上传中...",
filePath: res.tempFilePaths[0],
fileType: "image",
success(res) {
// 执行绑定头像
vk.userCenter.setAvatar({
data: {
avatar: res.fileID,
},
success() {
// 修改Vuex用户状态
vk.vuex('$user.userInfo.avatar', res.fileID);
}
});
}
});
}
});
}
},
// 计算属性
computed:{
}
}
</script>
......@@ -100,5 +146,4 @@
color: #999999;
margin-bottom: 20px;
}
</style>
</style>
\ No newline at end of file
......@@ -2,18 +2,72 @@ import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
// 定义不需要永久存储的目录,即下次APP启动数据会自动清空,值为在modules目录下的文件名
let notSaveStateKeys = ['$test'];
let lifeData = uni.getStorageSync('lifeData') || {};
const modulesFiles = require.context('./modules', true, /\.js$/);
modulesFiles.keys().map((modulePath, index) => {
let moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, '$1')
if(notSaveStateKeys.indexOf(moduleName) === -1) {
if(!lifeData[moduleName]) lifeData[moduleName] = {};
}
});
uni.setStorageSync('lifeData', lifeData);
// 保存变量到本地存储中
const saveLifeData = function(key, value){
// 判断变量名是否在需要存储的数组中
if(notSaveStateKeys.indexOf(key) === -1) {
// 获取本地存储的lifeData对象,将变量添加到对象中
let tmp = uni.getStorageSync('lifeData');
// 第一次打开APP,不存在lifeData变量,故放一个{}空对象
tmp = tmp ? tmp : {};
tmp[key] = value;
// 执行这一步后,所有需要存储的变量,都挂载在本地的lifeData对象中
uni.setStorageSync('lifeData', tmp);
}
}
// 加载modules目录下所有文件(分模块)
const modulesFiles = require.context('./modules', true, /\.js$/)
const modules = modulesFiles.keys().reduce((modules, modulePath) => {
const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, '$1')
const value = modulesFiles(modulePath)
modules[moduleName] = value.default
return modules
}, {})
const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, '$1')
const value = modulesFiles(modulePath)
modules[moduleName] = value.default
return modules
}, {});
const store = new Vuex.Store({
modules,
// 如果是开发环境,则开启严格模式
strict: process.env.NODE_ENV === 'development'
modules,
// 如果是开发环境,则开启严格模式
strict: process.env.NODE_ENV === 'development',
// 公共 mutations
mutations: {
updateStore(state, payload) {
// 判断是否多层级调用,state中为对象存在的情况,诸如user.info.score = 1
let nameArr = payload.name.split('.');
let saveKey = '';
let len = nameArr.length;
if(len >= 2) {
let obj = state[nameArr[0]];
for(let i = 1; i < len - 1; i ++) {
obj = obj[nameArr[i]];
}
//Vue.set(obj,nameArr[len - 1],payload.value)
obj[nameArr[len - 1]] = JSON.parse(JSON.stringify(payload.value));
saveKey = nameArr[0];
} else {
// 单层级变量,在state就是一个普通变量的情况
state[payload.name] = JSON.parse(JSON.stringify(payload.value));
saveKey = payload.name;
}
// 保存变量到本地,见顶部函数定义
saveLifeData(saveKey, state[saveKey])
}
}
})
export default store
export default store
\ No newline at end of file
import { mapState, mapGetters } from 'vuex'
import store from "@/store"
// 尝试将用户在根目录中的store/index.js的vuex的state变量,全部加载到全局变量中
let mapStateKey = store.state ? Object.keys(store.state) : [];
let mapGettersArr = store.getters ? Object.keys(store.getters) : [];
let mapGettersKey = {};
for(let index in mapGettersArr){
let key = mapGettersArr[index].replace('/', '_');
mapGettersKey[key] = mapGettersArr[index];
}
module.exports = {
beforeCreate() {
// 将vuex方法挂在到vk实例中
// 使用方法为:如果要修改vuex的state中的user.name变量为"史诗" => this.vk.vuex('user.name', '史诗')
// 如果要修改vuex的state的version变量为1.0.1 => this.vk.vuex('version', '1.0.1')
this.vk.vuex = (name, value) => {
this.$store.commit('updateStore', {
name,
value
})
};
this.vk.state = (name) => {
let value = this.$store.state[name];
return JSON.parse(JSON.stringify(value));
};
this.mapGetters = mapGetters;
},
computed: {
// 将vuex的state中的所有变量,解构到全局混入的mixin中
...mapState(mapStateKey),
// 将vuex的getters中的所有函数,解构到全局混入的mixin中
...mapGetters(mapGettersKey)
}
}
\ No newline at end of file
/**
* vuex 用户状态管理模块
* import store from "@/store";
*/
let lifeData = uni.getStorageSync('lifeData') || {};
export default {
// 通过添加 namespaced: true 的方式使其成为带命名空间的模块
namespaced: true,
/**
* vuex的基本数据,用来存储变量
* 调用示例
* that.$store.state.user.userInfo
*/
state: {
// 登录用户的信息
userInfo: uni.getStorageSync("uni_id_user_info")
/**
* 登录用户信息
* js调用示例
* (推荐) vk.state('$user').userInfo;
* 或 that.$store.state.$user.userInfo;
* 页面上直接使用示例
* {{ $user.userInfo }}
* js更新示例
* vk.vuex('$user.userInfo.avatar', res.fileID);
*/
userInfo: lifeData.$user.userInfo
},
/**
* 从基本数据(state)派生的数据,相当于state的计算属性
* 调用示例
* that.$store.getters['user/getUserInfo']
*/
getters: {
/**
* 获取用户信息(使用计算属性获取)
* js调用示例
* that.$store.getters['$user/getUserInfo'];
* 页面上直接使用示例
* {{ $user_getUserInfo }}
*/
getUserInfo: (state) => {
return state.userInfo;
}
......@@ -28,29 +41,16 @@ export default {
* 提交更新数据的方法,必须是同步的(如果需要异步使用action)。
* 每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。
* 回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数,提交载荷作为第二个参数。
* 调用示例
that.$store.commit('user/setUserInfo',{
username:"admin"
});
*/
mutations: {
setUserInfo: (state, userInfo) => {
state.userInfo = userInfo
}
},
/**
* 和mutation的功能大致相同,不同之处在于 ==》
* 1. Action 提交的是 mutation,而不是直接变更状态。
* 2. Action 可以包含任意异步操作。
* 调用示例
that.$store.dispatch('user/setUserInfo',{
username:"admin"
});
*/
actions: {
setUserInfo (context, userInfo) {
uni.setStorageSync("uni_id_user_info", userInfo);
context.commit('setUserInfo',userInfo)
}
}
}
}
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册