26 前端封装(简单实用vuex,封装权限验证操作,js-promise,async+await,封装请求模块)
26 前端封装
(简单实用vuex,封装权限验证操作,js-promise,async+await,封装请求模块)
一 使用vuex(简单调用)
可以参考drf系列的这篇文章:https://www.cnblogs.com/zhangmingyan/articles/11791597.html
新建store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state:{
loginStatus:false
},
mutations:{
changeLoginStatus(state,{num}){
state.loginStatus = num
}
}
})
修改main.js
import Vue from 'vue'
import App from './App'
import store from './store/index.js';
Vue.prototype.$store = store
Vue.config.productionTip = false
// 引入全局组件
import divider from './components/common/divider.vue';
Vue.component('divider',divider)
import noThing from './components/common/no-thing.vue';
Vue.component('no-thing',noThing)
// 引入配置文件
import $C from './common/config.js';
Vue.prototype.$C = $C
// 挂在助手函数库
import $U from './common/util.js';
Vue.prototype.$U = $U
App.mpType = 'app'
const app = new Vue({
store,
...App
})
app.$mount()
在项目的任意位置皆可以this.$store调用
二 封装跳转权限验证层
思路:
1 实现如点赞点踩需要登录的操作,通过加了一个权限操作验证,如果没有登录跳转到登录页面
2 实现如跳转到发朋友圈的页面,通过加了一个权限跳转验证,如果没有登录先跳转到登录页面
如果是python技术站,可以简单理解为搞了个装饰器。
代码:
Main.js(关注两个权限验证字眼)
import Vue from 'vue'
import App from './App'
import store from './store/index.js'
// 原型上有这个store
Vue.prototype.$store = store
Vue.config.productionTip = false
// 组册全局组件
import divider from './components/common/divider.vue';
import noThing from './components/common/no-thing.vue'
Vue.component('divider',divider)
Vue.component('no-thing',noThing)
// 引入配置文件
import $C from './common/config.js';
Vue.prototype.$C = $C
// 挂在助手函数库
import $U from './common/util.js';
Vue.prototype.$U = $U
// 权限验证操作
Vue.prototype.checkAuth = (callback) =>{
// 权限验证
if (!store.state.loginStatus){
uni.showToast({
title:'请先登录',
icon:'none'
});
return uni.navigateTo({
url:'/pages/login/login'
})
}
// js叫回掉函数,其实和装饰器差不多。
callback()
}
// 权限验证跳转
Vue.prototype.navigateTo = (options)=>{
// 权限验证
if (!store.state.loginStatus){
uni.showToast({
title:'请先登录',
icon:'none'
})
return uni.navigateTo({
url:'/pages/login/login'
})
}
uni.navigateTo(options)
}
App.mpType = 'app'
// 实例化的app加载 store里面的内容。
const app = new Vue({
store,
...App
})
app.$mount()
Common-list.vue
// 关注事件
follow(){
//console.log('点击了关注')
// 通知父组件
this.checkAuth(()=>{
this.$emit('follow',this.index)
}
)
},
// 顶踩操作
doSupport(type){
// console.log(type)
// 先经过权限验证,如果验证通过了再回掉这个传入的箭头函数。
this.checkAuth(()=>{
this.$emit('doSupport',{
type,
index:this.index
})
})
},
// 评论
doComment(){
this.checkAuth(()=>{
if (!this.isdetail) {
return this.openDetail()
}
this.$emit('doComment')
})
},
index.vue
// 监听导航按钮点击事件
onNavigationBarButtonTap() {
// 使用自己封装的权限验证跳转
this.navigateTo({
url: '../add-input/add-input',
})
},
三 promise方法:
核心:
0 promise 是异步的不会阻塞下面代码。
1 promise对象支持.then(res=>{}).catch(err=>{})
2 promise对象代码体内 resolve(xxx) 触发---->其对象的.then() 方法并且把xxx传给res 执行then内的回掉函数
3 promise对象代码体内 reject(yyy) 触发---->其对象的.catch() 方法并且把yyy传给err 执行catch内的回掉函数
其实就是监听内部的resolve以及reject,resolve会触发then,resolve的内容并且作为then内部回掉函数的参数,reject会触发catch,同理resolve。
简单使用:
//ps:这个resolve,reject重要的是位置不是名字,叫啥都行。
new Promise(function (resolve, reject) {
log('start new Promise...');
var timeOut = Math.random() * 2;
log('set timeout to: ' + timeOut + ' seconds.');
setTimeout(function () {
if (timeOut < 1) {
log('call resolve()...');
resolve('200 OK');
}
else {
log('call reject()...');
reject('timeout in ' + timeOut + ' seconds.');
}
}, timeOut * 1000);
}).then(function (r) {
log('Done: ' + r);
}).catch(function (reason) {
log('Failed: ' + reason);
});
ps:直接看下方标题七 实际案例
参考博客:
参考博客:https://www.liaoxuefeng.com/wiki/1022910821149312/1023024413276544
代码以及执行效果:
其实就是监听内部的resolve以及reject,resolve会触发then,resolve的内容并且作为then内部回掉函数的参数,reject会触发catch,同理resolve。
###### 案例1 ajax案例
use strict';
// ajax函数将返回Promise对象:
function ajax(method, url, data) {
var request = new XMLHttpRequest();
return new Promise(function (resolve, reject) {
request.onreadystatechange = function () {
if (request.readyState === 4) {
if (request.status === 200) {
resolve(request.responseText);
} else {
reject(request.status);
}
}
};
request.open(method, url);
request.send(data);
});
}
var log = document.getElementById('test-promise-ajax-result');
var p = ajax('GET', '/api/categories');
p.then(function (text) { // 如果AJAX成功,获得响应内容
log.innerText = text;
}).catch(function (status) { // 如果AJAX失败,获得响应代码
log.innerText = 'ERROR: ' + status;
});
// 输出:ERROR: 400
###### 案例二连续计算案例
// 0.5秒后返回input*input的计算结果:
function multiply(input) {
return new Promise(function (resolve, reject) {
log('calculating ' + input + ' x ' + input + '...');
setTimeout(resolve, 500, input * input);
});
}
// 0.5秒后返回input+input的计算结果:
function add(input) {
return new Promise(function (resolve, reject) {
log('calculating ' + input + ' + ' + input + '...');
setTimeout(resolve, 500, input + input);
});
}
var p = new Promise(function (resolve, reject) {
log('start new Promise...');
resolve(123);
});
p.then(multiply)
.then(add)
.then(multiply)
.then(add)
.then(function (result) {
log('Got value: ' + result);
});
四 补充async+await方法
拓展连接:
https://segmentfault.com/a/1190000007535316
http://www.ruanyifeng.com/blog/2015/05/async.html
核心():
-
一旦调用了个async a()函数如,x = a() , 那么相当于x 直接隐式的拿到了个promise对象,此时a并没有执行内部的代码。a执行的时候如果一旦发生return行为,那么就相当于promise的resolve行为,也就会传给x.then了。
-
ps特殊的情况: async执行的时候里面的有异步代码就会跳过接着往下执行,就相当于去函数的结束的位置return了个null,也就相当于这个async的then等到了resolve行为,然并卵里面的异步并没有执行完。
-
根据上一条,想使用then等完async 那么要把里面的异步统统await,然后发生return也就是发生resolve然后执行then里的逻辑。
-
async 定义的函数里面的return的内容直接封装成了promise的resolve值,async函数直接可以进行then操作。
-
await要写在async定义的函数内部,await 了一个promise对象则会阻塞进行等待这个promise对象完事儿。await的不是promise对象则正常执行(相当于没写await)。
第一点:async 是一个修饰符,async 定义的函数会默认的返回一个Promise对象resolve的值.
就算你不写, 直接return 任何, 它都会封装一下,让你return的东西相当于Promise的resolve() ,就是这么刚!
// 这俩效果是一样的
function getData_1 () {
return '100'
}
function getData_2 () {
return new Promise((resolve, reject) => {
resolve('100')
})
}
// 0. async基础用法测试
async function fun0() {
console.log(1)
return 1
}
fun0().then( x => { console.log(x) }) // 输出结果 1, 1,
async function funa() {
console.log('a')
return 'a'
}
funa().then( x => { console.log(x) }) // 输出结果a, a,
async function funo() {
console.log({})
return {}
}
funo().then( x => { console.log(x) }) // 输出结果 {} {}
async function funp() {
console.log('Promise')
return new Promise(function(resolve, reject){
resolve('Promise')
})
}
funp().then( x => { console.log(x) }) // 输出promise promise
第二点 await 也是一个修饰符
概念:
1) await 关键字 只能放在 async 函数内部, await关键字的作用 就是获取 Promise中返回的内容, 获取的是Promise函数中resolve或者reject的值
2) 如果await 后面并不是一个Promise的返回值,则会按照同步程序返回值处理(就相当于await失效)
三个小案例带你走向人生巅峰:
//----------------- 1.await后面跟着的是promise对象则会等待。--------------------
// await 关键字 只能放在 async 函数内部, await关键字的作用 就是获取 Promise中返回的内容, 获取的是Promise函数中resolve或者reject的值
// 如果await 后面并不是一个Promise的返回值,则会按照同步程序返回值处理,为undefined
const bbb = function(){ return 'string'}
async function funAsy() {
const a = await 1
const b = await new Promise((resolve, reject)=>{
setTimeout(function(){
resolve('time')
}, 3000)
})
const c = await bbb()
console.log(a, b, c)
}
funAsy() // 运行结果是 3秒钟之后 ,输出 1, time , string,
//----------------- 2.await后面跟着的不是promise对象则不会等待。---------------------
function log2(time) {
setTimeout(function(){
console.log(time)
return 1
}, time)
}
async function fun1() {
const a = await log2(5000)
const b = await log2(10000)
const c = log2(2000)
console.log(a)
console.log(1)
}
fun1()
// 以上运行结果为: 立刻输出undefined 立刻输出1 2秒后输出2000 5秒后输出5000 10秒后输出10000
//----------------- 3 async / await 后面凡是promise对象必等其结束再往下运行。---------------------
const asy = function(x, time) {
return new Promise((resolve, reject) =>{
setTimeout(()=>{
resolve(x)
}, time)
})
}
const add = async function() {
const a = await asy(3, 5000)
console.log(a)
const b = await asy(4, 10000)
console.log(b)
const c = await asy(5, 15000)
console.log(a,b,c)
const d = a + b +c
console.log(d)
}
add();
// 5秒后输出3 又10秒后输出4 又15秒后输出5 然后立刻输出3,4,5,然后输出12
五 封装请求模块(简单封装)
思路:
1 就是把原有的uni.request(xxx)里面的xxx封装起来更方便我们使用。
2 封装的时候要注意一点异步的方法,如果不传入 success、fail、complete 等 callback 参数,将以 Promise 返回数据。(人话:如果不传入success,fail...这些方法 。request就会返回个promise对象,就可以使用then和catch了)
代码:
common/request.js
import $C from '@/common/config.js'
export default {
common:{
method:'GET',
header:{
"content-type":"application/json"
},
data:{}
},
request(options = {}){
options.url = $C.webUrl + options.url
options.method = options.method || this.common.method
options.header = options.header || this.common.header
// 验证权限token
// 该有的参数传入进去,返回了一个promise对象可以直接.then使用了就。
return uni.request(options)
},
get(url, data={}, options={}){
options.url = url
options.data = data
options.method = 'GET'
return this.request(options)
},
post(url, data={}, options={}){
options.url = url
options.data = data
options.method = 'POST'
return this.request(options)
},
}
main.js 挂载一下
// 挂载请求模块
import $H from './common/request.js'
Vue.prototype.$H = $H
pages/index/index.vue测试
// 获取分类
// this.$H.get('/postclass').then(res=>{
// let [err,result] = res
// console.log(result);
// })
let res = await this.$H.get('/postclass')
let [err,result] = res
console.log(result);