1. Project background and questions
Before I made wechat mini program, I had launched an H5 project. The UI framework used in H5 was Vant, and the Vue version was 3.x. Vant Downloadp is used to maintain user experience, but the vue version mentioned in Taro uses version 2.x.
-
Why use Taro instead of Uni-app?
A: Next time use uni-app.
-
Taro, why can’t JSX get started?
A: I believe that if I do appellate the app, I will do something about it. I believe that if I do appellate the app, I will do something about it. I believe that if I do appellate the app, I will do something about it. “Depreciate” is commonly referred to as “Taro” + VUe2. x + vt-appellate.
-
If you do not have the ability to do multichannel transformations, try to do so by using vant-appellate appellate apps.
Answer: The project only requires that wechat small program can be used, not multi-terminal, so it can be safely used, and some logic in the H5 project can be reused.
2. Preparation before the project
2.1 Installation and initialization projects
2.1.1 Taro Installation + Initialization Project
Note: Node environment (>=12.0.0)
- The installation
yarn global add @tarojs/cli
Copy the code
- Initialize the
taro init taro_demo
Copy the code
- Install dependencies
# change directory
cd taro_demo
# install dependencies
yarn install
Copy the code
- Changing the root Directory
package.json
In thescripts
Under thedev:weapp
Development start command
{
"scripts" : {
- "dev:weapp": "taro build --type weapp"
+ # watch also enables compression
+ "dev:weapp": "set NODE_ENV=production && taro build --type weapp --watch"}}Copy the code
NODE_ENV = production (config/prod.js); cross-env = production (config/prod.js);
yarn add cross-env -D
Copy the code
{
"scripts" : {
- "build:weapp": "taro build --type weapp",
+ "build:weapp": "cross-env DEV_MODE_ENV=false taro build --type weapp",
- "dev:weapp": "set NODE_ENV=production && taro build --type weapp --watch"
+ "dev:weapp": "cross-env NODE_ENV=production DEV_MODE_ENV=true taro build --type weapp --watch",}}Copy the code
This allows us to distinguish between production and development based on the DEV_MODE_ENV variable we configured. Process.env. DEV_MODE_ENV is not accessible from SRC. The config directory is accessible. To access a custom env variable from SRC, set it to env in config/*.js.
// config/dev.js
module.exports = {
env: {
NODE_ENV: '"development"'.// Add the SERVICES_BASE_URL variable
SERVICES_BASE_URL: '"http://xxx"',}};// config/prod.js
module.exports = {
env: {
NODE_ENV: '"production"'.// DEV_MODE_ENV is used for production and development, so you don't have to change it manually every time
SERVICES_BASE_URL:
process.env.DEV_MODE_ENV === "true" ? "http://xxx" : "https://xxx",}};// Access to 'process.env.services_base_URL' is normally available
Copy the code
- Start the development command, and when it succeeds, you can see the newly generated root directory
dist
directory
yarn run dev:weapp
Copy the code
2.1.2 wechat developer tools
-
Download the wechat developer tool
-
Select dist and open it. No surprise, you can preview it normally.
2.2 Major Package versions in the project
The problems that follow are based on these versions.
package | version |
---|---|
Taro | 3.3.7 |
vant weapp | 1.9.2 |
echarts | 5.1.2 |
3. Use Vant retry P in Taro
3.1 to modifypostcss
Configuration without converting vant styles
// config/index.js
const config = {
mini: {
enableSourceMap: false.// It is used to control whether the sourceMap corresponding to js and CSS is generated
// http://taro-docs.jd.com/taro/docs/vant
postcss: {
pxtransform: {
enable: true.config: {
selectorBlackList: [/van-/],}},url: {
enable: true.config: {
limit: 1024,}},cssModules: {
enable: false.// The default is false, or true if you want to use CSS modules
config: {
namingPattern: "module".// Switch mode. The value can be global/module
generateScopedName: "[name]__[local]___[hash:base64:5]",},},},},};Copy the code
3.2 Configuring applets native files and components that reference Vant
3.2.1 According to the documentation, this is required when using Vant
// config/index.js
const config = {
// ...
copy: {
patterns: [
// The first three are basic
{
from: "src/components/vant-weapp/dist/wxs".to: "dist/components/vant-weapp/dist/wxs"}, {from: "src/components/vant-weapp/dist/common/style".to: "dist/components/vant-weapp/dist/common/style"}, {from: "src/components/vant-weapp/dist/common/index.wxss".to: "dist/components/vant-weapp/dist/common/index.wxss",},// Import any component that needs vant, such as button
{
from: `src/components/vant-weapp/dist/button/index.wxs`.to: `dist/components/vant-weapp/dist/button/index.wxs`}, {from: "src/components/vant-weapp/dist/button/index.wxml".to: "dist/components/vant-weapp/dist/button/index.wxml"],},options: {},}};Copy the code
// in index.config.js of the page or in global SRC /app.config.js
export default {
navigationBarTitleText: "Home page".usingComponents: {
"van-button": ".. /.. /components/vant-weapp/dist/button/index",}};Copy the code
You see, it’s a bunch of repetitive actions, and you need to use the Vant component, and you have to configure it in two places. It’s tough.
3.2.2 Upgrade and transform to optimize the introduction steps
- Root directory creation
vantComponentConf.js
file
This will take effect every time you modify the vantComponentConf file, without having to make repeated changes. Of course, you can use Babel to write a loader
Note:
- Every time a new Vant component is added, the project still has to be restarted
vite
That way, the configuration file changes will automatically restart immediately - Some vant components are still missing after rebooting. Add the missing components to the vantComponentConf. For example, button components rely on icon and loading.
const vantComponetNames = ["button"."icon"."loading"];
module.exports = vantComponetNames;
Copy the code
- Modify the
config/index.js
file
+ const path = require("path");
+ const fs = require("fs");
+ const vantComponetNames = require(".. /vantComponentConf");
+
+ const handleGetPatterns = (keyArr) => {
+ // These are public components
+ const defaultArr = [
+ {
+ from: "src/components/vant-weapp/dist/wxs",
+ to: "dist/components/vant-weapp/dist/wxs",
+},
+ {
+ from: "src/components/vant-weapp/dist/common/style",
+ to: "dist/components/vant-weapp/dist/common/style",
+},
+ {
+ from: "src/components/vant-weapp/dist/common/index.wxss",
+ to: "dist/components/vant-weapp/dist/common/index.wxss",
+},
+];
+
+ const componentArr = keyArr
+ .map((componentName) => {
+ // Synchronously checks whether the file exists
+ // Because WXS files do not exist under some component files of Vant retry P
+ const componentPath = path.resolve(
+ __dirname,
+ `.. /src/components/vant-weapp/dist/${componentName}/index.wxs`
+);
+
+ const isState = fs.statSync(componentPath, { throwIfNoEntry: false });
+
+ return [
+ {
+ from: `src/components/vant-weapp/dist/${componentName}/index.${
+ isState ? "wxs" : "wxss"
+} `,
+ to: `dist/components/vant-weapp/dist/${componentName}/index.${
+ isState ? "wxs" : "wxss"
+} `,
+},
+ {
+ from:
+ "src/components/vant-weapp/dist/" + componentName + "/index.wxml",
+ to:
+ "dist/components/vant-weapp/dist/" + componentName + "/index.wxml",
+},
+];
+})
+ .flat(Infinity);
+
+ return [...defaultArr, ...componentArr];
+};
const config = {
copy: {
+ // http://taro-docs.jd.com/taro/docs/vant
+ patterns: handleGetPatterns(vantComponetNames),
options: {},
},
}
Copy the code
- Modify the
src/app.config.js
file
+ const vantComponetNames = require(".. /vantComponentConf");
+
+ const getVantComponetConf = (arr) => {
+ const result = {};
+ arr.forEach((key) => {
+ result[`van-${key}`] = `./components/vant-weapp/dist/${key}/index`;
+});
+
+ return result;
+};
export default {
usingComponents: {
+... getVantComponetConf(vantComponetNames),}},Copy the code
4. Some problems about using Vant
4.1 The slots of some Vant components are not displayed correctly
The following search component does not display slot content correctly
<view>
<van-search use-action-slot="true" placeholder="Please enter store name to search...">
<view slot="action">search</view>
</van-search>
</view>
Copy the code
Solution:
You must use the slot-view component provided by taro. The Slot component is used in React
<template>
<view>
<van-search use-action-slot="true" placeholder="Please enter store name to search...">
<slot-view name="action">
<text>search</text>
</slot-view>
</van-search>
</view>
</template>
Copy the code
The contents of the slot are displayed correctly
4.2 vant-search
Could not get input
<template>
<view>
<van-search
:value="searchVal"
use-action-slot="true"
>
<slot-view name="action">
<text @tap.stop="onSearch">search</text>
</slot-view>
</van-search>
</view>
</template>
<script>
export default {
data() {
return {
searchVal: "",}},methods: {
onSearch() {
// No real time input values are printed
console.log("this.searchVal".this.searchVal); }}},</script>
Copy the code
Solution:
Ant – Search does not update the data synchronously by itself; you need to manually add the change event update
<template>
<view>
<van-search
:value="searchVal"
use-action-slot="true"
+ @change="onChange"> <slot-view name="action"> <text @tap.stop="onSearch"> Search </text> </slot-view> </van-search> </view> </template> <script> export default { data() { return { searchVal: "", } }, methods: {+ onChange(e) {
+ this.searchVal = e.detail;
+},
onSearch() {
console.log("this.searchVal", this.searchVal);
}
},
}
</script>
Copy the code
4.3 the use ofvan-field
Component, values for computed in vUE cannot trigger response updates
The computed property submitBtnDisabled, defined in computed, changes the value of the dependency but does not trigger a response update. No doubt, it’s not vue
<template>
<view class="phoneLoginWrap">
<form @submit="handleSubmit">
<van-cell-group>
<van-field
v-model="user"
:required="true"
name="user"
label="Account number:"
placeholder="Please enter your account number"
title-width="4em"
/>
<van-field
v-model="password"
:required="true"
name="password"
type="password"
label="Password:"
placeholder="Please enter your password"
/>
</van-cell-group>
<van-button type="info" form-type="submit" :block="true" :disabled="submitBtnDisabled">The login</van-button>
</form>
</view>
</template>
<script>
export default {
data() {
return {
user: "".password: ""}},computed: {
// Only when the page is entered for the first time
// The login button is always in disabeld state
submitBtnDisabled: function () {
return this.user ! = =' ' && this.password ! = =' ' ? false : true; }},methods: {
handleSubmit(e) {
// Vant-button Can be entered even if disabled is true
// The UI style works, but events can still be triggered
// So there is a judgment here
if (this.submitBtnDisabled) return;
console.log("login!!!", e)
}
}
}
</script>
Copy the code
Solution:
The diabled attribute of the button can be updated dynamically when the input field is changed
<template> <view class="phoneLoginWrap"> <form @submit="handleSubmit"> <van-cell-group> <van-field v-model="user" : Required ="true" name="user" label=" account: "placeholder=" Please input account"+ @change="(... args) => handleFieldChange.call(this, 'user', ... args)"/> <van-field v-model="password" :required="true" name="password" type="password" label=" password: "placeholder="+ @change="(... args) => handleFieldChange.call(this, 'password', ... args)"
/>
</van-cell-group>
<van-button type="info" form-type="submit" :block="true" :disabled="submitBtnDisabled">登录</van-button>
</form>
</view>
</template>
<script>
export default {
name: 'PhoneNumLogin',
data() {
return {
user: "",
password: ""
}
},
computed: {
submitBtnDisabled: function () {
return this.user !== '' && this.password !== '' ? false : true;
}
},
methods: {
+ handleFieldChange(type, e) {
+ const val = e.detail.trim();
+ // Update the value of data manually
+ if (type === 'user') {
+ this.user = val;
+ } else {
+ this.password = val;
+}}, handleSubmit(e) { if (this.submitBtnDisabled) return; console.log("login!!!" , e) } } } </script>Copy the code
4.4 Console alerts when vant components are in use
Cause: The verification logic was modified in the wechat base library, so the slot was not found or the properties type was not equal
5. About useec-canvas
Some of the problems with Echarts
5.1 Echarts is too large
Solution:
- Echarts online custom download
- Be sure to select zip online, place the downloaded file in ec-canvas/echarts.js, and be sure to rename it to echarts.js
5.2 EC-Canvas error. Addeventlistener is not a function
TypeError: t.addEventListener is not a function
Copy the code
Solution:
In the wx-Canvas.js file add:
// wx-canvas.js
export default class WxCanvas {
constructor(ctx, canvasId, isNew, canvasNode) {
// ...
}
+ // Add empty function to fix error when calling echarts.init
+ addEventListener() {}
}
Copy the code
5.3 EC-Canvas error This.chart. init is not a function
TypeError: this.Chart.init is not a function
Copy the code
Solution:
Taro 3.0 requires using selectComponent to get child component instances
import Taro, { getCurrentInstance } from "@tarojs/taro";
function initChart(el = "#canvasId") {
const currentIns = getCurrentInstance();
currentIns.page.selectComponent(el).init((canvas, width, height) = > {
const sysInfo = Taro.getSystemInfoSync();
const chart = echarts.init(canvas, null, {
width: width,
height: height,
devicePixelRatio: sysInfo.devicePixelRatio || sysInfo.pixelRatio, / / pixel
});
canvas.setChart(chart);
var option = {
// ...
};
chart.setOption(option);
return chart;
});
}
Copy the code
5.4 EC-Canvas interface asynchronous rendering after data request or real-time dynamic rendering after socket data acquisition
<template>
<view style="widh: 100%; height: 300px;">
<ec-canvas id="yearLineChart" canvas-id="month-line-chart" :ec="yearChart" />
</view>
</template>
<script>
import Taro from '@tarojs/taro';
import * as echarts from '@/src/components/echarts-for-weixin-master/ec-canvas/echarts';
function setOption(chart) {
var option = {
// ...
};
chart.setOption(option);
}
export default {
data() {
return {
yearChart: {
// With lazyLoad set to true, the chart needs to be initialized manually
lazyLoad: true}}},methods: {
// Initialize echarts
initChart(el, data) {
const currentIns = Taro.getCurrentInstance();
currentIns.page.selectComponent(el)
.init((canvas, width, height) = > {
const sysInfo = Taro.getSystemInfoSync();
const chart = echarts.init(canvas, null, {
width: width,
height: height,
devicePixelRatio: sysInfo.devicePixelRatio || sysInfo.pixelRatio / / pixel
});
setOption(chart, data);
// Note that the chart instance must be returned, otherwise it will affect event handling, etc
return chart;
});
},
// Ajax gets data in the background
getData() {
/ /...
// Suppose data is returned from the background
const data = {}
this.initChart('year'.'#yearLineChart', data); }},onShow() {
this.getData(); }}</script>
Copy the code
5.5 After the Echart bag is imported, it exceeds the Max of 500KB
Command line warning, resulting in each CTRL + S save code, wechat developer tools over there update slowly
[BABEL] Note: The code generator has deoptimised the styling of "unknown" as it exceeds the max of "500KB"
Copy the code
Solution:
- Config /index.js add exclude
module.exports = {
// ...
mini: {
// ...
compile: {
exclude: [
path.resolve(
__dirname,
".. /src/components/echarts-for-weixin-master/ec-canvas/echarts.js"),],},},};Copy the code
- Add in the Babel configuration file
compact: false
The default value is auto
module.exports = {
presets: [["taro",
{
framework: "vue".ts: false,}]].compact: false};Copy the code
5.6 After using EC-Canvas, a blank display is displayed on the desktop of the applets
The reason for the blank is that an error has been reported
Add force-use-old-canvas=”true” to the EC-canvas tag. However, I used version 5.1.2 for Echarts, which didn’t work.
Solution:
Windows terminal applet does not support Canvas2D, so it is modified to use the old canvas in Windows terminal
Whether the latest version fixes whether the desktop can be opened successfully, I have not verified here. I directly on the PR to modify the source code, measured effective.
Echarts-for-weixin-master /ec-canvas/ec-canvas. Js Component({methods: {- init: function (callback) {
+ init: async function (callback) {const version = wx.getSystemInfoSync().SDKVersion; Const canUseNewCanvas = compareVersion(version, "2.9.0") >= 0; const forceUseOldCanvas = this.data.forceUseOldCanvas; - const isUseNewCanvas = canUseNewCanvas && ! forceUseOldCanvas;+ // const isUseNewCanvas = canUseNewCanvas && ! forceUseOldCanvas;
+ // Fix desktop wechat open, echarts blank, console error
+ const { platform } = await wx.getSystemInfo();
+ let isUseNewCanvas = canUseNewCanvas && ! forceUseOldCanvas;
+ // Determine directly by using the re. If it is opened by wechat on the Windows desktop
+ // Set the isUseNewCanvas value to false
+ if (platform && /windows/i.test(platform)) {
+ isUseNewCanvas = false;
+}this.setData({ isUseNewCanvas }); / /... }}})Copy the code
6. Some questions about Taro
6.1 The project is too large to be previewed using wechat developer tools, so subcontracting is required
Note: Pages configured in tabBar cannot be subwritten to subpackages
- Before the subcontract:
// src/app.config.js
export default {
pages: ["pages/foo1/index"."pages/foo2/index"."pages/foo3/index"]};Copy the code
- After the subcontractor:
// src/app.config.js
export default {
pages: ["pages/foo1/index"."pages/foo2/index"].subpackages: [{root: "pages/foo3".pages: ["index"],},]};Copy the code
6.2 Taro. EventCenter Global message issues
6.2.1 EventCenter Global message listening for the first time does not take effect
Problem description
- Taron.eventcenter.trigger (‘getInfo’, data)
- Taron.eventcenter. on(‘getInfo’, e => {}) does not listen for the event
Solution:
- Manually delay trigger manually on the parent page (inelegant)
- Using vuex
6.2.2 Tabbar communication between Taro. EventCenter communication is not triggered for the first time
Cause: As above, the event has already been triggered, but subsequent pages have not been initialized and do not support historical message subscription
Solution:
- SetTimeout to delay the trigger manually on TAB foo1, and TAB foo2 will listen to it.
Taro.switchTab({
url: "/pages/foo1/index".complete: () = > {
// This can be done in foo2's onShow
setTimeout(() = > {
Taro.eventCenter.trigger(eventTypes.SENT_CUS_ID, 10086);
}, 800); }});Copy the code
- Not using native
tab
Build another one and get rid of this limitation - Use VUEX (pack to increase volume)
- Now that it’s vUE,
eventBus
Very good
import Vue from "vue";
import * as types from "./eventTypes";
// Special eventBus
// https://segmentfault.com/a/1190000012808179
const bus = new Vue({
data() {
return {
// Define data
cus_id: null}; },created() {
// Bind listener
this.$on(types.CHANGE_CUS_ID, (id) = > {
console.log("CHANGE_SHOP_ID==>");
this.cusId = id; }); }});export default bus;
export { types };
Copy the code
- Other means of communication in VUE…
6.3 Information about sitemap Indexes
Console warning
[Sitemap index information] According to sitemap rule [0], the current page [Pages/Overview /index] is indexedCopy the code
Solution:
Modify the checkSiteMap configuration field in setting of the applet project configuration file project.config.json to false
{
"setting": {
"checkSiteMap": false}}Copy the code
6.4 Production Packaging Removes console
- The installation
Note:
Use of the latest version of Terser will report errors
TypeError: Cannot read property 'javascript' of undefined
Copy the code
Downgrade the installation of version 4.x
Yarn add [email protected] - DCopy the code
config/prod.js
Modifying configuration files
module.exports = {
mini: {
// http://taro-docs.jd.com/taro/docs/config-detail#miniwebpackchain
webpackChain(chain, webpack) {
chain.plugin("terser").use(TerserPlugin, [
{
// https://www.npmjs.com/package/terser-webpack-plugin#terseroptionsco
terserOptions: {
mangle: true.compress: {
// https://swc.rs/docs/configuration/minification
drop_console: true.drop_debugger: true,},output: {
// https://drylint.com/Webpack/terser-webpack-plugin.html#%E5%AE%89%E8%A3%85
ascii_only: true.// Escape Unicode characters in strings and re}},},]); ,}}};Copy the code
6.5 Taro. OnSocketError Returns the error message “incomplete operation”, the true error is not retrieved
What does wx.onSocketError mean when it prompts incomplete operation?
Not solved
6.6 wechat Applet Experience Version Error Request Fail
Android error message, ios can see the specific error message
request:fail -2:net::ERR_FAILED
Copy the code
Solution:
- Check the server domain name configuration and strictly follow this specification
- Check certificate configuration, nginx with intermediate certificate
6.7 Update detection of new version of wechat mini program, automatic update
export default {
onReady() {
if(! Taro.canIUse("getUpdateManager")) {
Taro.showModal({
title: "Tip".content: "The current wechat version is too low to use this function, please upgrade to the latest wechat version and try again".showCancel: false});return;
}
// https://developers.weixin.qq.com/miniprogram/dev/api/base/update/UpdateManager.html
const updateManager = Taro.getUpdateManager();
updateManager.onCheckForUpdate((res) = > {
// Request a callback for the new version information
if (res.hasUpdate) {
updateManager.onUpdateReady(function () {
Taro.showModal({
title: "Update Prompt".content: "The new version is ready. Do you want to restart the application?".success: function (res) {
if (res.confirm) {
// The new version has been downloaded. Call applyUpdate to apply the new version and restartupdateManager.applyUpdate(); }}}); }); updateManager.onUpdateFailed(function () {
// Failed to download the new version
Taro.showModal({
title: "Update Prompt".content: "New version is online, please delete the current small program, search again open"}); }); }}); }};Copy the code
6.8 Taro cannot use CSS variables
Solution:
If it’s VUe3, there’s a ready-made solution, the vue3 single file component style feature
// Fix this by setting the style on the top-level element
import './style.css';
const style = { '--primary-color': 'red' }
return <View style={style} className='container'>container elemet</View>
/* styles.css */
.container {
color: var(--primary-color);
}
Copy the code
6.9 Use native HTML tags about Taro
In fact, it is recommended to use small program native tags, not HTML tags, afraid of falling into the pit.
- The installation
yarn add @tarojs/plugin-html
Copy the code
- Configure the plug-in
// config/index.js
config = {
// ...
plugins: ['@tarojs/plugin-html']
}
Copy the code
- use
<template> <div>Hello World! </div> </template>Copy the code
7. Reference materials
- Official Documents:
- Official documents of wechat applets
- Official documentation of Vant Syndrome