分类 技术宅的演示性文稿 下的文章

造成的原因可能是你的vue-touch安装的版本不对,vue2.0及其以上的版本的项目需要安装的是:npm install vue-touch@next后面的next必须加上,否则安装的vue-touch的版本则是版本1,加上next安装的版本才是2,才可以用于vue2.0构建的项目当中!

作者:kitty_777
链接:https://www.jianshu.com/p/8457348af319
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

总所周知,http是一种无状态协议,而当我们在传统的MVC模式下面,通常情况下是靠session来进行登陆验证。而现在的WEB已经发展到前后端分离的状态了,那么传统模式的session已经不能满足我们的需求。
使用AXIOS与thinkphp进行跨域(非跨域)通信的时候,在服务端是无法使用session的,那么我们怎么来判断用户是否登陆呢?这个时候我们则使用到了现在流行的JWT方法。

JWT是JSON Web Token的缩写JWT的作用是加密和解密。它可以把一堆数据加密,并生成一串密文,也可以把密文解密,还原原始数据。
这样一来就可以用JWT加密个人登录信息,以便个人登录时,并提供密文,以证明自己是合法用户。 例如:把登录后的uid加密形成密文,然后发回个客户端,客户端以后每次都携带密文,访问带有权限验证的页面,服务服务端通过解密,得到uid,说明是已登录过的用户,并开放访问。这样,就必须要求客户端在访问每个需要验证的页面,都必须携带密文,同时在服务端也就不需要使用session验证了。顺便也避免了服务端session数据大的时候,引起的问题。
因为加密的密文不是很长,服务端解密是很快的,所以不会给服务端造成压力。
这样带来的好处是,多种设备使用一种密钥,都可以通用,可以避开手机端使用session等问题。

同时,由于JWT是使用base64进行对称加密,也就是说是可以进行解密的,所以千万不要存储用户的密码等敏感信息!
同时,由于JWT是使用base64进行对称加密,也就是说是可以进行解密的,所以千万不要存储用户的密码等敏感信息!

同时,由于JWT是使用base64进行对称加密,也就是说是可以进行解密的,所以千万不要存储用户的密码等敏感信息!

好了,现在我们来介绍一下在thinkphp如何使用JWT
首先通过git获取https://github.com/firebase/php-jwt
把获取到的JWT放至thinkphp的目录下,目录结构如下:
Thinkphp/Library/Vender/Firebase/JWT
此时JWT文件里面应有4个文件分别为:

SignatureInvalidException.php
JWT.php
ExpiredException.php
BeforeValidException.php

除了JWT.php是我们要引入的主文件以外,其他文件不用直接引入。
我们在需要使用JWT的文件里面添加上命名空间
namespace.jpg
然后在要使用的操作类里面通过thinkphp的Vendor方法引入

public function Login(){
    Vendor('Firebase.JWT.JWT');
    // 使用JWT进行密钥签名
    define('KEY', '28ksdfgdioaiowjqwreosod23ldmbsm2Xa'); // 自定义私有密钥
    // 这里的$data是通过查询数据库里面是否有相应的用户名,并且密码正确返回的信息,我这里忽略了验证数据库信息的过程
    if($data){
        $nowtime = time();
        $token = [
            'iss' => 'teaxia', //签发者
            'aud' => username, //jwt所面向的用户
            'iat' => $nowtime, //签发时间
            'nbf' => $nowtime, //生效时间(马上生效)
            'exp' => $nowtime + 3600, // 过期时间1小时
            'data' => [
                'userid' => $data['id'],    // 数据库的用户ID(请自行获取)
                'username' => $data['name'] // 数据库的用户名(请自行获取)
            ]
        ];
        $jwt = JWT::encode($token, KEY);    // 通过JWT获取token
        $this->ajaxReturn($jwt);            // 返回用户token
    }
}

以上,通过JWT生成用户TOKEN的过程就完成了,那么我们在验证TOKEN的时候,使用

$key = "28ksdfgdioaiowjqwreosod23ldmbsm2Xa";            // 私钥
$decoded = JWT::decode($jwtstr, $key, array('HS256'));  // $jwtstr是每次请求时传过来的token
$arr = json_decode(json_encode($decoded), true);        // 解密数据

这里面的$arr就是解密的用户信息,拿到这个用户信息就可以判断用户权限这些东西了

假设数据结构为:

let data = [
{id: 1, text: 't11', parentId: 0},
{id: 2, text: 't11', parentId: 0},
{id: 3, text: 't11', parentId: 1},
{id: 4, text: 't11', parentId: 1},
{id: 5, text: 't11', parentId: 3},
{id: 6, text: 't11', parentId: 2},
];

需要转换成:

// let tree =[{
// id:1,text:'t11',parentId:0,
// child:[...]
// }]

计算代码:

data.forEach(ele => {
  let parentId = ele.parentId;
  if (parentId === 0) {
    //是根元素的hua ,不做任何操作,如果是正常的for-i循环,可以直接continue.
  } else {
    //如果ele是子元素的话 ,把ele扔到他的父亲的child数组中.
    data.forEach(d => {
      if (d.id === parentId) {
        let childArray = d.child;
        if (!childArray) {
          childArray = []
        }
        childArray.push(ele);
        d.child = childArray;
      }
    })
  }
});
//去除重复元素
data = data.filter(ele => ele.parentId === 0);
console.log('最终等到的tree结构数据: ', data);

本文主要解决以下问题

  1. 怎么样才能使用apicloud把我们生产的项目打包成app呢?
  2. 可以在vue里面调用apicloud的api访问我们的设备,使用一些硬件功能呢?

使用VUE项目npm run build打包过后,我们得到的其实就一个index.html跟static资源文件夹。当然,我们直接把代码部署到服务器时候是没有任何问题的。但是我们怎么样才能使用apicloud把我们生产的项目打包成app呢?并且可以在vue里面调用apicloud的api访问我们的设备,使用一些硬件功能呢?

关于生成app的部分,其实很简单。首先我们看看apicloud的打包目录
apicloud目录结构.png
我们可以看到里面有一些css html image等目录,但是我们在使用npm run build的时候webpack就已经把项目里面使用到的资源压缩到static目录里面了,如果我们强行把它分离出来的话,index.html肯定会报错,所以我们不能把资源分离出来。
我们直接在apicloud的打包目录里面把static资源目录直接增加进去,然后index.html覆盖以前的文件。这样我们其实就可以直接使用apicloud打包了。(下图是增加了static的目录结构,其实只用把打包的文件直接复制进apicloud的根目录覆盖就可以了)
新目录结构.png

解决了打包问题,我们回头来看看如何在VUE里面使用apicloud的API呢?
首先我们在index.html里面引入apicloud的api.js
HTML.png
<script src="script/api.js"></script>
这段别改,因为script是apicloud的目录,你复制到apicloud的打包目录才有的东西,所以也就是说,你如果使用了apicloud的API,那就只能在真机上才能运行。
引入了api以后,你就可以直接在VUE里面使用api了。比如我现在加入一个扫描二维码然后回调赋值给vue的内部变量
代码.png

里面引入了apicloud的FNScanner扫码模块在回调函数里面直接把值赋值给vue就可以了。

很多时候,我们在页面使用Ajax刷新时候,会希望它出现loading的图标,让用户体验更好一些。那么如果我们每次在Axios里面进行请求,都要显示loading图标的话,那么没有一个全局的方法的话,势必会造成代码冗余的问题。有什么方法可以实现这个方法呢?

这里,我们就要用到Axios的请求拦截器与相应拦截器了

首先,我们在请求拦截器里面增加一个VUX的loading组件

axios.interceptors.request.use(
config => {

//请求拦截器,调用loading插件
// 显示loading
// 判断是否重复提交请求,也就是loading是否还存在,如果存在则不显示新的loading
let isShow = window.app.$vux.loading.isVisible()
if(!isShow&&config.showLoading){
    window.app.$vux.loading.show({
    text: 'Loading'
   })
}
config.data = JSON.stringify(config.data);
config.headers = {
    'Content-Type': 'application/json',
}
return config;
},
error => {

return Promise.reject(err);
}
);

整个数据里面,我们看到了里面有一个参数是$vux.loading.isVisible()这个。这个是vux自带的一个loading状态显示的参数。如果loading正在显示的话,它会是true,否则的话就显示false
因为我们不希望同时有多个请求的时候,出现多个loading状态,这样的话用户看起来会很迷茫,所以我们在调用的时候,先判断一下这个状态。
然后在响应拦截器里面关掉它就好了
loading.png