搭建前端网络请求模块

  1. HTTP 超文本传输协议
  2. 发送一个请求查询用户日志记录
    • 请求
    • 响应
    • 请求方式有哪些?
    • 响应码有哪些?
    • 客户端请求后,服务器响应携带的 https 证书
    • 常用加密算法
  3. 快速搭建 Vue 普通 H5 项目页面的网络请求
    • JS 变量修饰符
    • 函数 Function
    • Object 对象
    • 对象的定义
    • Ajax 请求
    • Axios 框架
  4. Vue Cli 脚手架项目请求模块的搭建
    • 基础安装环境
    • package.json 配置
    • 配置 main.js
    • 请求 Demo 示例
    • 模块之间的引用和导出
  5. H5 和 App 原生交互

HTTP 超文本传输协议

TCP 三次握手

  1. 客户端发 syn 询问给服务器。
  2. 服务器回应询问 syn,并发送一个指令 ack 客户端。
  3. 客户端回 ack 服务器。 正式连接成功后开始客户端请求 Http 报文,服务器响应报文。搭建前端网络请求模块_第1张图片

四次挥手过程

搭建前端网络请求模块_第2张图片

发送一个请求查询用户日志记录

请求

:method: POST:scheme: https:authority: vendor-api-prod.gaoying.com:path: /customer/logs/Accept: application/json, text/plain, */*Content-Type: application/x-www-form-urlencoded  //表单提交方式Origin: http://h5-vendor-dev.gaoying.comContent-Length: 236Accept-Language: zh-cnHost: vendor-api-dev.gaoying.comUser-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 13_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148Referer: http://h5-vendor-dev.gaoying.com/page/customerMain.html?customerId=172821&userId=15243265&token=41cadcb70eed35378a92379871a51181Accept-Encoding: gzip, deflate, brConnection: keep-alive

响应

   status: 200   Access-Control-Allow-Origin: *   Content-Type: application/json;charset=UTF-8  //json 响应格式   Date: Fri, 27 Dec 2019 05:58:18 GMT   Server: Tengine

请求方式有哪些?

   METHODS: [      'ACL',         'BIND',       'CHECKOUT',      'CONNECT',     'COPY',       'DELETE',      'GET',         'HEAD',       'LINK',      'LOCK',        'M-SEARCH',   'MERGE',      'MKACTIVITY',  'MKCALENDAR', 'MKCOL',      'MOVE',        'NOTIFY',     'OPTIONS',      'PATCH',       'POST',       'PROPFIND',      'PROPPATCH',   'PURGE',      'PUT',      'REBIND',      'REPORT',     'SEARCH',      'SOURCE',      'SUBSCRIBE',  'TRACE',      'UNBIND',      'UNLINK',     'UNLOCK',      'UNSUBSCRIBE'    ]

响应码有哪些?

STATUS_CODES: {  '100': 'Continue',  '101': 'Switching Protocols',  '102': 'Processing',  '103': 'Early Hints',  '200': 'OK',  '201': 'Created',  '202': 'Accepted',  '203': 'Non-Authoritative Information',  '204': 'No Content',  '205': 'Reset Content',  '206': 'Partial Content',  '207': 'Multi-Status',  '208': 'Already Reported',  '226': 'IM Used',  '300': 'Multiple Choices',  '301': 'Moved Permanently',  '302': 'Found',  '303': 'See Other',  '304': 'Not Modified',  '305': 'Use Proxy',  '307': 'Temporary Redirect',  '308': 'Permanent Redirect',  '400': 'Bad Request',  '401': 'Unauthorized',  '402': 'Payment Required',  '403': 'Forbidden',  '404': 'Not Found',  '405': 'Method Not Allowed',  '406': 'Not Acceptable',  '407': 'Proxy Authentication Required',  '408': 'Request Timeout',  '409': 'Conflict',  '410': 'Gone',  '411': 'Length Required',  '412': 'Precondition Failed',  '413': 'Payload Too Large',  '414': 'URI Too Long',  '415': 'Unsupported Media Type',  '416': 'Range Not Satisfiable',  '417': 'Expectation Failed',  '418': "I'm a Teapot",  '421': 'Misdirected Request',  '422': 'Unprocessable Entity',  '423': 'Locked',  '424': 'Failed Dependency',  '425': 'Unordered Collection',  '426': 'Upgrade Required',  '428': 'Precondition Required',  '429': 'Too Many Requests',  '431': 'Request Header Fields Too Large',  '451': 'Unavailable For Legal Reasons',  '500': 'Internal Server Error',  '501': 'Not Implemented',  '502': 'Bad Gateway',  '503': 'Service Unavailable',  '504': 'Gateway Timeout',  '505': 'HTTP Version Not Supported',  '506': 'Variant Also Negotiates',  '507': 'Insufficient Storage',  '508': 'Loop Detected',  '509': 'Bandwidth Limit Exceeded',  '510': 'Not Extended',  '511': 'Network Authentication Required'}

客户端请求后,服务器响应携带的 https 证书

HTTPS在 HTTP 与 TCP 之间加入 SSL 层,一个加密/身份验证层,用于安全的 HTTP 数据传输。 它是一个 URI scheme(抽象标识符体系)。SSL 是安全套接层 。它的任务是负责在网络传输层基础上对网络连接进行数据加密。具有校验机制,配备身份证书。客户端利用公钥对数据加密,服务端收到加密数据后 对数据进行解密。

搭建前端网络请求模块_第3张图片

Https 服务器端口是 443, Https 公共密钥采用 RSA 算法加密,证书信息将在请求响应之前回复给客户端。客户端根据证书信息本地做一个安全校验,通过后再允许服务端响应返回数据,否则取消本次请求响应。签名算法:SHA-256 ECDSA

常用加密算法

对称加密
  • 单向散列函数MD5 是一种不可逆的信息摘要算法,严格来说不是加密。单向散列函数是一种不可逆的信息摘要算法,无法通过密文还原成明文(注意:是算法上不能实现),对于简单的 MD5 加密(这里的简单是指:明文长度短,且字符单一,并且进行 HASH 操作的时候没有进行加盐处理),是可以通过一些在线工具网站解密出来,实则是利用了彩虹表的技术。
  • AES 加密 加密原理:字节代换、行位移、列混合(矩阵相乘:状态矩阵 和 固定矩阵相乘) 、轮钥加密:轮钥加密是将 128 位轮密钥 Ki 同状态矩阵中的数据进行逐位异或操作。
  • DES 加密
非对称加密
  • RSA 加密搭建前端网络请求模块_第4张图片

快速搭建 Vue 普通 h5 项目页面的网络请求

在学习请求之前,需要掌握好 Javascript 语言。最基础的知识首先要了解和掌握变量修饰符,Function 和 Object 对象。

js 变量修饰符

let 是局部变量,非常适合循环的时候。const 是只读变量, 初始化的时候就要赋值,且只能赋值一次。var 是全局变量,全局都可以用。

函数 Function

搭建前端网络请求模块_第5张图片 从上图我们看到有个名为 open 的函数,包含参数、调用者、长度、名字、以及 Proto 对象。该对象里面有 apply 、bind、 call 函数。还有一个 contructor 构造器。

  • Function 属性: length、name、prototype。

  • Function.prototype.apply() //调用一个函数并将其设置为提供的值。 可以将参数作为 Array 对象传递

  • Function.prototype.bind() //创建一个新函数,该新函数在调用时将其设置为提供的值,并在调用新函数时在提供的任何参数之前添加给定的参数序列。

  • Function.prototype.call() //调用一个函数并将其设置为提供的值。 可以按原样传递参数。

  • Function.prototype.toString() //返回表示函数源代码的字符串。

    //题外话,apply 和 bind 增强代码的扩展性,类似 iOS 的 category;

  1. 动态改变 this 的指向,也就是 this 从 callObject 动态切换为 thisArg。

  2. callObject.method.apply(thisArg,thisArray),可以将 thisArray 转化为 arguments,传入到 callObject.method 内部。

    我们通过以下代码来测试 bind 的用法:

//程序员的黄金年龄 18 ~ 35var checkProgramerAgeRange = function (value) {   if (typeof value !== 'number')       return false;   else       return value >= this.minimum && value <= this.maximum;}let programmerRange = { minimum: 18, maximum: 35 };// 把函数内部的 this 修改为 range 对象,let boundCheckProgramerAgeRange = checkProgramerAgeRange.bind(programmerRange);console.log(boundCheckProgramerAgeRange(12));

Object 对象

Object 继承 Function,扩展了自己的许多方法。

Object 的属性构造器 Object.prototypeObject.assign()   将所有可枚举的自身属性的值从一个或多个源对象复制到目标对象。Object.create()  用指定的原型对象和属性创建一个新对象。Object.defineProperty()  定义一个 property 给指定对象Object.defineProperties() 定义一个属性 给指定对象Object.entries() 返回一个装有 map 的数组。Object.getOwnPropertyNames() 得到这个对象自己的属性名Object.getPrototypeOf() 得到指定类型的属性Object.is() 比较对象Object.keys() 字符窜属性Object.values()
let stuObj = {room:"english"};Object.defineProperties(stuObj,{    stuName:{        value:"qiugaoying",        writable:true        /*         configurable, enumerable,          value, writable, get, set        */    },    age: {        value:18,        writable:true    }})//可直接覆盖某对象的属性;Object.defineProperty(stuObj,"stuName",{    value:"gaogao",    writable: true})stuObj.age = 20;console.log(stuObj.stuName); //gaogaoconsole.log(stuObj.age); //20console.log(Object.keys(stuObj)); //room 取得公共属性console.log(Object.values(stuObj)); //room 取得公共属性值console.log(Object.getOwnPropertyNames(stuObj)); //room,age,stuName 取得对象所有属性console.log(Object.getOwnPropertyDescriptors(stuObj)); //获取属性描述器console.log(stuObj["stuName"]); //gaogao

对象的定义

传统方式定义一个对象
function Person(name,age){   this.name = name;   this.age = age;}//通过函数的 prototype 公共空间存储方法Person.prototype.introduce = function(){    console.log("hello,my name is "+this.name);}new Person().introduce();
Class 方式定义一个对象
class Person{    constructor(name,age){        this.name = name;        this.age = age;    }    introduce(){        console.log("我的名字是:"+this.name);    }}

类的本质是对象,对象继承 Function。所以 introduce 方法还是存储在 prototype 公共空间中。操作类函数也可通过 Person.prototype 去动态新增新的方法。另外要注意一点类的所有实列共享原型的 prototype。

let student = new Person("qiugaoying",18);let student2 = new Person("lihua",22); console.log(student.__proto__ == student2.__proto__); //结果为 true。 类的所有实列共享原型的 prototype

Ajax 请求

通常,发起一个请求,需要传入基础参数,业务 url, 业务参数,设置请求头,和响应方式。 接着对响应成功和失败的处理;前端通常的请求方式有 表单提交,Ajax 异步请求,jquery 也提供了 ajax 封装的快捷 api。另外也有较新的框架 Axios。

ajax 的出现是解决局部数据刷新的问题。可通过后台异步调用接口实现页面局部刷新。浏览器原生有个 XMLHttpRequest 对象。 搭建前端网络请求模块_第6张图片jquery 出来之后,ajax 的调用简化了好多。

 $ajax({     type: 'POST',     dataType: 'json', //服务端返回的数据类型     contentType: 'application/json' ,//参数类型     url : "http://127.0.0.1/log/list/",     headers:{'Content-Type':'application/json'},//请求头, 内容编码类型 默认 "application/x-www-form-urlencoded"     data: JSON.stringify({"name":"qiugaoying"}), //传参     success: function(result,status,xhr){         console.log(result); //获取结果     },     error: function (xhr,status,error){         console.log(error);     } });

Axios 框架

Axios 是一个基于 promise 的 HTTP 库。也可以用在浏览器和 node.js 中。我们来观察一下在 axios 的 api 方法。搭建前端网络请求模块_第7张图片

  • 从图可以看出,有个默认属性中有个 xmlHttpRequet 网络适配器。
  • 可设置基础 baseURL、请求头, 请求超时等一些基础设置。
  • 转换请求数据和响应数据,支持防御 XSRF。
  • 提供了常用的 get、post 等请求。自动转换 JSON 数据。还提供请求和响应的拦截器。
script 标签引入 axios 的 js
//构建一个 axios 实列只读变量,设置基础 urlconst http = axios.create({    baseURL: 'https://vendor-api-prod.qiugaoying.com',    timeout: 1000,    transformRequest: [function(data) {        // Do whatever you want to transform the data        let ret = ''        for (let it in data) {            ret += encodeURIComponent(it) + '=' + encodeURIComponent(data[it]) + '&'        }        return ret    }]});
封装基础参数,排序、加密

对请求的基础参数做一个封装。 大部分请求都需要带上一些基础参数和 userId、token 等字段。最后对所有字段 key 排序,最后转成 json 字符串再加密。以下为示例:

const netManager = {    getRequestParams: function(params) {        let userId = localStorage.getItem("userId");        let token = localStorage.getItem("token");        // var userInfo = JSON.parse(userInfoStr);        var obj = Object.assign(params, {            api_version: 1, //接口版本            platform: 2, //平台类型            terminal: 1, //终端类型            nonce: (Math.random().toFixed(8) + '').replace('0.', ''), //随机数;            timestamp: new Date().getTime(), //当前时间戳 毫秒            user_id:123, //userId            token: "ec29c3af0dd998yjhgd22f9y867ws6512", //token            version_code: 100 //当前版本号        });        let sign = MD5(this.strKeySort(obj)).toUpperCase(); //md5 加密        obj["Sign"] = sign;        return obj;    },    //key 排序    strKeySort: function(obj) {        const newkey = Object.keys(obj).sort();        const newArr = [];        for (let i = 0; i < newkey.length; i++) {            if (obj[newkey[i]] === 'undefined' || obj[newkey[i]] === 'null') {                obj[newkey[i]] = '';            }            newArr.push(`${newkey[i]}=${obj[newkey[i]]}`)        }        const newStr = newArr.join('&') + '&secret_key=gaoyingAESKey';        return newStr;    },    //获取 url 后面带的参数;    getUrlKey: function (name) {        return decodeURIComponent((new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)').exec(location.href) || [, ""])[1].replace(/\+/g, '%20')) || null    }}
axios 实列发起一个请求示例

这里拿请求用户个人主页基础信息为样例,把下面方法放入 Vue 的 methods 中。 loading 用的是 weiui.js 框架。以下可以实现一个分页加载的请求:

var vm = new Vue({    el: '#PageContainer1',    data: {        //分页数据        pageNumber: 1,        pageSize: 10,        gyPageListStart: 0,        hasMoreDataFlag: false,        dataSource: [],    },    methods: {        execBaseCustomerRequest: function(url, listKey) {             var loading = null;              if (this.pageNumber == 1) {                  loading = weui.loading('加载中');              }              let pageVue = this; //this 在不同的作用域中指向的对象不同;临时存储 vue 对象              if (this.pageNumber == 1) {                  this.gyPageListStart = 0;              }              http.post(url, netManager.getRequestParams({                  customer_id: this.customerId,                  start: this.gyPageListStart,                  size: 10,              })).then(function(response) {                  if (loading) {                      loading.hide();                  }                  let dataDic = response.data;                  if (dataDic.status == 1) {                      var arr = pageVue.dataSource;                      if (pageVue.pageNumber == 1) {                          arr = [];                      }                      var dataArr = dataDic.data[listKey];                      arr = arr.concat(dataArr);                      pageVue.gyPageListStart = dataDic.data.start;                      vm.$data.hasMoreDataFlag = (dataDic.data.more == 1);                      vm.$data.dataSource = arr;                  }                  setTimeout(function() {                      pageVue.requestLoadingFinished = true;                  }, 800);                  //重置加载完成的状态;              }).catch(function(error) {                  console.log(error);              });        }     }});

其他: url 通常会放到一个全局文件中配置

const gaoyingAPI = {    customerList: "/customer/list/",    customerLogs: "/customer/logs/",    customerCoupons: "/customer/coupons/",    customerOrders: "/customer/orders/",    customerDetail: "/customer/detail/"}
Promise 用法简要讲解

从上文中,我们看到 http 发送 post 方法请求之后,通过 promise 语法 then 的回调监听响应结果,通过 catch 方法 来捕捉异常错误处理。ES6 就支持了 Promise 的用法。Promise 中文为承诺。有三种状态:pending (进行中)、fulfilled (已成功)、rejected (已失败)。 即状态一旦更改就不能再次改变赋值。这也是承诺的意义。Promise 实列通过 then 方法或者 catch 方法 返回一个新的 Promise 实例来实现链式调用。then 方法可以返回普通值或者一个新的 promise。不设置返回值时,默认返回 null。Promise 有很多用法,但什么情况下需要用到 Promise 呢? 在需要处理异步耗时任务的时候,可用 Promise 包装后进行返回。Promise 用的时候会遇到很多种情况,Promise 也提供了对应的解决方法。

  • 当 Promise.then 方法返回一个新的 Promise 时候,下一级的 then 将在 新的 Promise then 执行之后执行。
//Promise then 嵌套 方式一new Promise(resolve => {    console.log("step1:异步请求处理耗时任务");    setTimeout(() => {        resolve("qiu");    }, 1000);}).then(value => {    //第一个接口请求成功拿到 qiu    console.log("step1-result:" + value);    return new Promise(resolve => {        console.log("step2-1:异步请求处理耗时任务 2");        setTimeout(() => {            resolve("qiugao");        }, 1000);        //触发第二个接口请求    }).then(value => {        //第二个接口请求成功,拿到 id2 做第一件事情。        console.log("step2-1-result-event1:" + value);        return "qiugaoying";    }).then(value => {        //第二个接口请求成功,拿到 id2 做第二件事情。        console.log("step2-1-result-event2:" + value);        return "hello, my name is qiugaoying";    });}).then(value => {    //最后全部请求完成,触发汇总刷新。    console.log("step1-result:" + value);});/*console 输出结果:step1:异步请求处理耗时任务step1-result:qiustep2-1:异步请求处理耗时任务 2step2-1-result-event1:qiugaostep2-1-result-event2:qiugaoyingstep1-result:hello, my name is qiugaoying*///Promise then 嵌套,方式二: 把 then 移到同一级展开。执行打印结果是一样的。new Promise(resolve => {    console.log("step1:异步请求处理耗时任务");    setTimeout(() => {        resolve("qiu");    }, 1000);}).then(value => {    //第一个接口请求成功拿到 qiu    console.log("step1-result:" + value);    return new Promise(resolve => {        console.log("step2-1:异步请求处理耗时任务");        setTimeout(() => {            resolve("qiugao");        }, 1000);        //触发第二个接口请求    });}).then(value => {    //第二个接口请求成功,拿到 id2 做第一件事情。    console.log("step2-1-result-event1:" + value);    return "qiugaoying";}).then(value => {    //第二个接口请求成功,拿到 id2 做第二件事情。    console.log("step2-1-result-event2:" + value);    return "hello, my name is qiugaoying";}).then(value => {    //最后全部请求完成,触发汇总刷新。    console.log("step1-result:" + value);});
  • then 方法提供两个参数,第二个参数可选。一个是名为 resolve 的成功回调 和 另一个名为 reject 的失败回调。通常处理一个失败回调我们会用 catch 方法去捕捉异常和失败。
    new Promise(resolve => {        console.log("step1:异步请求处理耗时任务");        setTimeout(() => {            resolve("qiu");        }, 1000);    }).then(value => {        //第一个接口请求成功拿到 qiu        console.log("step1-result:" + value);        return new Promise(resolve => {            console.log("step2-1:异步请求处理耗时任务");            setTimeout(() => {                resolve("qiugao");            }, 1000);            //触发第二个接口请求        });    }).then(value => {        //第二个接口请求成功,拿到 id2 做第一件事情。        let hasError = true        if (hasError) {            throw new Error("step2-1-result-event1-error 报异常");            //抛出异常 将不再继续执行 then, 直接到 catch 异常;中途如果没有遇到 catch 将直接到最后的 catch.        } else {            console.log("step2-1-result-event1:" + value);            return "qiugaoying";        }    })    /*.catch(err => {        console.log("中途 catchError 会继续往下走:" + err);        return "qiugaoying"        //也会返回一个 promise 实例,并且是 resolved 状态,不会被最后一个 catch 捕捉    })*/    .then(value => {        //第二个接口请求成功,拿到 id2 做第二件事情。        console.log("step2-1-result-event2:" + value);        return "hello, my name is "+value;    }).then(value => {        //最后全部请求完成,触发汇总刷新。        console.log("step1-result:" + value);    }).catch(error => {        console.log("end error:" + error);    });
  • finally 方法是最终执行的方法(无参),无论状态是什么,成功 or 失败 都会执行收尾。
  • Promise 还提供 all 方法(接收一个数组,里面值可以是普通函数,或者 Promise 对象),可用来做一个类似批量处理之后汇总的业务。
 testPromiseAll() {    function washFood(){        console.log('做饭第一步:洗菜');        let hasError = false;        if(hasError){            return "发现了一只虫子!洗掉它。";        }else{            return '菜洗干净了。';        }    }    function cutFood() {        console.log('做饭第二步:切菜');        var p = new Promise(function (resolve, reject) { //做一些异步操作            setTimeout(function () {                let cutFoodHasError = true;  //控制默契切菜时 是否发生异常                if(cutFoodHasError){                    reject("呜呜~ 割到手了,流血!")                }else{                    resolve('切好了菜。');                }            }, 1000);        })        /* 试试打开这里的注释        .catch(error=>{            console.log("切菜异常:"+error); //异常本身就是返回 resolve 状态,值是 null            console.log("用创口贴止血,继续做菜。");        });        */        return p;    }    function cooking() {        console.log('做饭第三步:炒菜');        var p = new Promise(function (resolve, reject) { //做一些异步操作            setTimeout(function () {                resolve('菜已做好!');            }, 2000);        });        return p;    }    //数组里,如果放 Promise 一定要返回状态。     Promise.all([washFood(), cutFood(),cooking()])        .then((result) => {            console.log('上桌,吃饭了:'+result);            console.log(result);        }).catch(error=>{            console.log("菜没做成,出现了小事故:"+error);        })   /*     结果:     1. 当 cutFoodHasError = true;打印如下结果:        菜没做成,出现了小事故:呜呜~ 割到手了,流血!     2. 当 cutFoodHasError = true 且 cutFood 方法里的 Promise 有异常捕捉时:         切菜异常:呜呜~ 割到手了,流血!        上桌,吃饭了:菜洗干净了!,,菜已做好     3. 当 cutFoodHasError = false         上桌,吃饭了:菜洗好了。切好了菜。菜已做好!    */    /*     Promise.all 使用总结:    数组里可以是 Promise 对象,也可以是别的值,只有 Promise 会等待状态改变    当所有的子 Promise 都完成,该 Promise 完成,返回值是全部值得数组    有任何一个失败,该 Promise 失败,返回值是第一个先失败的子 Promise 结果     */},
  • Promise 另外一个 race 方法。与 all 不同的是:race 类似竞赛,参数中的 Promise 实例只要有一个率先改变状态就会触发结果。
//打印结果: 兔子赢了testPromiseRace() {    function rabbit() {        console.log('兔子选手');        var p = new Promise(function (resolve, reject) {            setTimeout(function () {                resolve('兔子赢了');            }, 1000);        }) .catch(error=>{            console.log("兔子跑步中出现异常:"+error);        });        return p;    }    function tortoise() {        console.log('乌龟选手');        var p = new Promise(function (resolve, reject) {            setTimeout(function () {                resolve('乌龟赢了');            }, 3000);        });        return p;    }    Promise.race([rabbit(),tortoise()])        .then((result) => {            console.log("比赛结果:"+result);        })}

Vue Cli 脚手架项目请求模块的搭建

在 vue 的基础上,我们可以通过 vue cli 来管理我们的项目。vue cli 方式的优势在于模块之间可以很好地相互引用,通过 package 包来管理配置相关的框架依赖。生态非常丰富,可轻松运用 vue-router 来解决路由跳转等问题。首先第一步是要创建一个 vue cli 项目。

基础安装环境

npm install -g @vue/clivue create helloworld 方式创建项目也可以使用 GUI vue ui 来通过网页手动点击按钮操作来创建项目

package.json 配置

{  "name": "gaoying-cli",  "version": "0.1.0",  "private": true,  "scripts": {    "serve": "vue-cli-service serve",    "build": "vue-cli-service build",    "lint": "vue-cli-service lint"  },  "dependencies": {    "animate.css": "^3.7.2",    "core-js": "^3.4.3",    "vue": "^2.6.10",    "vue-axios": "^2.1.5",    "vue-router": "^3.1.3",    "vuex": "^3.1.2",    "weui.js": "^1.2.1"  },  "devDependencies": {    "@vue/cli-plugin-babel": "^4.1.0",    "@vue/cli-plugin-router": "^4.1.1",    "@vue/cli-plugin-vuex": "^4.1.1",    "@vue/cli-service": "^4.1.0",    "axios": "^0.19.0",    "vue-template-compiler": "^2.6.10",    "weui": "^2.1.3"  },  "eslintConfig": {    "root": true,    "env": {      "node": true    },    "extends": [      "plugin:vue/essential",      "eslint:recommended"    ],    "parserOptions": {      "parser": "babel-eslint"    }  },  "browserslist": [    "> 1%",    "last 2 versions"  ]}

配置 main.js

import Vue from 'vue'import App from './App.vue'import router from './router'import store from './store'import axios from 'axios' //请求网络import VueAxios from 'vue-axios' import weui from 'weui.js' //weuiJsimport 'weui' //weui 样式import ymAPI from '@/assets/js/urlConfig.js' //Apiimport netManager from '@/assets/js/netManager.js' //请求基础参数拼接import ymNativeBridge from '@/assets/js/ymNativeBridge.js' //原生事件交互import animate from 'animate.css'const ymHttp = axios.create({    baseURL: 'https://vendor-api-prod.gaoying.com',     timeout: 1000,    transformRequest: [function(data) {        // Do whatever you want to transform the data        let ret = ''        for (let it in data) {            ret += encodeURIComponent(it) + '=' + encodeURIComponent(data[it]) + '&'        }        return ret    }]});Vue.config.productionTip = falseVue.prototype.$weui = weuiVue.prototype.$ymAPI = ymAPIVue.prototype.$netManager = netManagerVue.prototype.$ymNativeBridge = ymNativeBridgeVue.use(VueAxios, ymHttp,animate)new Vue({  router,  store,  render: h => h(App)}).$mount('#app');

请求 Demo 示例

//和普通 h5 请求网络类似,唯一不同的就是通过挂载到 Vue 上的 axios ,可以通过 this.http 获取。this.netManager 也类似。

execBaseCustomerRequest: function(url, listKey) {   var loading = null;   if (this.pageNumber == 1) {       loading = this.$weui.loading('加载中');       this.gyPageListStart = 0;   }   let pageVue = this; // this 在不同的作用域中指向的对象不同;临时存储 vue 对象   this.$http.post(url, this.$netManager.getRequestParams({       customer_id: this.customerId,       start: this.gyPageListStart,       size: 10,   })).then(function(response) {       if (loading) {           loading.hide();       }       let dataDic = response.data;                if (dataDic.status == 1) {           var arr = pageVue.dataSource;           if (pageVue.pageNumber == 1) {               arr = [];           }           var dataArr = dataDic.data[listKey];           arr = arr.concat(dataArr);           pageVue.gyPageListStart = dataDic.data.start;           pageVue.hasMoreDataFlag = (dataDic.data.more == 1);           pageVue.dataSource = arr;       }else{           pageVue.$weui.topTips(dataDic.errorMsg);       }       setTimeout(function() {           pageVue.requestLoadingFinished = true;       }, 800);       //重置加载完成的状态;   }).catch(function(error) {       console.log(error);   });}

模块之间的引用和导出

import MD5 from './md5.js'export default {    getRequestParams: function(params) {        let userId = localStorage.getItem("userId");        let token = localStorage.getItem("token");        ......    }}//md5.js 文件中 var MD5 = function (string) {    ......}module.exports = MD5//接口配置 urlConfig.js 文件中const ymAPI = {    //客户信息     customerList: "/customer/list/",    customerLogs: "/customer/logs/",    customerCoupons: "/customer/coupons/",    customerOrders: "/customer/orders/",    customerDetail: "/customer/detail/"}module.exports = ymAPI

export 在 js 文件中可以有多个。

//testExport.jsexport const person = { name: "qiugaoying",sex:1, job:"software Programmer"}export const addressInfo = {province:"广东省", city:"guangzhou"}export const introduct = function(){    console.log("my name is qiugaoying");}

export 有多个的时候 ,导入必须用花括号括起来。

import {person,addressInfo} from "../../utils/testExport.js"import * as  allExp from "../../utils/testExport.js"  //加载全部 export,取个别名

** 总结 **

  1. export default 只能导出一个对象。import 和 export 同一 js 文件中可以导入或导出多次。
  2. module.exports 和 exports 都是 node 端在用,两者指向同一内存块,可以导出变量、函数、或者对象。
  3. exports 变量是在模块的文件级作用域内可用的,且在模块执行之前赋值给 module.exports。

H5 和 App 原生交互

//原生调用 appexport default {    callApp:function(handlerMethod, parameters) {        if (!window.WeixinJSBridge || !WeixinJSBridge.invoke) {            var handlerInterface = 'YunMiaoNative';            var dic = {                'handlerInterface': handlerInterface,                'function': handlerMethod, //调用原生的指令                'parameters': parameters //传递的参数;            };            if (/(iPhone|iPad|iPod|iOS)/i.test(navigator.userAgent)) {                window.webkit.messageHandlers[handlerInterface].postMessage(dic);            } else { //安卓                  app.ymAppWebClick(); //dic            }        } else {            //包含微信功能,比如可唤起小程序。        }    },    //原生调用 app 并传递参数给 H5    callbackH5: function(handlerMethod, parameters, callbackMethod) {        if (!window.WeixinJSBridge || !WeixinJSBridge.invoke) {            var handlerInterface = 'YunMiaoH5';            var dic = {                'handlerInterface': handlerInterface,                'function': handlerMethod, //调用原生的指令                'parameters': parameters, //传递的参数;                'callbackMethod': callbackMethod //回调的函数            };            if (/(iPhone|iPad|iPod|iOS)/i.test(navigator.userAgent)) {                window.webkit.messageHandlers[handlerInterface].postMessage(dic);            } else { //安卓                  app.ymAppWebClick(JSON.stringify(dic));            }        } else {            //包含微信功能,比如可唤起小程序。        }    }}

阅读全文: http://gitbook.cn/gitchat/activity/5e146270eb69ea4eda349b34

您还可以下载 CSDN 旗下精品原创内容社区 GitChat App ,阅读更多 GitChat 专享技术内容哦。

FtooAtPSkEJwnW-9xkCLqSTRpBKX

你可能感兴趣的:(前端)