热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

JS构建多端应用

JS构建多端应用一,需求与介绍1.1,介绍1,Taro是一套遵循React语法规范的多端开发解决方案。现如今市面上端的形态多种多样,Web、React-Native、微信小程序

JS构建多端应用

一,需求与介绍

 1.1,介绍

1,Taro 是一套遵循 React 语法规范的 多端开发 解决方案。现如今市面上端的形态多种多样,Web、React-Native、微信小程序等各种端大行其道,当业务要求同时在不同的端都要求有所表现的时候,针对不同的端去编写多套代码的成本显然非常高,这时候只编写一套代码就能够适配到多端的能力就显得极为需要。

使用 Taro,我们可以只书写一套代码,再通过 Taro 的编译工具,将源代码分别编译出可以在不同端(微信/百度/支付宝/字节跳动小程序、H5、React-Native 等)运行的代码。

2,Taro UI 是一款基于 Taro 框架开发的多端 UI 组件库

 1.2,需求

     一套代码,多端使用,减少开发成本

二,搭建项目

第一步:全局安装Taro 开发工具 @tarojs/cli

1 npm/cnpm install -g @tarojs/cli

第二步:创建项目

1 taro init YingQi

 在创建完项目之后,Taro 会默认开始安装项目所需要的依赖,安装使用的工具按照 yarn>cnpm>npm 顺序进行检测。如果安装失败,可以使用如下命令安装

1 npm/cnpm install

第三步:运行项目

以运行H5为例,输入如下命令

如果看到如下界面,表示运行成功

1.H5

H5预览项目

1 # npm script
2 $ npm run dev:h5
3 # 仅限全局安装
4 $ taro build --type h5 --watch
5 # npx 用户也可以使用
6 $ npx taro build --type h5 --watch

H5打包项目

1 # npm script
2 $ npm run build:h5
3 # 仅限全局安装
4 $ taro build --type h5
5 # npx 用户也可以使用
6 $ npx taro build --type h5

2.微信小程序

微信小程序预览项目

1 # npm script
2 $ npm run dev:weapp
3 # 仅限全局安装
4 $ taro build --type weapp --watch
5 # npx 用户也可以使用
6 $ npx taro build --type weapp --watch

微信小程序打包项目

1 # npm script
2 $ npm run build:weapp
3 # 仅限全局安装
4 $ taro build --type weapp 
5 # npx 用户也可以使用
6 $ npx taro build --type weapp

注意:去掉 --watch 将不会监听文件修改,并会对代码进行压缩打包

其他端的预览/打包项目与H5的类似,只需把H5替换为其他的即可,如下:

  1. 百度只能小程序:swan
  2. 支付宝小程序:alipay
  3. React-Native:rn
  4. 头条/字节跳动小程序:tt

三,配置项目架构

 3.1,配置dva

第一步:安装所需的依赖

1 npm/cnpm install --save dva-loading dva-core redux-logger

第二步:配置dva入口

 1 import Taro from '@tarojs/taro';
 2 import { create } from 'dva-core';
 3 // import { createLogger } from 'redux-logger';
 4 import createLoading from 'dva-loading';
 5 
 6 let app;
 7 let store;
 8 let dispatch;
 9 
10 function createApp(opt) {
11   // redux日志
12   // opt.OnAction= [createLogger()];
13   app = create(opt);
14   app.use(createLoading({}));
15 
16   // 适配支付宝小程序
17   if (Taro.getEnv() === Taro.ENV_TYPE.ALIPAY) {
18     global = {};
19   }
20 
21   //注册models
22   if (!global.registered) opt.models.forEach(model => app.model(model));
23   global.registered = true;
24   app.start();//启动
25 
26   store = app._store;
27   app.getStore = () => store;
28 
29   dispatch = store.dispatch;
30 
31   app.dispatch = dispatch;
32   return app;
33 }
34 
35 export default {
36   createApp,
37   getDispatch() {
38     return app.dispatch;
39   },
40 };

第三步:配置models文件-home

 1 import {STATUSSUCCESS} from '../utils/const';
 2 import {
 3     Home as namespace,
 4   } from '../utils/namespace';
 5 import {
 6   getSingleDataById,
 7 } from '../services/home';
 8 
 9 export default {
10   namespace: namespace,//'home',
11   state: {
12     singleId:'',
13     tableName:'',
14   },
15   effects: {
16     *getSingleData(_, { call, put,select }) {
17       const { singleId, tableName } = yield select(state => state[namespace]);
18       console.log('singleId===',singleId)
19       const { status, data } = yield call(getSingleDataById, {
20         singleId,
21         tableName,
22       });
23       if (status ==STATUSSUCCESS) {
24         yield put({
25           type: 'save',
26           payload: {
27             banner: data.banner,
28             brands: data.brands,
29           },
30         });
31       }
32     },
33   },
34   reducers: {
35     save(state, { payload }) {
36       return { ...state, ...payload };
37     },
38   },
39 };

第四步:配置models的统一入口

1 import home from './home';
2 
3 export default [ home];

第五步:引入到项目入口文件

1 import dva from './entries';
2 import models from './models';

第六步:在项目入口文件配置

 1 ...
 2 
 3 import { Provider } from '@tarojs/redux';
 4 
 5 ...
 6 
 7 const dvaApp = dva.createApp({
 8   initialState: {},
 9   models: models,
10 });
11 const store = dvaApp.getStore();
12 
13 ...
14 
15  render() {
16     return (
17       
18        ...
19       
20     );
21   }
22 
23 ...

 3.2,配置服务请求

 第一步:配置请求方式与返回状态

1 export const GET = 'GET';
2 export const POST = 'POST';
3 export const PUT = 'PUT';
4 export const PATCH = 'PATCH';
5 export const DELETE = 'DELETE';
6 export const UPDATE = 'UPDATE';
7 
8 export const STATUSSUCCESS = 1;//成功返回状态

第二步:配置请求基础地址与日志是否打印

1 import Taro from '@tarojs/taro';
2 // 请求连接前缀
3 export const baseUrl = Taro.getEnv() === Taro.ENV_TYPE.WEB?'':'http://localhost:8880';//web端使用代理服务,小程序端使用服务前缀
4 
5 // 开发环境输出日志信息
6 export const noCOnsole= (process.env.NODE_ENV === 'development');

第三步:封装request

 1 import Taro from '@tarojs/taro';
 2 import {STATUSSUCCESS} from './const';
 3 import { baseUrl, noConsole } from '../config';
 4 
 5 function checkHttpStatus(response) {
 6  
 7   if (!!noConsole) {
 8     console.log('respOnse===',response)
 9   }
10   if (response.statusCode >= 200 && response.statusCode <300) {
11     return response.data;
12   }
13   const error = new Error(response.statusText);
14   error.respOnse= response;
15   error.code = response.status;
16   throw error;
17 }
18 
19 function getResult(json) {
20   // const {dispatch} = store;
21   if (json.status ==STATUSSUCCESS) {
22     return json;
23   }
24   else {
25     const error = new Error(json.message || json.msg || '数据加载错误!');
26     error.code = json.code;
27     error.data = json;
28     throw error;
29   }
30 }
31 
32 export default (url = '', optiOns= {},) => {
33   let data;
34   let contentType;
35   data = options.data;
36   delete options.data;
37   cOntentType= options.contentType;
38   delete options.contentType;
39   const opts = {
40     url: baseUrl + url,
41     method: 'POST',
42     ...options
43   };
44   opts.header = {
45     ...opts.header,
46   };
47   
48 // 请求连接前缀
49   if (opts.method === 'GET') {
50      url = url.split('?');
51      url = url[0] + '?' + QueryString.stringify(url[1] ? {...QueryString.parse(url[1]), ...data} : data);
52      opts.headers['Content-type'] = contentType ? contentType : 'application/x-www-form-urlencoded'; //
53 
54   } else {
55     opts.header['Content-Type'] = contentType ? contentType : 'application/x-www-form-urlencoded'; //
56     opts.data = cOntentType=== 'application/json' ? JSON.stringify(data) : serialize(data);
57   }
58   if (!!noConsole) {
59     console.log(
60       `${new Date().toLocaleString()}【 request  ${url} 】DATA=${JSON.stringify(
61         data
62       )}`
63     );
64   }
65   return Taro.request(opts)
66   .then(checkHttpStatus)
67   .then(getResult)
68   .catch(err => ({err}));
69 };

第四步:请求服务

1 import request from '../utils/request';
2 import {PUT, POST} from '../utils/const';
3 
4 /*
5 ***获取单个登录数据***
6 */
7 export async function getSingleDataById(data) {
8   return request('/api/v1/yingqi/user/getSingleDataById', {data, method: PUT, contentType: 'application/json'});
9 }

 3.3,配置UI组件

 第一步:安装UI组件taro-ui

1 npm/cnpm install taro-ui --save

第二步:配置需要额外编译的源码模块

由于引用 `node_modules` 的模块,默认不会编译,所以需要额外给 H5 配置 `esnextModules`,在 taro 项目的 `config/index.js` 中新增如下配置项:

1 h5: {
2   esnextModules: ['taro-ui']
3 }

第三步:使用taro-ui

1 // page.js
2 import { AtButton } from 'taro-ui'
3 // 除了引入所需的组件,还需要手动引入组件样式
4 // app.js
5 import 'taro-ui/dist/style/index.scss' // 全局引入一次即可
1  <AtButton
2         onClick={this.handleChange.bind(this)}>
3         底部关闭幕帘
4       AtButton>

3.4,配置iconfont图标

 第一步:在iconfont上创建项目

第二步:上传图标并生成代码

第三步:在项目中配置

 1 @font-face {
 2   font-family: 'iconfont';  /* project id 1076290 */
 3   src: url('http://at.alicdn.com/t/font_1076290_m2xyh7ml7qi.eot');
 4   src: url('http://at.alicdn.com/t/font_1076290_m2xyh7ml7qi.eot?#iefix') format('embedded-opentype'),
 5   url('http://at.alicdn.com/t/font_1076290_m2xyh7ml7qi.woff2') format('woff2'),
 6   url('http://at.alicdn.com/t/font_1076290_m2xyh7ml7qi.woff') format('woff'),
 7   url('http://at.alicdn.com/t/font_1076290_m2xyh7ml7qi.ttf') format('truetype'),
 8   url('http://at.alicdn.com/t/font_1076290_m2xyh7ml7qi.svg#iconfont') format('svg');
 9 }
10 
11 .iconfont {
12   font-family: 'iconfont' !important;
13   font-size: 32px;
14   font-style: normal;
15   -webkit-font-smoothing: antialiased;
16   -moz-osx-font-smoothing: grayscale;
17 }
18 
19 .icon-more:before {
20   content: '\e605';
21 }

第四步:使用

1 <View className="iconfont icon-more arrow" />

效果如下:

四,常见问题

1,问题:使用inconfont图标时,web端没有显示图标

解决办法:在每一行//at.alicdn.com/t/font_1076290_m2xyh7ml7qi.eot前加“https:”

 

2,问题:Taro发起请求参数无法识别content-type类型

原因:由于常用的axios/fetch请求参数的头部是headers,而taro的是header,如果继续使用headers会引发content-type设置失效,变成默认的类型。

解决办法:headers->header

1  opts.header = {
2     ...opts.header,
3   };

 


推荐阅读
  • 云开发与
    大家好,今天我来为大家分享一下,Linux命令查询小程序中的WePY云开发实践。WhyWePY首先,先分享一下为什么要选择WePY?在项目开始进行选型的时候,我可选的底层框架有We ... [详细]
  • 安卓ndk开发!高级Android晋升之View渲染机制,附答案
    缘起深圳市腾讯计算机系统有限公司成立于1998年11月,是中国最大的互联网综合服务提供商之一,也是中国服务用户最多的互联网企业之一。腾讯业务多元化& ... [详细]
  • Android中高级面试必知必会,积累总结
    本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
  • 微信民众号商城/小顺序商城开源项目介绍及使用教程
    本文介绍了一个基于WeiPHP5.0开发的微信民众号商城/小顺序商城的开源项目,包括前端和后端的目录结构,以及所使用的技术栈。同时提供了项目的运行和打包方法,并分享了一些调试和开发经验。最后还附上了在线预览和GitHub商城源码的链接,以及加入前端交流QQ群的方式。 ... [详细]
  • 这篇文章主要讲解了“如何应对Android面试”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何应对 ... [详细]
  • 小程序wxs中的时间格式化以及格式化时间和date时间互转
    本文介绍了在小程序wxs中进行时间格式化操作的问题,并提供了解决方法。同时还介绍了格式化时间和date时间的互相转换的方法。 ... [详细]
  • 手把手教你使用GraphPad Prism和Excel绘制回归分析结果的森林图
    本文介绍了使用GraphPad Prism和Excel绘制回归分析结果的森林图的方法。通过展示森林图,可以更加直观地将回归分析结果可视化。GraphPad Prism是一款专门为医学专业人士设计的绘图软件,同时也兼顾统计分析的功能,操作便捷,可以帮助科研人员轻松绘制出高质量的专业图形。文章以一篇发表在JACC杂志上的研究为例,利用其中的多因素回归分析结果来绘制森林图。通过本文的指导,读者可以学会如何使用GraphPad Prism和Excel绘制回归分析结果的森林图。 ... [详细]
  • 本文概述了JNI的原理以及常用方法。JNI提供了一种Java字节码调用C/C++的解决方案,但引用类型不能直接在Native层使用,需要进行类型转化。多维数组(包括二维数组)都是引用类型,需要使用jobjectArray类型来存取其值。此外,由于Java支持函数重载,根据函数名无法找到对应的JNI函数,因此介绍了JNI函数签名信息的解决方案。 ... [详细]
  • 本文是一篇翻译文章,介绍了async/await的用法和特点。async关键字被放置在函数前面,意味着该函数总是返回一个promise。文章还提到了可以显式返回一个promise的方法。该特性使得async/await更易于理解和使用。本文还提到了一些可能的错误,并希望读者能够指正。 ... [详细]
  • loader资源模块加载器webpack资源模块加载webpack内部(内部loader)默认只会处理javascript文件,也就是说它会把打包过程中所有遇到的 ... [详细]
  • 起因由于我录制过一个小程序的课程,里面有消息模板的讲解。最近有几位同学反馈官方要取消消息模板,使用订阅消息。为了方便大家容易学 PythonFlask构建微信小程序订餐系统 课程。 ... [详细]
  • 这个问题困扰了我两天,卸载Dr.COM客户端(我们学校上网要装这个客户端登陆服务器,以后只能在网页里输入用户名和密码了),问题解决了。问题的现象:在实验室机台式机上安装openfire和sp ... [详细]
  • React 小白初入门
    推荐学习:React官方文档:https:react.docschina.orgReact菜鸟教程:https:www.runoob.c ... [详细]
  • 前言:原本纠结于Web模板,选了Handlebars。后来发现页面都是弱逻辑的,不支持复杂逻辑表达式。几乎要放弃之际,想起了Javascript中ev ... [详细]
  • 前言:原本纠结于Web 模板,选了Handlebars。后来发现页面都是弱逻辑的,不支持复杂逻辑表达式。几乎要放弃之际,想起了Javascript中eval函数。虽然eval函 ... [详细]
author-avatar
玉龙惊云诱惑_786_286
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有