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.

  1. Why use Taro instead of Uni-app?

    A: Next time use uni-app.

  2. 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.

  3. 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)

  1. The installation
yarn global add @tarojs/cli
Copy the code
  1. Initialize the
taro init taro_demo
Copy the code
  1. Install dependencies
# change directory
cd taro_demo
# install dependencies
yarn install
Copy the code
  1. Changing the root Directorypackage.jsonIn thescriptsUnder thedev:weappDevelopment 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
  1. Start the development command, and when it succeeds, you can see the newly generated root directorydistdirectory
yarn run dev:weapp
Copy the code
2.1.2 wechat developer tools
  1. Download the wechat developer tool

  2. 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 modifypostcssConfiguration 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
  1. Root directory creationvantComponentConf.jsfile

    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 restartedviteThat 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
  1. Modify theconfig/index.jsfile
+ 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
  1. Modify thesrc/app.config.jsfile
+ 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-searchCould 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-fieldComponent, 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-canvasSome 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:

  1. 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
  1. Add in the Babel configuration filecompact: falseThe 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 nativetabBuild another one and get rid of this limitation
  • Use VUEX (pack to increase volume)
  • Now that it’s vUE,eventBusVery 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.jsModifying 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.

  1. The installation
yarn add @tarojs/plugin-html
Copy the code
  1. Configure the plug-in
// config/index.js
config = {
  // ...
  plugins: ['@tarojs/plugin-html']
}
Copy the code
  1. use
<template> <div>Hello World! </div> </template>Copy the code

7. Reference materials

  1. Official Documents:
  2. Official documents of wechat applets
  3. Official documentation of Vant Syndrome