JS构建多端应用

一,需求与介绍

1.1,介绍

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

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

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

1.2,需求

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

二,搭建项目

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

 npm/cnpm install -g @tarojs/cli

第二步:创建项目

 taro init YingQi

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

 npm/cnpm install

第三步:运行项目

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

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

1.H5

H5预览项目

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

H5打包项目

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

2.微信小程序

微信小程序预览项目

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

微信小程序打包项目

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

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

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

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

三,配置项目架构

3.1,配置dva

第一步:安装所需的依赖

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

第二步:配置dva入口

 import Taro from '@tarojs/taro';
import { create } from 'dva-core';
// import { createLogger } from 'redux-logger';
import createLoading from 'dva-loading'; let app;
let store;
let dispatch; function createApp(opt) {
// redux日志
// opt.onAction = [createLogger()];
app = create(opt);
app.use(createLoading({})); // 适配支付宝小程序
if (Taro.getEnv() === Taro.ENV_TYPE.ALIPAY) {
global = {};
} //注册models
if (!global.registered) opt.models.forEach(model => app.model(model));
global.registered = true;
app.start();//启动 store = app._store;
app.getStore = () => store; dispatch = store.dispatch; app.dispatch = dispatch;
return app;
} export default {
createApp,
getDispatch() {
return app.dispatch;
},
};

第三步:配置models文件-home

 import {STATUSSUCCESS} from '../utils/const';
import {
Home as namespace,
} from '../utils/namespace';
import {
getSingleDataById,
} from '../services/home'; export default {
namespace: namespace,//'home',
state: {
singleId:'',
tableName:'',
},
effects: {
*getSingleData(_, { call, put,select }) {
const { singleId, tableName } = yield select(state => state[namespace]);
console.log('singleId===',singleId)
const { status, data } = yield call(getSingleDataById, {
singleId,
tableName,
});
if (status ==STATUSSUCCESS) {
yield put({
type: 'save',
payload: {
banner: data.banner,
brands: data.brands,
},
});
}
},
},
reducers: {
save(state, { payload }) {
return { ...state, ...payload };
},
},
};

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

 import home from './home';

 export default [ home];

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

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

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

 ...

 import { Provider } from '@tarojs/redux';

 ...

 const dvaApp = dva.createApp({
initialState: {},
models: models,
});
const store = dvaApp.getStore(); ... render() {
return (
<Provider store={store}>
...
</Provider>
);
} ...

3.2,配置服务请求

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

 export const GET = 'GET';
export const POST = 'POST';
export const PUT = 'PUT';
export const PATCH = 'PATCH';
export const DELETE = 'DELETE';
export const UPDATE = 'UPDATE'; export const STATUSSUCCESS = 1;//成功返回状态

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

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

第三步:封装request

 import Taro from '@tarojs/taro';
import {STATUSSUCCESS} from './const';
import { baseUrl, noConsole } from '../config'; function checkHttpStatus(response) { if (!!noConsole) {
console.log('response===',response)
}
if (response.statusCode >= 200 && response.statusCode < 300) {
return response.data;
}
const error = new Error(response.statusText);
error.response = response;
error.code = response.status;
throw error;
} function getResult(json) {
// const {dispatch} = store;
if (json.status ==STATUSSUCCESS) {
return json;
}
else {
const error = new Error(json.message || json.msg || '数据加载错误!');
error.code = json.code;
error.data = json;
throw error;
}
} export default (url = '', options = {},) => {
let data;
let contentType;
data = options.data;
delete options.data;
contentType = options.contentType;
delete options.contentType;
const opts = {
url: baseUrl + url,
method: 'POST',
...options
};
opts.header = {
...opts.header,
}; // 请求连接前缀
if (opts.method === 'GET') {
url = url.split('?');
url = url[0] + '?' + QueryString.stringify(url[1] ? {...QueryString.parse(url[1]), ...data} : data);
opts.headers['Content-type'] = contentType ? contentType : 'application/x-www-form-urlencoded'; // } else {
opts.header['Content-Type'] = contentType ? contentType : 'application/x-www-form-urlencoded'; //
opts.data = contentType === 'application/json' ? JSON.stringify(data) : serialize(data);
}
if (!!noConsole) {
console.log(
`${new Date().toLocaleString()}【 request ${url} 】DATA=${JSON.stringify(
data
)}`
);
}
return Taro.request(opts)
.then(checkHttpStatus)
.then(getResult)
.catch(err => ({err}));
};

第四步:请求服务

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

3.3,配置UI组件

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

 npm/cnpm install taro-ui --save

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

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

 h5: {
esnextModules: ['taro-ui']
}

第三步:使用taro-ui

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

3.4,配置iconfont图标

第一步:iconfont上创建项目

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

第三步:在项目中配置

 @font-face {
font-family: 'iconfont'; /* project id 1076290 */
src: url('http://at.alicdn.com/t/font_1076290_m2xyh7ml7qi.eot');
src: url('http://at.alicdn.com/t/font_1076290_m2xyh7ml7qi.eot?#iefix') format('embedded-opentype'),
url('http://at.alicdn.com/t/font_1076290_m2xyh7ml7qi.woff2') format('woff2'),
url('http://at.alicdn.com/t/font_1076290_m2xyh7ml7qi.woff') format('woff'),
url('http://at.alicdn.com/t/font_1076290_m2xyh7ml7qi.ttf') format('truetype'),
url('http://at.alicdn.com/t/font_1076290_m2xyh7ml7qi.svg#iconfont') format('svg');
} .iconfont {
font-family: 'iconfont' !important;
font-size: 32px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
} .icon-more:before {
content: '\e605';
}

第四步:使用

 <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

  opts.header = {
...opts.header,
};

JS构建多端应用的更多相关文章

  1. next.js、nuxt.js等服务端渲染框架构建的项目部署到服务器,并用PM2守护程序

    前端渲染:vue.react等单页面项目应该这样子部署到服务器 貌似从前几年,前后端分离逐渐就开始流行起来,把一些渲染计算的工作抛向前端以便减轻服务端的压力,但为啥现在又开始流行在服务端渲染了呢?如v ...

  2. Phonegap 之 iOS银联在线支付(js调用ios端银联支付控件)

    Phonegap项目,做支付的时候,当把网站打包到ios或android端成app后,在app上通过wap调用银联在线存在一个问题: 就是当从银联支付成功后,再从服务器返回到app客户端就很难实现. ...

  3. 通过Web Api 和 Angular.js 构建单页面的web 程序

    通过Web Api 和 Angular.js 构建单页面的web 程序 在传统的web 应用程序中,浏览器端通过向服务器端发送请求,然后服务器端根据这个请求发送HTML到浏览器,这个响应将会影响整个的 ...

  4. Vue 爬坑之路(十一)—— 基于 Nuxt.js 实现服务端渲染(SSR)

    直接使用 Vue 构建前端单页面应用,页面源码时只有简单的几行 html,这并不利于网站的 SEO,这时候就需要服务端渲染 2016 年 10 月 25 日,zeit.co 背后的团队对外发布了一个 ...

  5. 基于VUE.JS的移动端框架Mint UI

    Mint UI GitHub:github.com/ElemeFE/mint 项目主页:mint-ui.github.io/# Demo:elemefe.github.io/mint- 文档:mint ...

  6. 从Hybrid到React-Native: JS在移动端的南征北战史

    注:因为不了解Dart,所以本文不对flutter相关内容进行阐述, 实在抱歉 Hybrid Hybird是一种混合开发应用,可以实现JS和Java代码的互通,单纯使用ios/android原生实现, ...

  7. 解析Nuxt.js Vue服务端渲染摸索

    本篇文章主要介绍了详解Nuxt.js Vue服务端渲染摸索,写的十分的全面细致,具有一定的参考价值,对此有需要的朋友可以参考学习下.如有不足之处,欢迎批评指正. Nuxt.js 十分简单易用.一个简单 ...

  8. 基于Vue.js PC桌面端弹出框组件|vue自定义弹层组件|vue模态框

    vue.js构建的轻量级PC网页端交互式弹层组件VLayer. 前段时间有分享过一个vue移动端弹窗组件,今天给大家分享一个最近开发的vue pc端弹出层组件. VLayer 一款集Alert.Dia ...

  9. NativeScript - JS 构建跨平台的原生 APP

    使用 NativeScript,你可以用现有的 JavaScript 和 CSS 技术来编写 iOS.Android 和 Windows Phone 原生移动应用程序.由原生平台的呈现引擎呈现界面而不 ...

随机推荐

  1. Netty源码分析-- 处理客户端接入请求(八)

    这一节我们来一起看下,一个客户端接入进来是什么情况.首先我们根据之前的分析,先启动服务端,然后打一个断点. 这个断点打在哪里呢?就是NioEventLoop上的select方法上. 然后我们启动一个客 ...

  2. 利用MAT分析JVM内存问题,从入门到精通(二)

    上一篇文章MAT入门到精通(一)介绍了MAT的使用场景和基本概念,这篇文章开始介绍MAT的基本功能,后面还有两篇,一篇是MAT的高级功能,另一篇是MAT实战案例分析. 三.欢迎页 使用MAT打开一个h ...

  3. linux修改时间显示格式

    1. 问题描述 Linux下经常使用 "ls - ll"命令查看文件夹或文件创建及权限信息,但是满屏的Mar .May.Jul有点小难受. 2. 解决方案 修改bash_profi ...

  4. requests.exceptions.ChunkedEncodingError: ('Connection broken: IncompleteRead(0 bytes read)', IncompleteRead(0 bytes read))【已解决】

     问题: 跑python自动化时出现报错如下图 解决: requests请求时,后面加上参数:stream=True. 参考外国小哥:https://stackoverflow.com/questio ...

  5. Python 为什么要继承 object 类?

    自己搬运自己在知乎上的回答,感觉破乎吃枣药丸,哪天挂了这里就是个备份. 链接:https://www.zhihu.com/question/19754936/answer/229327803 2017 ...

  6. Day1 -Python program

    采用python 3.5 用PyCharm编译 第一串代码 print ("hello,world!") 练习1 输入一个用户名和密码,如果输入正确,就欢迎登陆,否则就显示错误. ...

  7. 从无到有构建vue实战项目(六)

    十.徒手撸一个vue下拉左侧二级导航 先附上最终效果图: vue代码: <div class="dropdown-menu-explore" v-on:mouseover=& ...

  8. 万字长文:ELK(V7)部署与架构分析

    ELK(7版本)部署与架构分析 1.ELK的背景介绍与应用场景 在项目应用运行的过程中,往往会产生大量的日志,我们往往需要根据日志来定位分析我们的服务器项目运行情况与BUG产生位置.一般情况下直接在日 ...

  9. C#7.1 新增功能

    连载目录    [已更新最新开发文章,点击查看详细] C# 7.1 是 C# 语言的第一个点版本(更新版本). 它标志着该语言发布节奏的加速. 理想情况下,可以在每个新功能准备就绪时更快推出新功能.  ...

  10. 基于ng-zorro的ASP.NET ZERO前端实现

    Abp官方提供的企业版(ASP.NET ZERO)[以下简称Zero]模板中前端使用的是Metronic,本篇博客介绍使用ng-zorro和ng-alain替换官方前端,以及使用官方生成器自动生成代码 ...