目录

小程序全局组件使用自动插入节点

小程序全局组件使用(自动插入节点)

前言

小程序中没有全局环境,像vue的全局组件小程序实现起来非常困难,vue中可以直接在app.vue中注册,但是小程序需要每个page中都插入节点才可以使用

解决方案

在小程序中实现全局组件,首先,需要在app.json中注册,然后需要在所有的page中插入节点,可以通过node脚本实现

新建文件generator/index.js

代码如下

/**
 * @description: 将组件插入到小程序项目,包括app.json和page
 * @param {string} cpName 组件名
 * @param {string} cpPath 组件路径
 * @param {string} cpString 要插入的组件字符串内容
 * @param {Array<string>} whiteList 不需要插入的组件
 * @return {*}
 */
function insertComponent(
  cpName = 'new-user-dialog',
  cpPath = '/components/newUserDialog/newUserDialog',
  cpString = `<new-user-dialog class="new-user-dialog"></new-user-dialog>`,
  whiteList = [
    'pages/home/index',
  ]
) {
  try {
    const path = require('path');
    const fs = require('fs');
    const entryFilePath = './app.json';

    if (fs.statSync(entryFilePath)) {
      const { EOL } = require('os');

      // app.json 内容
      const contentMain = fs.readFileSync(path.resolve(entryFilePath), {
        encoding: 'utf-8',
      });
      // 获取每行内容
      const contentMainLine = contentMain.split(/\r?\n/g);
      // 组件('new-user-dialog':)正则
      const compReg = eval(`/['"]?${cpName}['"]?:/`);
      // 组件正则
      const usingComponentReg = /['"]?usingComponents['"]?:/;
      // 检测组件配置项所在行
      const ucLineNum = contentMainLine.findIndex(line =>
        line.match(usingComponentReg)
      );

      // TODO: 插入组件部分
      // 检测tabbar
      const tabBarStartReg = /['"]?tabBar['"]?:/;
      // app.json没有配置自定义组件,自定义添加
      if (!compReg.test(contentMain)) {
        // 如果没有usingComponent配置项的话,就找tabbar,放在后面
        if (ucLineNum < 0) {
          const tabBarLineNum = contentMainLine.findIndex(line =>
            line.match(tabBarStartReg)
          );
          contentMainLine[
            tabBarLineNum - 1
          ] += `${EOL}  "usingComponents": { "${cpName}": "${cpPath}" },`;
        } else {
          // 有配置项,放到配置项里面
          contentMainLine[ucLineNum] += `${EOL}    "${cpName}": "${cpPath}",`;
        }
        fs.writeFileSync(
          path.resolve(entryFilePath),
          contentMainLine.join(EOL),
          { encoding: 'utf-8' }
        );
      }

      // TODO: 插入page部分
      // pages开始,逗号结尾的部分
      const pageConfigReg = /['"]?pages['"]?: \[([^\]]+)\],/;
      // 将pages按照逗号分隔为数组
      const pageList = pageConfigReg
        .exec(contentMain)[1]
        .replace(/\s+/g, '')
        .replace(/"/g, '')
        .replace(/\n\s+/g, '')
        .split(',')
        .filter(pn => {
          return !whiteList.includes(pn);
        });
      pageList.forEach(pagePath => {
        insertFileToPage(pagePath, cpString);
      });
    }

} catch (error) {
console.warn(error);
}
}

/**

- @description: 将组件插入到 page
- @param {string} pagePath 组件 page 路径
- @param {string} cpString 要插入的组件字符串内容
- @return {_}
  _/
  function insertFileToPage(pagePath, cpString) {
  const path = require('path');
  const fs = require('fs');
  if (pagePath.indexOf('wxml' < 0)) {
  pagePath += '.wxml';
  }
  const pageContent = fs.readFileSync(path.resolve(pagePath), {
  encoding: 'utf-8',
  });
  // 组件('new-user-dialog':)正则
  const compReg = new RegExp(cpString);

// 没有引用标签则添加标签引用
if (!compReg.test(pageContent)) {
const { EOL } = require('os');
const pageLine = pageContent.split(/\r?\n/g);
// 添加到最后一行
pageLine[pageLine.length - 1] += `${EOL}${cpString}`;
fs.writeFileSync(path.resolve(pagePath), pageLine.join(EOL), {
encoding: 'utf-8',
});
}
}

/**

- @description: 将组件插入到小程序项目,包括 app.json 和 page
- @param {string} cpName 组件名
- @param {string} cpPath 组件路径
- @param {string} cpString 要插入的组件字符串内容
- @param {Array<string>} whiteList 不需要插入的组件
- @return {_}
  _/
  function deleteComponent(
  cpName = 'new-user-dialog',
  cpPath = '/components/newUserDialog/newUserDialog',
  cpString = `<new-user-dialog class="new-user-dialog"></new-user-dialog>`,
  whiteList = [
  'pages/mine/login/logout/logut',
  'pages/mine/login/method/method',
  'pages/mine/login/scan/scan',
  'pages/mine/login/people/people',
  'pages/mine/collect/collect',
  ]
  ) {
  try {
  const path = require('path');
  const fs = require('fs');
  const entryFilePath = './app.json';

      if (fs.statSync(entryFilePath)) {
        // app.json 内容
        const contentMain = fs.readFileSync(path.resolve(entryFilePath), {
          encoding: 'utf-8',
        });
        // pages开始,逗号结尾的部分
        const pageConfigReg = /['"]?pages['"]?: \[([^\]]+)\],/;
        // 将pages按照逗号分隔为数组
        const pageList = pageConfigReg
          .exec(contentMain)[1]
          .replace(/\s+/g, '')
          .replace(/"/g, '')
          .replace(/\n\s+/g, '')
          .split(',')
          .filter(pn => {
            return !whiteList.includes(pn);
          });
        pageList.forEach(pagePath => {
          deleteFileToPage(pagePath, cpString);
        });
      }

  } catch (error) {
  console.warn(error);
  }
  }

/**

- @description: 将组件从 page 中删除
- @param {string} pagePath 组件 page 路径
- @param {string} cpString 要删除的组件字符串内容
- @return {_}
  _/
  function deleteFileToPage(pagePath, cpString) {
  const path = require('path');
  const fs = require('fs');
  if (pagePath.indexOf('wxml' < 0)) {
  pagePath += '.wxml';
  }
  let pageContent = fs.readFileSync(path.resolve(pagePath), {
  encoding: 'utf-8',
  });
  // 组件('new-user-dialog':)正则
  const compReg = new RegExp(cpString, 'g');

// 有引用标签则删除标签引用
if (compReg.test(pageContent)) {
pageContent = pageContent.replace(compReg, '');
fs.writeFileSync(path.resolve(pagePath), pageContent, {
encoding: 'utf-8',
});
}
}

// deleteComponent()
insertComponent();

使用

node .\generator\index.js

参考