Aries Man

Personal Center


  • 首页

  • 归档

js通过位运算实现权限加解密

发表于 2019-02-21

首先介绍一下js中的位运算

  • “&” :与运算,转化为二进制数,如果相同位数都为1则得结果为1,否则为0
  • “|” :或运算,转化为二进制数,如果相同位数只要有一个为1则得结果为1,否则为0
  • “^” :异或运算,转化为二进制数,如果相同位数不同则得结果为1,否则为0
  • “<<” 异位运算符,1<<1,表示将1左移一位,也就是010,在二进制中代表2

十进制数字互相转化

  • 十进制转为别的进制
1
2
3
var num = 123;
console.log(num.toString(2))
console.log(num.toString(8))//参数传想要转化的位数
  • 别的进制转化为十进制
1
2
var num = 110;
console.log(parseInt(num,2))//二进制转化为十进制

假设我们现在有5项权限,在二进制中用1代表拥有权限,0代表不拥有。所以11111这样代表拥有所有的五项权限,那么我们如何知道用户是否有某一项具体权限呢。

比如,我们现在想检测用户是否有第一项权限,我们首先用过异位 1 << 0,向左移0位,还是1,然后1 & (Math.pow(2,5) -1),

如果返回0,说明个位对不上,也就是说我们当前没有权限,如果返回1,说明我们拥有第一项权限,同理,如果需要检验第二位权限,只需要异位2就好了。

1
2
3
4
5
6
7
if((1 << 0) & (Math.pow(2,5) - 1) !== 0){
//拥有第一项权限权限
}

if((1 << 1) & (Math.pow(2,5) - 1) !== 0){
//拥有第二项权限权限
}

上面写的是大概原理,可能初次接触有点绕,下面我给大家举几个详细的例子说明:

首先需要说明的是 1 << 0,相当于,2的零次方,1<<1,结果是2的一次方,所以上面我用了,Math.pow()这个方法。我们现在来验证一下我们使用上述方法是否能准确的判断权限。

假设,我们拥有第三项权限,那么就是 1 << 2,也就是十进制的4,二进制的100,第三位为1,代表有权限,跟我们预想的一致。然后跟2的5次方减1进行与运算,也就是31,结果为4,为什么会得到4呢,因为与运算相同为1,不同为0,也就是结果为00100的二进制数,说明我们拥有第三项权限。

  • 接下来介绍权限的计算,也就是说我有第一、三项权限,那么代表我权限的值是多少呢。

我们可以这样计算:

你拥有第一项,所以应该是1<<1,也就是1,拥有第三项权限,也就是1<<2,也就是4, 2 + 4 =5,5就是代表你权限的数字。

验证一下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
1 << 0
//1
1 & 5
//1 非0,说明拥有第一项权限

1 << 2
//4
4 & 5
//4 非0,说明拥有第三项权限

1 << 1
//2
2 & 5
//0 为0,说明没有第二项权限

php-tp5

发表于 2019-02-21

开启错误信息,调试模式

开发的时候可能会出错,但是如果不开启错误信息以及调试模式的话,只会返回页面错误,所以我们可以在application/config.php中开启错误信息以及调试模式,方便开发

绑定模块

tp5默认模块为index,所以访问时需要,域名/index.php/模块名/控制器/方法名
配置完成后,就不需要输入模块名了,绑定方法如下

在public/index.php中增加内容

1
define('BIND_MODULE', 'index');

如果你有多个模块,可以新建admin.php等,在里面绑定不同的模块

绑定扩展

有时候我们需要封装一些方法,这些方法可以放在extra目录下,但是还需要绑定,同样的,在public/index.php中增加

1
define('EXTEND_PATH','../extend/');

然后就可以定义我们自己的类,使用时

1
use extend下的目录名\类名

这样就可以了

ionic

发表于 2019-02-21

ts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
import { Component } from '@angular/core';
import { NavController, NavParams,ModalController,ViewController, LoadingController, ToastController } from 'ionic-angular';
import { LoginPage } from "../login/login";
import { UserPage } from "../user/user";
import { Storage } from "@ionic/storage";
import { BaseUi } from "../../common/baseui";
import { BookmarkPage } from "../bookmark/bookmark";
import { RestProvider } from "../../providers/rest/rest";
import {SettingProvider} from "../../providers/setting/setting";

/**
* Generated class for the PersonalCenterPage page.
*
* See https://ionicframework.com/docs/components/#navigation for more info on
* Ionic pages and navigation.
*/

@Component({
selector: 'page-personal-center',
templateUrl: 'personal-center.html',
})

export class PersonalCenterPage extends BaseUi{
public notLogin : boolean = true;
public logined : boolean = false;
public bookmark:any;
public font:string;
public nick_name:string;
public errorMessage:any;
public url:string;
selectedTheme: string;
constructor(public navCtrl: NavController,
public navParams: NavParams,
public modalCtrl : ModalController,
public viewCtrl:ViewController,
public loadingCtrl: LoadingController,
public toastCtrl: ToastController,
public storage:Storage,
public rest:RestProvider,
public settings:SettingProvider) {
super();
this.settings.getActiveTheme().subscribe(val => this.selectedTheme = val);
}


changeFonts(){
this.storage.set('font',this.font);
}
showModal(){
let modal = this.modalCtrl.create(LoginPage);
modal.onDidDismiss(this.getUserInfo);
modal.present();
}

showBookmark(){
let modal = this.modalCtrl.create(BookmarkPage);
modal.present();
}

ionViewDidEnter(){
this.getUserInfo();
}

getUserInfo(){
this.storage.get('user').then((f)=>{
if(f){
var loading = super.showLoading(this.loadingCtrl,'加载中...');
this.rest.getUerInfo(f).subscribe((val)=>{
loading.dismiss();
if(val['status'] == 0){
this.nick_name = val['msg']['nick_name'] ? val['msg']['nick_name'] : f;
this.url = val['msg']['upload_time'] ? 'http://111.231.54.181/static/uploads/headface/' + val['msg']['upload_time'] + '/' + val['msg']['url'] : './assets/imgs/avatar.jpg';
this.notLogin = false;
this.logined = true;
}
},
error => {
this.errorMessage = <any>error;
this.notLogin = true;
this.logined = false;
loading.dismiss();
});
}
else{
this.notLogin = true;
this.logined = false;
}
});
//初始化字体
this.storage.get('font').then((f)=>{
if(f){
this.font = f;
}
else{
this.font = '0';
}
});
}

gotoUserPage(){
this.navCtrl.push(UserPage);
}

toggleChangeTheme() {
if (this.selectedTheme === 'dark-theme') {
this.settings.setActiveTheme('light-theme');
}
else {
this.settings.setActiveTheme('dark-theme');
}
}

}

html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
<ion-header>

<ion-navbar>
<ion-title>更多</ion-title>
</ion-navbar>

</ion-header>

<ion-content>
<ion-card *ngIf="notLogin">
<ion-card-header text-center>
登陆 sexybook,体验更多功能
</ion-card-header>
<ion-card-content text-center>
<button ion-button outline small color="secondary" (click)="showModal()">登陆/注册</button>
</ion-card-content>
</ion-card>


<ion-list *ngIf="logined">
<button ion-item (click)="gotoUserPage()">
<ion-avatar item-start>
<img src="{{this.url}}" alt="">
</ion-avatar>
<h2>{{this.nick_name}}</h2>
<p>查看个人主页或编辑简介</p>
</button>
</ion-list>

<ion-list>
<ion-list-header>
设置
</ion-list-header>
<ion-item>
<ion-icon name="eye" color="primary" item-start><ion-icon>
<ion-label>夜间模式</ion-label>
<ion-toggle (ionChange)="toggleChangeTheme()"></ion-toggle>
</ion-item>

<ion-item>
<ion-icon name="resize" item-start color="danger"></ion-icon>
<ion-label>字体大小</ion-label>
<ion-select [(ngModel)]="font" cancelText="取消" okText="确定" (ngModelChange)="changeFonts()">
<ion-option value="0">默认</ion-option>
<ion-option value="1">中</ion-option>
<ion-option value="2">大</ion-option>
</ion-select>
</ion-item>

<button ion-item (click)="showBookmark()">
<ion-icon name="pricetag" item-start color="secondary"></ion-icon>
<ion-label>我的书签</ion-label>
</button>
</ion-list>

<ion-list>
<ion-list-header>
关于
</ion-list-header>
<ion-item>
<ion-icon name="settings" item-start></ion-icon>
<ion-label item-content>系统版本</ion-label>
<p item-end>1.0.0</p>
</ion-item>
</ion-list>

</ion-content>

工作中遇到的一些问题

发表于 2019-02-21

关于js操作改变input值,不触发onchange事件

input onchange是失去焦点以后触发的,我们通过js去操作它一直没有获得焦点,也就不会触发。
同理,也不会触发oninput,因为oninput是用户修改内容时才会触发。解决方法就是手动调用。

H5本地上传获取真实路径兼容写法

1
2
3
4
5
6
7
8
9
10
11
12
13
function getFileUrl(fileId) { 
var url;
var file = document.getElementById(fileId);
var agent = navigator.userAgent;
if (agent.indexOf("MSIE")>=1) {
url = file.value;
} else if(agent.indexOf("Firefox")>0) {
url = window.URL.createObjectURL(file.files.item(0));
} else if(agent.indexOf("Chrome")>0) {
url = window.URL.createObjectURL(file.files.item(0));
}
return url;
}

s对象、数组,改变原数据后新数据也随之改变

1
2
3
4
var a = {'num':1};//原数据
var b = a;//假设我们用b来存储
a.num = 2;//对原数据进行一些改变
console.log(b.num);//2

上面这种方法是达不到我们想要的效果的,因为实际在给b赋值时,是进行了传址操作,也就是说让b跟a指向同一个地址,实际数据只有一份,所以a改变时b也会随之改变。
一般的解决方法有深拷贝、转化为字符串。深拷贝可以去我的另一篇JS进阶里面有个extend方法,实际就是循环递归,拷贝一份一模一样的出来,下面简单写一下字符串转化的方法。

1
2
3
4
var a = {'num':1};
var b = JSON.stringify(a);
a.num = 2;
console.log(JSON.parse(b.num));//1

打造自己的js库

发表于 2019-02-21

随着code经验的增加,函数封装,可复用性组件开发可以说是一个水到渠成的过程,最近一直想写一个属于自己的js库,将自己用的较多的组件都放在里面,但是也一直被搁置,因为我感觉自己目前能力可能不够,但是不试试怎么知道呢。只要尝试,就算不成功,对自己也是宝贵的经验。

万事开头难,这一步很关键,使用命名空间避免冲突,将方法绑定到window上。ps:能有今天的成长,大部分归功于前辈们的代码通过解读能学到很多东西,感谢!

1
2
3
4
5
6
7
8
9
10
11
12
13
namespace = function(){
var args = arguments; //函数内部args为参数长度
for(var i = 0;i<args.length;i++){ //循环截取参数绑定到window上边
var objs = args[i].split('.');
var obj = window;
for(var j = 0;j<objs.length;j++){
obj[objs[j]] = obj[objs[j]] || {};
obj = obj[objs[j]]
}
}
return obj
}
namespace("gu.base")//启动方式

运行完成后,window上边会绑定gu,gu下边有方法base,然后在gu.base上边进行函数扩展。

  • base
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
namespace('gu.base');

(function () {
/**
* 获取传入参数类型
* @param {object} obj
* @return {string}
* @date 2017-11-16
*/
function getParamType (obj) {
return (obj == null ? String(obj) : Object.prototype.toString.call(obj).replace(/\[object\s+(\w+)\]/i,"$1") || "object").toLowerCase();
};

/**
* 类似$.extend()
* @param destination
* @param source
* @return {object} destination
* @date 2017-11-16
*/
gu.base.extend = function (destination,source) {
if (destination == null) {
destination = source
}
else {
for (var property in source){
if (getParamType(source[property]).toLowerCase() === "object" &&
getParamType(destination[property]).toLowerCase() === "object" )
arguments.callee(destination[property], source[property])
else
destination[property] = source[property];
}
}
return destination;
};

gu.base.isArray = function (obj) {
return getParamType(obj) === "array";
};

gu.base.isObject = function (obj) {
return getParamType(obj) === "object";
};

gu.base.isFunction = function (obj) {
return getParamType(obj) === "function";
};

gu.base.isString = function (obj) {
return getParamType(obj) === "string";
};

gu.base.isBoolean = function (obj) {
return getParamType(obj) === "boolean";
};

gu.base.isDate = function (obj) {
return getParamType(obj) === "date"
};
gu.base.g = function (id) {
return document.getElementById(id);
}

})();
gu.base.extend(window, gu.base);
  • date
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
namespace('gu.date');

extend(gu.date,{
/**
*获取日期,默认日期为今天,默认分隔符为'-'
* @param time
* @returns {string}
* @date 2017-11-21
*/
toDateString:function (time) {
var time = time ? time : new Date(),
m = time.getMonth(),
d = time.getDay(),
y = time.getFullYear(),
separator = arguments[1] ? arguments[1] : '-';

return y + separator + (m.toString().length < 2 ? '0' + m : m) +separator +(d.toString().length < 2 ? '0' + d : d);
},
/**
* 获取日期以及时间,默认日期为今天,默认分隔符为'-'
* @param time
* @returns {string}
* @date 2017-11-21
*/
toDateTimeString:function (time) {
var time = time ? time : new Date(),
h = time.getHours(),
i = time.getMinutes(),
s = time.getSeconds();

return gu.date.toDateString.apply(this,arguments) + " " + (h.toString().length < 2 ? '0' + h : h)+ ":" + (i.toString().length < 2 ? '0' + i : i)+ ":" + (s.toString().length < 2 ? '0' + s : s);
}
});
  • load
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
namespace('gu.load');

extend(gu.load,{
/**
* 加载js
* @param url
* @param callback
* @returns {boolean}
* @date 2017-11-21
*/
loadScript:function (url, callback) {
var head = document.getElementsByTagName("head")[0];
var script = document.createElement("script");
script.type = "text/javascript";
script.charset = 'GBK';
script.src = url;
var timeout = setTimeout(
function (){
head.removeChild(script);
callback.call(this,false);
},
50
);

script.onload = function () {
head.removeChild(script);
clearTimeout(timeout);
callback();
};
head.appendChild(script);
return true;
},
/**
* 加载css
* @param url
* @param callback
* @date 2017-11-21
*/
loadCss:function (url, callback) {
var head = document.getElementsByTagName("head")[0];
var link = head.appendChild(
document.createElement("link")
);
link.href = url;
link.rel = 'stylesheet';
callback.call(this,true);
}
});

extend(window,gu.load);
  • cookie
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
namespace('gu.cookie');

extend(gu.cookie,{
/**
* 设置cookie,最好先用navigator.cookieEnable判断一下cookie是否可用
* @param key
* @param value
* @param expires
* @param domain
* @param path
* @returns {boolean}
*/
set:function (key,value,expires,domain,path) {
var cValue,cExpires,cDomain,cPath,cookieArr = [];
if(!key){
return false;
}
cValue = value ? encodeURIComponent(value) : '';
cookieArr.push(key + "=" + cValue);
if(!isNaN(expires)){
var time = new Date();
time.setTime(time.getTime()+(expires*24*60*60*1000));
cExpires = time.toGMTString();
cookieArr.push('expires=' + cExpires);
}
if(domain != undefined){
cDomain = domain;
cookieArr.push('domain=' + cDomain);
}
if(path != undefined){
cPath = path;
cookieArr.push('path=' + cPath);
}
document.cookie = cookieArr.join('; ');
},
/**
* 获取cookie
* @param key
* @returns {string}
*/
get:function (key) {
var cookieArr = document.cookie.split('; ');
for(var i=0;i<cookieArr.length;i++){
if(cookieArr[i].indexOf(key) == 0){
return decodeURIComponent(cookieArr[i].substring(cookieArr[i].split('=')[0].length + 1,cookieArr[i].length));
}
}
},
/**
* 清除cookie
* @param key
* @param domain
*/
clear:function (key,domain) {
var cDate = new Date();
gu.cookie.set(key,"",-2,domain);
}
});
  • string
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
namespace('gu.string');
extend(gu.string,{
/**
* 获得字节数,中文2
* @param str
* @returns {number}
*/
getByteLength:function (str) {
var bytes = 0;
for(var i=0;i<str.length;i++){
if(str.charCodeAt(i) > 255){
bytes ++
}
bytes ++
}
return bytes;
},
/**
* 去空
* 数据库中utf-8占三个字符,gbk占俩
* @param str
* @returns {XML|string|*}
*/
trim:function (str) {
str = str.replace(/\s+$/,'').replace(/^\s+/,'');
return str;
}
});
  • config
1
2
3
4
namespace('gu.config');
extend(gu.config,{
host:'//111.231.54.181'
});
  • ajax通用部分封装
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
(function ($) {
$.ajaxSetup({
dataType:'json',
beforeSend:function (xhr) {
xhr.withCredentials = true;
commTool.loadingOpen();
},
complete:function () {
commTool.loadingClose();
},
error:function () {
commTool.msg('网络无法连接,请稍后再试。');
}
});
})(jQuery);

vue项目搭建

发表于 2019-01-13

模仿搭建vue-cli

其实vue-cli本身就挺好用的,但是毕竟自己亲手搭的还是比较灵活,出了问题也方便解决,所以我们自己动手搭建一个脚手架

主要用到的工具

  • webpack
  • webpack-cli

package.json配置如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
{
"name": "book",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "cross-env NODE_ENV=development webpack-dev-server",
"build": "cross-env NODE_ENV=production webpack"
},
"author": "",
"license": "ISC",
"devDependencies": {
"babel-core": "^6.26.3",
"babel-loader": "^7.1.5",
"babel-preset-es2015": "^6.24.1",
"config": "^3.0.1",
"cross-env": "^5.2.0",
"css-loader": "^2.1.0",
"file-loader": "^3.0.1",
"gulp": "^4.0.0",
"html-webpack-plugin": "^3.2.0",
"os": "^0.1.1",
"style-loader": "^0.23.1",
"url-loader": "^1.1.2",
"vue": "^2.6.6",
"vue-loader": "^15.6.2",
"vue-router": "^3.0.2",
"vue-template-compiler": "^2.6.6",
"webpack": "^4.29.3",
"webpack-cli": "^3.2.3",
"webpack-dev-server": "^3.1.14"
},
"dependencies": {
"axios": "^0.18.0",
"element-ui": "^2.5.4",
"qs": "^6.6.0"
}
}

webpack.config.js内容如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
const webpack = require('webpack');
const path = require('path');
const VueLoaderPlugin = require('vue-loader/lib/plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const dev_mode = (process.env.NODE_ENV == 'development');
const config =require('config');
const os = require('os');

//获取ip
//注意匹配127.0.0.1的情况
let host = '';
let obj = os.networkInterfaces();
for (n in obj) {
obj[n].map(v => {
/^[0-9]{1,}\.[0-9]{2,}\.[0-9]{1,}\.[0-9]{1,}$/.test(v.address) && (host = v.address)
})
}
module.exports = {
entry:path.join(__dirname,'src/main.js'),
output:{
filename:'index.js',
path:path.resolve(__dirname,'dist')
},
mode: dev_mode ? 'development' : 'production',
module:{
rules:[
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader'
},
{
test: /\.vue$/,
loader:'vue-loader'
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
},
{
test: /\.(gif|jpg|jpeg|woff(2)?|ttf|eot|svg)/,
use: [
{
loader: 'url-loader',
options: {
limit: 1024,
name: '[name].[hash:6].[ext]'
}
},
]
}
]
},
devServer: {
contentBase: path.join(__dirname,'src'),
watchContentBase: true,
hot: true,
port: config.port,
host: '0.0.0.0',
proxy: {
'/index.php': {
target:"http://guying.club",
changeOrigin: true,
secure: false,
},
}
},
plugins:[
new VueLoaderPlugin(),
new HtmlWebpackPlugin(),
]
}

if(dev_mode){
module.exports.plugins = module.exports.plugins.concat([
new webpack.HotModuleReplacementPlugin(),
new webpack.DefinePlugin({
'LOCAL_ADDRESS': JSON.stringify(`http://${host}:${config.port}`)
})
])
}

然后是自己封装的axios请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/**axios封装
* 请求拦截、相应拦截、错误统一处理
*/
import axios from 'axios';
import QS from 'qs';

// 环境的切换
if (process.env.NODE_ENV == 'development') {
axios.defaults.baseURL = LOCAL_ADDRESS;
} else if (process.env.NODE_ENV == 'debug') {
axios.defaults.baseURL = '';
} else if (process.env.NODE_ENV == 'production') {
axios.defaults.baseURL = '';
}



// 请求超时时间
axios.defaults.timeout = 10000;

// post请求头
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8';

// 请求拦截器
axios.interceptors.request.use(
config => {
// 每次发送请求之前判断是否存在token,如果存在,则统一在http请求的header都加上token,不用每次请求都手动添加了
// 即使本地存在token,也有可能token是过期的,所以在响应拦截器中要对返回状态进行判断
return config;
},
error => {
return Promise.error(error);
})

// 响应拦截器
axios.interceptors.response.use(
response => {
if (response.status === 200) {
return Promise.resolve(response);
} else {
return Promise.reject(response);
}
},
//服务器状态码不是200的情况
error => {
if (error.response && error.response.status) {
switch (error.response.status) {
// 401: 未登录
// 未登录则跳转登录页面,并携带当前页面的路径
// 在登录成功后返回当前页面,这一步需要在登录页操作。
case 401:
router.replace({
path: '/login',
query: { redirect: router.currentRoute.fullPath }
});
break;
// 403 token过期
// 登录过期对用户进行提示
// 清除本地token和清空vuex中token对象
// 跳转登录页面
case 403:
Toast({
message: '登录过期,请重新登录',
duration: 1000,
forbidClick: true
});
// 清除token
localStorage.removeItem('token');
store.commit('loginSuccess', null);
// 跳转登录页面,并将要浏览的页面fullPath传过去,登录成功后跳转需要访问的页面
setTimeout(() => {
router.replace({
path: '/login',
query: {
redirect: router.currentRoute.fullPath
}
});
}, 1000);
break;
// 404请求不存在
case 404:
Toast({
message: '网络请求不存在',
duration: 1500,
forbidClick: true
});
break;
// 其他错误,直接抛出错误提示
default:
Toast({
message: error.response.data.message,
duration: 1500,
forbidClick: true
});
}
return Promise.reject(error.response);
}
}
);
/**
* get方法,对应get请求
* @param {String} url [请求的url地址]
* @param {Object} params [请求时携带的参数]
*/
export function get(url, params){
return new Promise((resolve, reject) =>{
axios.get(url, {
params: params
})
.then(res => {
resolve(res.data);
})
.catch(err => {
reject(err.data)
})
});
}
/**
* post方法,对应post请求
* @param {String} url [请求的url地址]
* @param {Object} params [请求时携带的参数]
*/
export function post(url, params) {
return new Promise((resolve, reject) => {
axios.post(url, QS.stringify(params))
.then(res => {
resolve(res.data);
})
.catch(err => {
reject(err.data)
})
});
}
  • 初步搭建完成,可以使用了
  • 如果有问题,后续补充

使用了vue-router后页面地址栏路径改变后刷新页面报错

这个主要时由于设置了vue-router为history模式,找不到路由下面的index.html页面,解决方式为配置nginx服务器的try_files,
本地解决方式为配置webpack-dev-server,增加 -history-api-fallback

使用vue-router以后地址栏改变找不到静态资源

配置webpack>output>publicPath:’/‘

vscode

发表于 2018-12-24

设置终端为gitbash

可能有的同学使用linux指令习惯了,所以使用powershell时感觉不是很方便,我们可以设置一下终端为gitbash就可以愉快的使用linux指令了

  • 首先打开设置,然后搜索shell
  • 然后找到这一列terminal.integrated.shellArgs.windows
  • 打击编辑setting.json
  • 然后你就会发现里面有powershell的配置路径,对应换成git目录下的/bin/bash.exe就可以了

自定义ll指令

  • vim ~/.bashrc
  • 输入alias ll= “ls -l”
  • :wq保存并退出
  • source ~/.bashrc //激活指令

vscode一些比较好用的插件

  • vscode的强大之处就是各种各样的插件,需要什么就找什么
  • chinese //中文简体
  • Auto Close Tag //自动闭合标签
  • Auto Rename Tag //重命名标签
  • Live Server //启动本地服务,打开静态页面
  • 一些常用的配置
    {
    “protocol”: “sftp”,
    “host”: “服务器地址”,
    “port”: 22,
    “username”: “username”,
    “password”: “password”,
    “uploadOnSave”: true,//保存后自动上传
    “remotePath”: “要上传的地址”,
    //要忽略的文件
    “ignore”: [
    ".vscode",
    ".git",
    ".DS_Store",
    "**/node_modules"
    
    ]
    }
  • Path Autocomplete //路径智能提示
  • PHP IntelliSense //支持很多php功能,最好用的就是可以启动本地服务,直接调试php页面,不过需要配置php执行文件路径
  • sftp
  • tp5 //tp5框架智能提示
  • Vetur //适用于vue框架

es6

发表于 2018-12-01

函数默认参数设置

1
function test(num = 1){}

如果不传参数,那么num默认为1,相当于

1
2
3
function test(num){
num = num || 1;
}

let、const

let 的出现是为了弥补原生js没有块作用域,只有函数作用域,我们为了不污染全局变量所以采用面向对象的编程方式;使用node也有这方面的原因。 比如上边例子中,let所在区域被称为死区,这一区域完全不受外部影响,所以我们可以把代码写成一块一块互不影响,不用害怕以前使用’var’要考虑作用域以及冲突; 但是使用过程中有几点值得注意,那就是如果重复声明会报错,在声明之前使用也会报错,因为它不存在变量提升

const是为了声明一个常量,不可改变,准确的说是不能改变它的指向的那个内存地址

Class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class getData{
constructor(name){
this.name=name;
}
static plus(name){
return name+'2';
}
start(){
//do some thing
this.ajaxData()
let final=getData.plus(result);

}
ajaxData(){
let param={};
param.length=10;
$.post('url',param,function(data){
console.log(data)
})
}
}

let gy=new getData;
gy.start();

它的原理就是面向对象的编程模式;比如this.ajaxData等同于this.prototype.ajaxData;同样都是在它的原型链上边添加方法或属性;class里面的this一直指向例化它的对象; 但是如果是函数里边的另一个函数,这个时候this就不在指向实例化对象,比如上边的$.post;这个时候我们需要把’.bind(this)’写在$.post后边来改变指针。

constructor是将属性绑定在this上边;

如果一个函数前边写 static ,那么就是指明它是一个静态函数,一般来说都是把一些封装好的方法写成静态函数,比如一些运算或者数据处理等,静态函数只能由class本身调用

箭头函数

1
2
3
4
5
6
7
8
9
10
11
let test=function(num){
return num*num;
}
let test=num=>num*num
```

箭头函数的优势就是简洁方便,不过除了短它还是有优势的,比如它的this也是绑定作用域,准确来说就是它所在的作用域,而不是我们 一般的谁调用指向谁

注意:如果没有参数或者多个参数,那么你需要将参数放在小括号里面,如果不仅仅有一步操作,那么需要把操作放在对象里边。如果需要返回一个对象,需要用小括号包起来, 因为es6会将‘{’解析为块的开始

#### map,set

数组去重
const set=new Set([1,1,2,3,3,4,5])
console.log([…set]) //1,2,3,4,5
属性:size
方法:add,delete,has

1
2
3
4

#### async

相当于使用jQuery的这种写法

let requests = [];
requests.push($.getJSON(url));
requests.push($.getJSON(url1));
$.when().apply(this,requests).done(function(data){
console.log(data)
})

1
2
3
4
5
6
7
8
9
10
11

async function test(){

return new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve('呵呵哒');
})
})
}

返回一个promise对象,我们可以这样处理

test().then(v=>{
console.log(v);
})
`

git

发表于 2018-12-01

初次安装后需全局设置用户名及email

git config --global --list

列出当前全局系统配置,如果需要列举当前仓库的配置,可以吧global更换为local

1
2
git config --global user.name "your name"
git config --global user.email "your email address"

reset

git log

打印出log后按Q退出,log里面会有hash字符串,复制以后git reset hasn字符串,可撤销操作。

git ignore

在git目录下新建 .gitgnore文件

1
2
/node_modules/
!/node_modules/test/ //node_modules里面只有test文件夹正常提交

git branch

新建分支

1
git branch test

切换分支

1
git checkout test

分支合并

1
git merge test

拉取指定分支代码

git pull origin test

推送指定分支代码

git push origin test

cordova热更新

发表于 2018-12-01

热更新原理

通过添加热更新插件生成当前文件时间戳,程序启动后与服务器代码进行比较,如果服务器时间戳大于app时间戳,就从服务器下载文件, 实现自动更新。

安装Cordova-hcp Cli

npm install cordova-hot-code-push-cli -g

安装Cordova-hcp 插件

cordova plugin add cordova-hot-code-push-plugin

配置cordova-hcp.json文件

在项目根目录新建文件cordova-hcp.json

1
2
3
4
5
{
"autogenerated": true,
"content_url": "http://192.168.31.112/www", //服务器路径
"update": "start"
}

配置config.xml文件

1
2
3
4
5
<chcp>
<auto-download enabled="true" />
<auto-install enabled="true" />
<config-file url="http://172.16.1.245:8080/cordova-hot-update/cordova/www/chcp.json" />
</chcp>

运行

cordova-hcp build

12

何足道

14 日志
5 标签
© 2019 何足道
由 Hexo 强力驱动
|
主题 — NexT.Muse v5.1.4