“This article has participated in the good article call order activity, click to see: back end, big front end double track submission, 20,000 yuan prize pool for you to challenge!
preface
Recently, the company is preparing to develop a scanning code billing type of micro channel small program, time is tight, urgent task. The first reaction is to open the small program open platform to view the development documents, oh huo, the official components are too few, do you want to write it by hand? Through multi-party research, it is understood that Uniapp and Taro are the most popular small program development frameworks in the market. Since the company’s technology stack is fully developed using React Hooks + TS, Taro is the natural choice of framework.
Introduction of Taro
Taro is an open cross-end cross-framework solution that supports the use of React/Vue/Nerv frameworks to develop applications such as wechat/JD/Baidu/Alipay/Bytedance/QQ Mini Program/H5 / RN. At present, the upper end of the market has a variety of forms, such as Web, React Native, wechat small program and other terminals are popular. When business requirements are required to perform on different ends at the same time, the cost of writing multiple sets of code for different ends is obviously very high, and the ability to write only one set of code to be able to adapt to multiple ends is extremely necessary.
Installation and use
The Taro project is based on node. Make sure you have a relatively new node environment (>=12.0.0). It is recommended to use the node version management tool NVM to manage nodes.
CLI Tool Installation
First, you need to use NPM or yarn global install @tarojs/cli, or use NPX directly:
Install the CLI using NPM
npm install -g @tarojs/cli
# OR Use Yarn to install the CLI
yarn global add @tarojs/cli
# OR install CNPM, use CNPM to install CLI
cnpm install -g @tarojs/cli
Copy the code
NPM 5.2+ can also use NPX to create a template project without a global installation:
npx @tarojs/cli init taro_init_template
Copy the code
For convenience, it is recommended to create a template project using NPX directly
Run & start the project
# yarn
yarn dev:weapp
yarn build:weapp
# npm script
npm run dev:weapp
npm run build:weapp
# Global installation only
taro build --type weapp --watch
taro build --type weapp
# NPX users can also use it
npx taro build --type weapp --watch
npx taro build --type weapp
# Watch Also enables compression
$ set NODE_ENV=production && taro build --type weapp --watch # Windows
$ NODE_ENV=production taro build --type weapp --watch # Mac
Copy the code
The above is the compilation command of wechat small program, and other small program compilation can be viewed in the package.json folder under the project folder
Run the small program, you will find an additional dist folder in the project directory, open the wechat developer tool, log in with your own wechat signal, click + in the small program interface, import the project, define the project name by yourself, select the folder dist folder under the newly created template project, AppId can temporarily use the test number oh, Later you can register one for development use.
[Sitemap Index Information] According to the Sitemap rule [0], the current page [pages/index/index] will be indexed
Json => setting => checkSiteMap
{
"miniprogramRoot": "dist/"."projectname": "taro_template"."description": "taro_template"."appid": "touristappid"."setting": {
"urlCheck": true."es6": false."postcss": false."preloadBackgroundData": false."minified": false."newFeature": true."autoAudits": false."coverView": true."showShadowRootInWxmlPanel": false."scopeDataCheck": false."useCompilerModule": false.// Add it here
"checkSiteMap":false
},
"compileType": "miniprogram"."simulatorType": "wechat"."simulatorPluginLibVersion": {},
"condition": {}}Copy the code
Quickly create new page & Add TabBar
Taro Create –name [page name] can quickly generate a new page file in the pages directory of the current project and fill in the base code. It is a powerful tool to improve development efficiency. Add a page and configure app.config.ts
App.config. ts Complete configuration
export default {
pages: [
"pages/index/index"."pages/setting/setting".// "pages/login/login"].subpackages: [{root: "pages/login/".pages: [
"login"]}],window: {
backgroundTextStyle: "light".navigationBarBackgroundColor: "#fff".navigationBarTitleText: "WeChat".navigationBarTextStyle: "black"
},
tabBar: {
list: [{pagePath: "pages/index/index".text: "Home page".iconPath: "assets/images/tab_index.png".selectedIconPath: "assets/images/tab_index_active.png"
},
{
pagePath: "pages/setting/setting".text: "Personal center".iconPath: "assets/images/tab_setting.png".selectedIconPath: "assets/images/tab_setting_active.png"}].color: "#BFBFBF".selectedColor: "#1296DB".backgroundColor: "#fff".borderStyle: "white"}};Copy the code
The app.config.ts file has subpackages added to it. Here’s how this configuration works
Subpackages subcontract
When the small program is started, the main package will be downloaded and the page in the main package will be started by default. When the user enters a page in the subpackage, the client will download the corresponding subpackage and display it after the download is complete.
At present, the size of small program subcontract has the following restrictions:
- The subcontract size of the whole small program shall not exceed 20M
- The size of a single subcontract or main package cannot exceed 2M
Note: Subcontracting cannot be used as tabbar pages. Subcontracting pages can be added to subpackages and removed from Pages
routing
Taro.switchTab(option)
Go to the tabBar page and close all other non-Tabbar pages
Taro.reLaunch(option)
Close all pages and open a page in the application
Taro.redirectTo(option)
The current page is closed and a page in the application is displayed. However, jumping to the Tabbar page is not allowed.
Taro.navigateTo(option)
Keep the current page and go to a page in the application. But you can’t jump to the Tabbar page. Use Taro. NavigateBack to return to the original page. The page stack in the applet is up to ten layers.
Taro.navigateBack(option)
Close the current page and return to the previous page or multilevel page. You can use getCurrentPages to get the current stack of pages and determine how many layers to return.
For details about how to use routes, see the official document.
Request encapsulates Taro. Request
Defining a unified state
export const HTTP_STATUS = {
SUCCESS: 200.CREATED: 201.ACCEPTED: 202.CLIENT_ERROR: 400.AUTHENTICATE: 301.FORBIDDEN: 403.NOT_FOUND: 404.SERVER_ERROR: 500.BAD_GATEWAY: 502.SERVICE_UNAVAILABLE: 503.GATEWAY_TIMEOUT: 504
}
export const REFRESH_STATUS = {
NORMAL: 0.REFRESHING: 1.NO_MORE_DATA: 2
}
Copy the code
Define an error uniform output method
import { formatTime } from ".. /utils/common"
/ * * * *@param {string} Name Indicates the incorrect name *@param {string} Action Description of the error action *@param {string} Info Error message, usually */ returned by fail
// eslint-disable-next-line
export const logError = (name: string, action: string, info? :string | object ) = > {
if(! info) { info ='empty'
}
let time = formatTime(new Date())
console.error(time, name, action, info)
if (typeof info === 'object') {
info = JSON.stringify(info)
}
}
Copy the code
Define the request. Ts
import Taro from '@tarojs/taro'
import { HTTP_STATUS } from './status'
import { logError } from './error'
import { baseUrl } from './baseUrl'
import { checkLogin } from "./auth"
export default {
baseOptions(params, method = 'GET') {
let { url, data } = params
let contentType = 'application/json'
contentType = params.contentType || contentType
type OptionType = {
url: string, data? :object | string, method? :any.header: object.// mode: string,
success: any.error: any.xhrFields: object,}const setCookie = (res: {
cookies: Array<{
name: string,
value: string,
expires: string,
path: string
}>,
header: {
'Set-Cookie': string}}) = > {
if (res.cookies && res.cookies.length > 0) {
let cookies = Taro.getStorageSync('cookies') | |' ';
res.cookies.forEach((cookie, index) = > {
// Windows wechat developer tool returns cookie format with name and value, on MAC it is just a string
if (cookie.name && cookie.value) {
cookies += index === res.cookies.length - 1 ? `${cookie.name}=${cookie.value}; expires=${cookie.expires}; path=${cookie.path}` : `${cookie.name}=${cookie.value}; `
} else {
cookies += `${cookie}; `}}); Taro.setStorageSync('cookies', cookies)
}
// if (res.header && res.header['Set-Cookie']) {
// Taro.setStorageSync('cookies', res.header['Set-Cookie'])
// }
}
const option: OptionType = {
url: url.indexOf('http')! = = -1 ? url : baseUrl + url,
data: data,
method: method,
header: {
'content-type': contentType,
// Add the request header
cookie: Taro.getStorageSync('cookies')},// mode: 'cors',
xhrFields: { withCredentials: true },
success(res) {
console.log('res', res)
setCookie(res)
if (res.statusCode === HTTP_STATUS.NOT_FOUND) {
return logError('api'.'Requested resource does not exist')}else if (res.statusCode === HTTP_STATUS.BAD_GATEWAY) {
return logError('api'.'There is a server problem')}else if (res.statusCode === HTTP_STATUS.FORBIDDEN) {
return logError('api'.'No access')}else if (res.statusCode === HTTP_STATUS.AUTHENTICATE) {
Taro.clearStorage()
// Go to the login page
checkLogin()
return logError('api'.'Please login first')}else if (res.statusCode === HTTP_STATUS.SUCCESS) {
return res.data
}
},
error(e) {
logError('api'.'Request interface problem', e)
}
}
// eslint-disable-next-line
return Taro.request(option)
},
get(url, data? :object) {
let option = { url, data }
return this.baseOptions(option)
},
post: function (url, data? :object, contentType? :string) {
let params = { url, data, contentType }
return this.baseOptions(params, 'POST')},put(url, data? :object) {
let option = { url, data }
return this.baseOptions(option, 'PUT')},delete(url, data? :object) {
let option = { url, data }
return this.baseOptions(option, 'DELETE')}}Copy the code
Define the baseUrl. Ts
export const baseUrl = 'http://172.36.0.26:3000'
Copy the code
Define the API. Ts
import request from "./request"
export const getDetail = (params):Promise<any> = > {return request.get('/url', params)
}
Copy the code
Component
const getDetail = () = >{
api.getDetail({
data: 1232
}).then((res) = >{
console.log(res)
})
}
Copy the code
Dva integration use
React state Management library: Redux, Dva, Mobx… This building uses Dva to build. Finally, the reason why WE choose Dva is completely to try new things, because we have been using Redux in previous projects, and we must know the complexity of Redux. You can also try Mobx. Mobx is arguably the cleanest of these libraries.
Of course, useContext() in hooks is also a solution for sharing state between components.
The installation
npm install --save dva-core dva-loading
npm install --save redux react-redux redux-thunk redux-logger
Copy the code
New SRC/utils/dva. Ts
// src/utils/dva.ts
import {create } from 'dva-core';
// import {createLogger } from 'redux-logger';
import createLoading from 'dva-loading';
let app: {use: (arg0: any) = > void; model: (arg0: any) = > any; start: () = > void; _store: any; getStore: () = > any; dispatch: any};
let store: {dispatch: any};
let dispatch: any;
let registered: boolean;
function createApp(opt: {models: any[]; initialState: any }) {
// Redux logs, refer to redux-logger
// opt.onAction = [createLogger()];
app = create(opt);
app.use(createLoading({}));
if(! registered) opt.models.forEach((model: any) = > app.model(model));
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;
},
getStore() { // This is a method to get the Store from a non-component file
returnapp.getStore(); }};Copy the code
Add the Models folder
Models is dedicated to managing your own data in a unified manner
models/index.ts
import { GlobalModelState } from "./setting/types"
import setting from "./setting/index"
const models:Array<GlobalModelState> = [
setting
]
export default models
Copy the code
models/setting/index.ts
import * as types from "./types";
const setting: types.GlobalModelState = {
namespace: "setting".state: {
userInfo: {}},// Modify the data in state
reducers: {
setUserInfo(state, { data }) {
console.log(data);
return {
...state,
userInfo: data.userInfo }; }}// Modify the data in state after the asynchronous operation
// effects: {
// *changeName({ payload }, { put, call }) {
// // Call triggers asynchrony
// // let data = yield call("/api", payload);
// // put Triggers the action
// yield put({
// type: "saveName",
// data: {
// name: "asynchronously modified ",
/ /},
/ /});
// yield console.log("run");
/ /},
// },
};
export default setting;
Copy the code
Entrance to the integration
Change the entry file app.ts to app. TSX, and introduce Provider, DVA, and Models.
import { Component, useEffect } from "react";
import { View, Text } from "@tarojs/components";
import "./app.scss";
// React-redux must be used here or an error will be reported
import { Provider } from "react-redux";
import dva from "./utils/dva";
import models from "./models";
/ / integration dva
const dvaApp = dva.createApp({
initialState: {},
models,
enableLog: false
});
const store = dvaApp.getStore();
const App: React.FC = ({ children }): JSX.Element => {
return <Provider store={store}>{children}</Provider>;
};
export default App;
Copy the code
Get data from the Store (useSelector)
const userInfo = useSelector(state= > state.setting.userInfo).nickName
Copy the code
Modifying data in a Store (useDispatch)
dispatch({
type:"setting/setUserInfo".data:{
userInfo
}
})
Copy the code
Page adaptation problem
By default, Taro is automatically converted to designWidth: 750. If the UI is given a 375 width, you can change it to config => **index.js **
designWidth: 750.deviceRatio: {
640: 2.34 / 2.750: 1.828: 1.81 / 2.375: 2
},
Copy the code
Of course, just changing the above part is not enough. Run the project at this time, and you will find that the taro UI component style becomes very large. What? The component is magnified twice? Do not panic, as follows can be configured
yarn add postcss-px-scale
Copy the code
const config = {
projectName: "taro_template".date: "2021-6-23".designWidth: 750.deviceRatio: {
640: 2.34 / 2.750: 1.828: 1.81 / 2.375: 2
},
sourceRoot: "src".outputRoot: "dist".plugins: [].defineConstants: {},
copy: {
patterns: [].options: {}},framework: "react".mini: {
postcss: {
pxtransform: {
enable: true.config: {}},url: {
enable: true.config: {
limit: 1024 // Set the upper limit of the conversion size}},cssModules: {
enable: false.// The default is false, or true if you need to use CSS Modules
config: {
namingPattern: "module".// The conversion mode is global/module
generateScopedName: "[name]__[local]___[hash:base64:5]"}},// Add configuration here
"postcss-px-scale": {
enable: true.config: { scale: 0.5.units: "rpx".includes: ["taro-ui"]}},},},h5: {
publicPath: "/".staticDirectory: "static".esnextModules: ['taro-ui'].postcss: {
autoprefixer: {
enable: true.config: {}},cssModules: {
enable: false.// The default is false, or true if you need to use CSS Modules
config: {
namingPattern: "module".// The conversion mode is global/module
generateScopedName: "[name]__[local]___[hash:base64:5]"}},// Add configuration here
"postcss-px-scale": {
enable: true.config: { scale: 0.5.units: "rem".includes: ["taro-ui"]}},},}};module.exports = function(merge) {
if (process.env.NODE_ENV === "development") {
return merge({}, config, require("./dev"));
}
return merge({}, config, require("./prod"));
};
Copy the code
Qr code scanning function
Scan code function is very simple, you can directly call the official method provided
Taro.scanCode({
success: result= > {
console.log("Callback for successful scan", result); }});Copy the code
See the official documentation for more usage, but I won’t introduce it here.
Debugging tips – Minidebug
Function is introduced
The main features include environment switching, identity Mock, application information acquisition, location simulation, cache management, scan, H5 jump, update version, etc.
The installation
yarn add @jdlfe/minidebug-next
Copy the code
Create a blank page debug
Use the CLI to quickly create a page
Taro create -- debug
Copy the code
Introducing component Debug
import { View } from '@tarojs/components'
import { Debug } from '@jdlfe/minidebug-next'
import './debug.scss'
const Bug: React.FC = () = > {
return (
<View>
<Debug />
</View>
);
};
export default Bug;
Copy the code
Add a page configuration entry to open pages. Pages should be configured in subpackages otherwise the main package will be too large.
For more usage, see github.com/jdlfe/minid…
The source address
Github repository address
Finally, let’s introduce ourselves
Everybody is good, I am front side dish chicken of dish chicken each other peck, a front end development of some unknown small company moves brick member. This is my first post on the Nuggets, and I have to say that writing articles is exhausting, much more so than writing code, so I hope you can support me a lot. Later will continue to output some new articles.
You can also follow my public number: front-end development enthusiasts every day will collect some big guy articles and create some original articles, welcome to follow me.