干货 | 小程序跨端框架实践之Remax篇

remax:用真React运行时方案打造跨平台小程序应用 跨平台小程序开发常面临多端重复维护的困境,传统编译方案仅模拟JSX语法,难以复用React的Hooks、Context与组件生态。remax作为一种运行时方案,借助react-reconciler为React提供小程序宿主环境,让组件树通过虚拟DOM映射为原生节点,setState变更直接转换为setData指令,实现真正的React开发体验。它保留了React调度器与Hooks原生的行为,适合多端团队低成本迁移现有React组件,也便于在小程序端使用Redux等状态管理。本文从运行机制、工程搭建到构建发布 阅读详情

作者简介

 

汽车票前端研发团队,致力于提供更便捷更智慧的出行方式,关注前端技术方向的探索和实践。

一、项目背景

随着小程序在用户规模和商业化上取得的极大成功,各大平台都推出了自己的小程序。然而这些平台的小程序开发在语法上又不尽相同,不同平台小程序代码的维护需要投入很大的精力,在逻辑性上也很难达到统一的效果。虽然也有各种转换工具可以基于某一个平台转换出其他平台的代码,但转换的效果也是差强人意,往往还需要人工去修改。使用小程序跨端开发框架来实现一次开发、到处运行以提升效率,已经成为开发者强烈而迫切的需求。

目前,小程序跨端开发框架主要可以按照技术栈和实现原理两个维度进行分类。从技术栈来说,主流的跨端框架基本遵循 React、Vue 这两个前端开发最常使用的框架。由于所在团队主要使用的是React,所以本文主要介绍采用React语法的框架。从实现原理上,开源社区的跨端框架可分为编译时(compile time)和运行时(runtime)。

主流框架及其特点介绍如下表1-1所示:

  表1-1 React语法小程序跨端框架举例

框架
厂家
特征

Kbone

腾讯

不限技术栈,微信小程序和 Web 端同构的运行时解决方案,模拟了一套dom和bom接口,用以兼容现有的前端体系,只能用于Web兼容微信小程序,无法满足其他平台小程序的开发

Taro1/2

京东

类React,静态编译型框架仅在开发时遵循React语法,编译后运行时与React无关

Nanachi

去哪儿

React,静态编译型框架

Rax

阿里巴巴

以运行时方案为基础,支持局部场景使用编译时方案。运行时的支持基于Kbone,使用的是类React语法的Rax框架

Remax

蚂蚁金服

使用原生React来构建小程序,运行时框架,从Remax2.0开始支持Web应用的构建

Taro3

京东

不限技术栈,使用一套runtime层来兼容各种DSL,诞生于Remax之后

compile time编译时的跨端框架,主要的工作量在编译阶段。框架会把用户写的业务代码解析成 AST 树,然后通过语法分析将用户写的原始代码转换成符合小程序规则的代码。运行时模式的跨端框架通过适配层,实现自定义渲染器,是真正的在小程序的逻辑层中运行起React或Vue框架的方式,这种方式比静态编译有天然的优势。

编译时主要存在以下问题:灵活的JSX语法既可以写出非常复杂灵活的组件,同时也增加了编译阶段框架去分析和优化的难度。这就导致适配工作量巨大,维护成本较高,即使这样,也无法适配所有的写法。例如京东的Taro 1/2 用穷举的方式对 JSX 可能的写法进行了一一适配,但依然需要开发者遵循大量的语法约束,避免很多动态写法。否则代码就不能正常编译运行,开发效率难以保证。此外,由于 DOM 和 BOM API 的缺失,Web 上累积的各种前端生态,基本无法在编译时小程序中复用。京东的 Taro 1/2 , 去哪儿的 Nanachi都属于静态编译型的React或类React跨端框架。

与之相比,运行时方案的优势就在于能直接复用现有的前端生态。拿Remax来说,它最大的优势是可以几乎没有限制的使用React的语法完成代码编写,正如它的口号一样——使用真正React来构建跨平台小程序。此外,从Remax2.0开始,remax/one支持Web应用的构建。

我们团队做选型的时候Taro3还是待发布状态,所以没有做太多的考虑,下面着重去比较一下Rax和Remax。Rax和Remax都是出自阿里系但两个框架从设计思路上完全不同。

Remax从诞生之初就是为了支持小程序跨端框架Rax为了能尽量压缩React体积对React进行了重写,又引入了Driver机制来适配多端,这就意味着Rax有额外的学习成本,并且Rax不能随着React的迭代而更新。虽然Rax看似比较完善,提供了一套开箱即用的跨端API和完整的跨端UI控件支持,但它过多的依赖阿里的构建体系,似乎不太适合做为开源框架的选择。

综合以上几点考虑最终我们选择了Remax。

二、效果展示

图2-1到2-3分别为首页,列表页和详情页在Web和微信小程序上的运行效果,实现了一套代码多端运行,同时能做到同步更新。

0f2748fcd0be26fb9d8cc46c77a75fb4.png

2466a808defa2d6c84232ee79c02b1a5.png

图2-1 携程船票首页web和微信小程序运行结果

e87959bbd5d2300db456a6679c0d423e.png

0ceecc53eb965f82f4d0a3b94e6189ae.png

图2-2 携程船票列表页web和微信小程序运行结果

528694621ea8b4191ff68585ae08dc4a.png

f06e0b0e69570bf3e348306e8a1ce9b0.png

图2-3 携程船票详情页web和微信小程序运行结果

下面介绍一下Remax的基本用法。

三、基本用法


3.1 创建/安装依赖/运行

使用create-remax-app创建的小程序

npxcreate-remax-app my-app
? name my-app //填写你的appName
? author test<test@test.c>
? descriptionRemax Project  //填写项目描述
? platform 
❯ 跨平台小程序
  微信小程序
  阿里(支付宝)小程序
  头条小程序
  百度小程序

因为我们介绍的是跨端小程序,这里选择跨平台小程序。

运行项目

cd my-app&& npm install
npm run dev web//web端预览
npm run devwechat //微信小程序端

小程序端运行后会在项目目录里生成 dist/wechat、dist/ali各个小程序的产物,用小程序的IDE导入对应的目录即可预览。

项目的目录结构大致如下:

e2774adc30ed7b9555d259094242ca11.png

其中public目录在编译时会被复制到dist目录下,里面的原生页面pages目录也会和Remax的pages目录合并,这一部分后面会详细介绍。

3.2 Remax的跨平台机制

以下详细介绍Remax的跨平台机制

03bd65c0640e7664033f87d9f9ff068a.png

以上就是一个页面的基本文件目录结构,但是我们翻一遍Remax的文档就会发现它提供的跨平台的接口是少之又少,只有9个组件以及5个路由相关的API。所以Remax又提供了一种用文件名后缀来区分不同平台代码的方法:

c02a3cffda3c0943116e949c2245198b.png

如上面的目录所示,在页面的目录里增加相应后缀的文件在build相应平台的时候就会优先使用对应后缀的文件。

Remax还提供了环境变量区分平台的机制,在代码中直接通过process.env.REMAX_PLATFORM区分平台。例如:

if (process.env.REMAX_PLATFORM==='wechat') {}

以上代码在编译后只会保留对应平台的部分,所以无需担心兼容多平台带来额外的代码size增加。

除了上面说到的9个跨平台的组件和5个跨平台的API外,Remax还可以直接使用各个平台的组件及API,无需使用useComponents声明。

import React from'react';
import { View } from'remax/one';
import NativeCard from'./native-card';//native-card 是一个原生自定义组件
// 组件
exportdefault () => (
  <View>
    <NativeCard />
  </View>
);
// API
if (process.env.REMAX_PLATFORM==='ali') {
    systemInfo = my.getSysyemInfoSync();
} elseif (process.env.REMAX_PLATFORM==='wechat') {
    systemInfo = my.getSysyemInfoSync();
}

根据以上机制我们就可以自定义出任何我们需要的跨平台API及组件。

按照Remax的说法之所以不提供更多的跨平台组件和API是因为他们在设计之初没有标准去抹平各个平台的差异。这当然给使用框架的开发者带来了一些麻烦,许多的组件和API不能开箱即用,需要额外的去做一层封装。但这也是Remax这个框架的优势,只保留了核心的组件及API使得它本身不占太多的size,也使得要兼容一个新的平台变得非常容易。

四、实践干货

4.1混合原生

之前我们说到了public目录里的原生代码会拷贝到dist目录并且pages目录会合并,我们可以利用这一机制最大程度的复用现有小程序的代码,这也是我们团队选择Remax这个框架的原因之一。

让我们来体验一下,先创建一个原生小程序,以微信小程序为例:

小程序的文件目录大致如下

c47adde3a386fd4a4d745b2dfb2d93f1.png

‍

现在把整个小程序的代码放入public目录

892eedfe83c9b1571337352e890875b2.png

此时npm run dev wechat就会把pages以及utils拷贝到dist目录下并且pages目录合并了。

c18fc39f95ed4dfbc5cc5375d063528a.png

虽然合并了,但是我们观察一下发现原生小程序的app.json的内容不见了,难道要在Remax里面把app.json都写一遍么?带着疑问我们仔细翻看Remax的文档,发现remax.config.js里是可以配置动态生成app.json的配置的:

onAppConfig() {
    ...
      // 获取原始小程序配置originConfig和 remax app.config.js配置tmp
    // 做合并处理
    const appJSON =JSON.parse(JSON.stringify(originConfig));
    tmp.pages.forEach(function (item) {
        if (appJSON.pages.indexOf(item) ==-1) {
            appJSON.pages.push(item);
        }
    });
    tmp.subPackages.forEach(function (item) {
        let needAdd =true;
        for (let i =0, a = appJSON.subPackages; i < a.length; i++) {
            if (a[i].root=== item.root) {
                needAdd =false; a[i] = item;break;
            }
        }
        if (needAdd) {
            appJSON.subPackages.push(item);
        }
    });
    ...
    return appJSON;
}

经过以上处理,原小程序的app.json内容就和remax.config.js内容合并了,以上代码只处理了pages和subPackages,如果觉得还有什么需要合并的也可以在这里处理。此时,build生成的产物app.json,就保留了原小程序的内容并且合并了Remax小程序的内容。

产物里的app.js也没有原生小程序里的代码,那原有的逻辑怎么办呢。重新在Remax写一遍吗?大可不必。

我们可以自定义一个运行时插件:

function createBothFun(remaxConfig, originConfig, key) {
    const remaxFun = remaxConfig[key];
    const originFun = originConfig[key];
    return function () {
        // 这里的this就是微信的app 里的this
        remaxFun.apply(this,arguments);
        originFun.apply(this,arguments);
    };
}
const lifeCycles=['onLaunch','onShow','onHide','onPageNotFound','onError']
function tryMergeConfig(remaxConfig, originConfig) {
    for (const key in originConfig) {
        if (key ==='constructor') {
            console.log('xxx');
        } elseif (lifeCycles.indexOf(key) >=0) {
            remaxConfig[key] =createBothFun(remaxConfig, originConfig, key);
        } else {
            remaxConfig[key] = originConfig[key];
        }
    }
}
const mergeConfig = (remaxConfig, originConfig) => {
    tryMergeConfig(remaxConfig, originConfig);
    return remaxConfig;
};
export default {
    onAppConfig({ config }) {
        let __app = App;
        let originConfig;
        App =function (origin) {
            originConfig = origin;
        };
        __non_webpack_require__('./app-origin.js');
        App = __app;
        //merge config
        config =mergeConfig(config, originConfig);
        const onLaunch = config.onLaunch;
        config.onLaunch= (...args) => {
            if (onLaunch) {
                onLaunch.apply(config, args);
            }
        };
        return config;
    },
};

把原来的app.js重命名为app-origin.js,然后在onAppConfig函数中使用__non_webpack_require__('./app-origin.js'); 请注意,这里的相对路径是产物里的相对路径,经过以上一番操作后,我们的原小程序就可以真正和Remax混合运行了。

但是这样一来,我们的Remax似乎变得不能跨端了,因为它只能编译成你public目录里放置的原生小程序类型。

难道混合和跨端只能是鱼和熊掌不可兼得?后面我们将介绍使用工程化的方法来实现鱼和熊掌兼得。

4.2 Modal API化

你可能注意到了Remax的文档里面列举了10个控件,但我说它只有9个控件,官方的文档上也说只有9个控件,为什么呢?因为Modal严格的说来不能算是一个控件。

Modal实际上是调用createPortal这个API来创建一个节点覆盖在其它内容之上,在web端是使用的ReactDOM的createPortal,在小程序端是使用的@remax/runtime这个包里提供的同名方法。实际上portal在两端挂载的位置也不太一样,在Web端是直接的body上创建了一个新的div,而在小程序上则是挂在页面实例一个叫modalContainer的节点。在实际使用中,使用Modal组件去显示弹窗非常不方便,所以还是得把它变成API调用的方式。

以小程序端为例:

import...
import { createPortal } from'@remax/runtime';
import {ReactReconcilerInst } from'@remax/runtime/esm/render';


let createPortal__ = createPortal;
let ReactReconcilerInst__ = ReactReconcilerInst;
const styles = {
    modalContainer: {
        ...
    },
};
export default function withModal(TargetComponent) {
    const WrappedModalComponent = (props) => {
        const { mask,...other } = props;
        const component =useRef();
        const container =getCurrentPage().modalContainer;
        return createPortal__(
                  <View style={{ ...styles.modalContainer,pointerEvents: mask ?'auto':'none' }}>
                      <TargetComponent {...other} mask={mask} show={show} close={close} ref={component} />
                  </View>,
                  container
              )
    };
    WrappedModalComponent.hide= (conext) => {
        const container =getCurrentPage().modalContainer;
        if (container._rootContainer) {
            ReactReconcilerInst__.updateContainer(null, container._rootContainer,null,function () {
            });
        }
        container.applyUpdate();
    };
    WrappedModalComponent.show= (props) => {
        const container =getCurrentPage().modalContainer;
        if (!container._rootContainer) {
            container._rootContainer=ReactReconcilerInst__.createContainer(container,false,false);
        }
        const element = React.createElement(WrappedModalComponent, props);
        ReactReconcilerInst__.updateContainer(element, container._rootContainer,null,function () {
        });
        context.modalContainer.applyUpdate();
    };
    return WrappedModalComponent;
}
export { withModal };

使用示例:

//在需要弹窗的组件上使用withModal装饰器
@withModal
export default MyComponent(props) {
  ...
  return<View>{...}</View>
}
//在不支持装饰器的模式下也可以直接调用
function MyComponent(props) {
    ...
  return<View>{...}</View>
} 
const ModaledComponent =withModal(MyComponent)
//在需要使用弹窗的地方使用
ModaledComponent.show(props);//展示弹窗
ModaledComponent.hide();

4.3 工程化

考虑到我们的小程序是多部门多团队共同合作的项目,不可能让整个公司同时都使用Remax重写原来的业务,那样会有极大不可控风险。所以Remax只能是在部分业务试用,并且能渐进的切换原有的业务,这就要求我们必须有工程化的方案。

我们期望的小程序产物的结构如下:

2a8d2f80ca836879b8cebdd80ab2d5e0.png

而 Web 端的产物结构如下:

a9b4ec7c7be750d8bf1f0269c0d9cca2.png

这表示小程序端是依赖原有小程序的,Web端是可以单个业务单独发布的,于是我们在编译过程中给小程序和Web生成两套不同的壳工程。

编译小程序的过程中拉取壳工程,壳工程的目录结构大致如下:

16a1484e54a429afa42423ee21230a61.png

其中remaxA和remaxB的页面代码是在拉取壳工程的时候动态生成的,我们在壳工程里放入一个配置文件bundle.js,用来描述该壳工程有哪些Remax业务代码:

module.exports= {
  remaxA: {
    git:"git@remaxA.git"
  },
  remaxB: {
    gitL "git@remaxB.git"   
    }
}

在拉取壳工程的同时clonebundle.js所配置的仓库到临时目录packages,此时packages目录如下:

0fb719a50187356ca9e51d0053c0956a.png

然后根据Remax业务代码里的app.config.js,重新在壳工程生成新的页面和页面配置,其核心逻辑如下:

const template = (projectName, path) => {
    return`import ${projectName} from'~packages/${projectName}/src/pages${path ?`/${path}`:''}';
${projectName}.prototype.onShareAppMessage;
${projectName}.prototype.onPageScroll;
${projectName}.prototype.onShareTimeline;
exportdefault ${projectName};
`;
}


const pageHandler = (projectName) => {
    const projectPath =`${rootDir}/packages/${projectName}`;
    shell.cd(projectPath);
    let conf =require(`${projectPath}/src/app.config.js`);
    let platConf = conf[platform] || conf;
    const projectAllPages = [];
    ...
    // 遍历 pages 和subPackages配置并替换路径
    pagePath.replace('pages/',`pages/${projectName}/`);
    ...
    subPackage.root= subPackage.root.replace('pages/',`pages/${projectName}/`);
    ...
    // 将pages subPackages里所有的页面路径合并到一起
    let allPages = [...platConf.pages]
    allPages.push(path.join(subPackage.root, page));
    // 遍历页面配置生成新的页面
    allPages.forEach((mapPath) => {
        const pagePath = path.resolve(rootDir,'src','pages', projectName,`${mapPath}.js`);
        fse.ensureFileSync(pagePath);
        const data =template(projectName, mapPath);
        fs.writeFileSync(pagePath, data);
    });
};
const complier = () => {
    ...
    //获取子项目git地址,下载至packages目录下
    const packagesPath = path.resolve(rootDir,'packages');
    const subDirs = fs.readdirSync(packagesPath);
    // 遍历packages根据packages里的app.config.js重新生成合并路径后的页面
    subDirs.forEach((name) => {
        let file = fs.statSync(`${packagesPath}/${name}`);
        if (file.isDirectory()) {
            pageHandler(name);
        }
    });
    ...
};
module.exports= complier

生成的页面代码如下:

import remaxA from'~packages/remaxA/src/pages/index/index';
remaxA.prototype.onShareAppMessage;
remaxA.prototype.onPageScroll;
remaxA.prototype.onShareTimeline;
exportdefault remaxA;

这个可以修改上面代码中template按需求修改, 这段代码中之所以有类似remaxA.prototype.onShareAppMessage; 这样的无用代码是因为Remax在编译过程中会收集页面代码里的生命周期函数的关键字,非必需的生命周期在页面代码没有出现的时候,编译产物里也不会有。

生成的页面路径如下:

28844f453523134dca24242d79ba73a0.png

同样的,在Web端也会有相似的操作。我们Web是使用node容器发布的,所以壳工程就弄成了node工程了。如果使用静态发布那就不需要壳工程了,直接build发布产物就可以了。

此外,由于小程序的单包size限制的原因,在小程序webpack配置方面需要做一些额外的配置,避免多个Remax业务不共同依赖的代码也打到主包去,导致主包的单包size超出限制,这里给一个例子,仅供参考:

configWebpack:function (options) {
      let config = options.config;
      let subpackageGroups = {};
      Object.keys(projects).forEach((key) => {
          let packagePages = projectsPages[key];
          let allPages = packagePages.allPages.map((page) =>`pages/${key}/${page}`);
          let pages = packagePages.pages;
          subpackageGroups[`${key}Common`] = {
              name:`package-${key}-common`,
              test: (module) =>newRegExp(`[\\/]packages[\\/]${key}[\\/]src[\\/]`).test(module.userRequest),
              chunks:'all',
              minChunks:2,
              minSize:0,
              priority:91,
              filename:`pages/${key}/package-${key}-common.js`,
          };
      });
      config.optimization.merge({
          splitChunks: {
              maxAsyncRequests:100,
              maxInitialRequests:100,
              automaticNameDelimiter:'-',
              enforceSizeThreshold:50000,
              cacheGroups: {
                ...,
                ...subpackageGroups
              },
          },
      });
    },

五、经验总结

  • 经过实践,我们发现Remax确实是可以做到一处编写到处运行的,不足之处是Remax没有提供一整套开箱即用的跨端API和控件,使用这个框架可能会有较多的前期基础工作。但这也是它的优势,核心的依赖少了,而且是完全开放的,不会说用它就会带来一个全家桶的依赖。

  • 由于Remax实现原理的限制,在小程序上较复杂的页面性能上会有不足。当然这也是所有跨端框架存在的问题,好在可以通过使用自定原生组件的方式来解决。

  • Remax目前还不支持DOM、BOM接口,也不支持直接使用webhostcomponent 来编写跨端小程序,所以要实现跨端的话还是需要对现有的React应用做一定的改造。

  • Remax还不支持RN平台,说不支持并不是说不能支持,只是要兼容RN的话,可能还得在现有的React上做一些限制。比如RN对css的支持,以及要实现一整套的RN的控件来兼容web端及小程序端,这又使得Remax不那么纯粹了。

六、写在最后

本文旨在给大家提供一些新的思路,在选型方面应该从多方面去考量,各个方案可能没有明显的好坏之分,适合的才是最好的。就拿Taro来说,得益于有官方团队的支持,Taro3的发展速度非常之快,各个方面都做的比较完善。而Remax社区似乎没有那么活跃,所以发展速度相对来说比较慢。期待有更多的朋友来参与开源框架的贡献。

团队招聘信息

我们是携程火车票研发团队,负责火车票业务的开发以及创新。火车票研发在多种交通线路联程联运算法、多种交通工具一站式预定、高并发方向不断地深入探索和创新,持续优化用户体验,提高效率,致力于为全球人民买全球火车票。

在火车票研发团队,你可以和众多技术大牛一起,真实地让亿万用户享受你的产品和代码,提升全球旅行者出行体验和幸福指数。

如果你也热爱技术,并渴望不断成长,火车票研发团队期待与你一起高速前行。目前我们前端、后台、算法、大数据、测试等技术岗位均有职位。

简历投递:tech@trip.com 邮件标题:【姓名】-【携程火车票】-【投递职位】

【推荐阅读】

201b1d8586564e21f1ec2aac6d87bea2.png

 “携程技术”公众号

  分享,交流,成长

火神:基于remaxjs的小程序,寿命长且繁荣 火神 Vulcan: 瓦肯星、火神星、祝融星 《星际迷航》中 Mr.Spock 的出生星球 瓦肯人以信仰严谨的逻辑和推理闻名 在进行瓦肯举手礼的时候通常还伴随着一句话:Live long and prosper(生生不息,繁荣昌盛) 基于开发的跨平台小程序 目前只有微信( wechat )版本,后续再添加其他版本 文件 入门指南 安装依赖 注意:Remax要求Node.js版本大于等于12 npm install # or yarn 调试项目 # 选定要进行开发的平台,如 wechat,并调试 npm run dev wechat # or yarn dev wechat 使用小程序开发者工具打开项目下的dist/[target]目录。例如微信小程序,目录为dist/wechat 注意:微信和字节跳动小程序需要在IDE中打开“不校验合法域名” , 开发 测试数据 Mock测试数据使用 , 立即下载

相关推荐

【大模型微调】魔搭社区GPU进行LLaMA-Factory微调大模型自我认知

本教程介绍如何使用魔搭社区GPU资源和LLaMA-Factory工具进行大模型微调。主要内容包括环境配置、工具安装、模型训练和效果评估。通过LoRA算法进行自我认知微调,详细说明了从数据准备到模型导出的完整流程,并提供了参数调优和显存管理等实用技巧,帮助读者快速掌握大模型定制化训练方法。

LChuck的博客 2924

探索Remax:构建高效React小程序的利器

探索Remax:构建高效React小程序的利器 去发现同类优质开源项目:https://gitcode.com/ Remax 是一个开源框架,它让开发React小程序变得更加简单、高效。通过将React的开发体验无缝地带入微信、支付宝、百度等小程序平台,Remax极大地提升了开发者的工作效率。现在,让我们深入了解一下Remax的核心技术和应用场景。 技术分析 React哲学的延伸 Remax 基于...

gitblog_00089的博客 674

【图形学】Loop细分算法及半边结构实现(C++)

文章目录Loop 细分算法介绍增加新顶点更新旧顶点算法实现半边结构半边结构的表示方法半边结构的构造方法创建所有顶点创建所有面及半边半边结构的使用 Loop 细分 顾名思义,网格细分是将粗糙网格精细化的过程,如下动图。Loop细分是众多网格细分算法的一种,Loop细分仅仅对三角形网格模型有效。值得注意的是,虽然叫Loop细分,但是不能理解为“循环”细分,叫这个名字是因为作者的名字是这个而已。 下面是一个粗糙的兔子模型1000个面,进行3次细分 算法介绍 Loop细分算法主要分两步进行 增加新顶点:增加

wk_119的博客 8066

探秘 Remax: 前端开发的新选择

Remax 是一个基于 React 的跨平台小程序框架,它的目标是让开发者能够以编写 Web 应用的方式构建微信、支付宝等多平台的小程序。通过高度抽象和统一的 API,Remax 能显著提升开发效率,降低维护成本。让我们一起深入了解一下这个项目的精髓所在。 ## 技术分析 ### 1. 基于 React Remax 深度整合了 React 生态,这意味着你可以直接使用 React 的组件化思...

gitblog_00074的博客 625

单片机控制双向可控硅的5种实用触发电路设计(附完整电路图)

本文深入解析了单片机控制双向可控硅的5种实用触发电路设计,涵盖从基础隔离到复杂负载驱动的实战方案。重点探讨了光电耦合器选型、过零检测同步、RC吸收电路精密计算以及应对感性负载和高噪声环境的加固策略,并提供了完整的电路图与调试避坑指南,旨在帮助开发者实现安全可靠的交流负载控制。

joy55的博客 2207

【AI生成】 LoRa无中心自组网实现方案

LoRa技术是一种低功耗广域网通信技术,它采用了扩频频率调制技术,能够实现远距离的传输。LoRa在物联网中具有重要的应用价值,可以支持大规模的设备连接并且具有较低的成本。同时,LoRa具有高度的抗干扰能力和适应性,能够在复杂的环境中实现稳定的通信。通过使用无中心自组网实现方案,可以进一步提高LoRa网络的灵活性和可靠性,实现设备之间的智能互联。LoRa无中心自组网实现方案将为物联网应用提供更加便捷和高效的通信解决方案。LoRa无中心自组网实现方案一、无中心自组网概念及优势。

qq_31310977的博客 2089

Remax 框架深度解析:用 React 开发跨平台小程序

Remax 是一个创新的小程序开发框架,它允许开发者使用完整的 React 语法来构建跨平台小程序应用。与传统的编译型小程序框架不同,Remax 采用了运行时解决方案,这意味着开发者可以享受到 React 生态系统的全部能力,而不受传统小程序框架的限制。 ## 核心特性详解 ### 1. 真正的 React 开发体验 Remax 最大的优势在于它提供了完整的 React 支持: - 支持所有...

gitblog_00099的博客 665

CCS8.1 导入CCS3.3工程方法

    CCS3.3作为开发人员使用最广开发工具,研究人员手上存在不少该版本的建立的程序版本,然而随着TI公司推出高级版本的CCS平台,在新的平台上集成了更加丰富的功能和优点。利用新版本的平台在开发和编译旧版本工程上可以节省大量时间和精力。在使用新版本开发3.3版本工程时,首要解决的就是加载3.3的工程文件,现将加载过程记录如下: 第一步:Project-&gt;Import Legacy CC...

1万+

Remax 框架常见问题深度解析

Remax 是一个基于 React 的小程序开发框架,它允许开发者使用 React 语法开发小程序应用。本文将针对开发者在使用 Remax 过程中遇到的常见问题进行详细解答,帮助开发者更好地理解和使用这个框架。 ## 核心功能支持问题 ### React 生态支持 **Q:是否支持 React Hooks/Redux/Dva 等 React 特性?** A:完全支持。Remax 基于 Re...

gitblog_01087的博客 454

基于线性光耦HCNR200的高压直流采样电路设计与精度优化

本文详细介绍了基于线性光耦HCNR200的高压直流采样电路设计与精度优化方法。针对直流高电压测量中的安全与干扰问题,提出采用HCNR200光耦隔离方案,实现高精度线性传输。文章深入解析电路设计关键细节,包括电阻网络、运放选型、滤波电容配置等,并提供精度优化实战技巧与常见问题排查指南,助力新能源电动汽车和高压储能系统的高压直流采样应用。

weixin_42713608的博客 579

ResNet改进(50):SKConv和CBAM增强的ResNet模型

动态调整感受野大小- 结合通道和空间注意力模型的核心思想是在ResNet的每个残差块后插入这些注意力模块,使网络能够自适应地关注更重要的特征。模型的核心是类,它在标准ResNet34的基础上:替换了初始卷积层,使用更小的核(3×3)和步长(1)在每个残差块后选择性添加SKConv和CBAM模块# 加载预训练ResNet34# 自定义初始层# 添加注意力机制的残差层通过集成SKConv和CBAM,这个改进的ResNet模型能够更有效地捕捉多尺度特征并关注关键信息区域。

2401_82355416的博客 621

干货 | 携程门票H5转小程序实践

作者简介本文作者为携程门票前端小程序组,关注小程序相关的开发和优化。一、背景自微信小程序出来后,互联网进入一个新的纪元。由于手机的容量有限,每个人不可能装太多APP ,总有一些APP大...

携程技术 701

【Android面试八股文】Android Application为什么是单例?

这道题相对简单,就是考察大家是否了解application的创建流程。的实例,它用来存储和处理整个全局变量的一些事情,它同时还是一个。为空的时候,才会创建,从而保证了它是一个单例对象。一样有自己的生命周期,但是它并没有那么复杂,因为。对象的创建过程,找出它为什么是单例的原因。全局进行一些配置,比如配置插件。的时候才会创建,所以说可以在。凭什么是单例,我们查看下。启动的时候都会创建一个。是怎么一步步创建的。是一个单例,即每一个。

字节卷动 531

2021-11月报

0、产品设计 聚好看、酷开科技、雷鸟科技、虹魔方三季度盘点:终端厂商互联网业务表现不俗 OTT盒子前三季度线上销量达207万台,销额为5亿元 中国移动家庭智能终端行业报告重磅发布 1、基础知识(编程语言、计算机理论基础) 图解|什么是TCP拥塞控制及谷歌的BBR算法 大约在1988年之前TCP/IP是没有拥塞控制的,但是随着网络接入规模的发展之前仅有的端到端窗口控制已经无法满足要求,在1986年引发大规模网络瘫痪,此时就要提到一个重量级人物:Van Jacobson范

天空24的专栏 2762

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

react构建小程序框架及remax的工作原理

1、为什么要用 React 来构建小程序? react生态体系完善。 自Facebook在2013年5月开源React,经历了7年多的发展,react的社区生态体系非常庞大,若是使用react来构建小程序,那么在小程序开发中可以充分利用 React 生态体系中大量的技术沉淀(比如:react-use、field-form)。 更完整的 TypeScript 支持。 (1)当然也可以用 TypeScript 去写现有的小程序,但是由于小程序的架构原因(在小程序中,模版层和逻辑层是分开的,分别运行

祥哥的说 3204

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

Remax 快速入门指南:从零开始构建小程序应用

Remax 是一个基于 React 的小程序开发框架,它允许开发者使用熟悉的 React 语法来开发各类小程序应用。通过 Remax,你可以: - 使用完整的 React 开发生态 - 开发跨平台小程序(支持阿里系、微信、头条等) - 享受 React 的组件化开发体验 - 复用现有的 React 知识和技能 ## 环境准备 在开始之前,请确保你的开发环境满足以下要求: 1. **Node...

gitblog_00907的博客 607

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

小程序领域必备:高效开发框架推荐

本文旨在帮助小程序开发者解决「多端开发效率低」「代码复用难」「技术栈不统一」等核心问题,系统梳理当前主流高效开发框架的技术特点、适用场景和实战方法,覆盖从框架选择到落地开发的全流程。本文将从「为什么需要高效框架」→「核心概念解释」→「主流框架推荐」→「实战案例」→「未来趋势」逐步展开,用「故事+代码+场景」的方式,让你彻底掌握小程序高效开发的底层逻辑。多端适配:同一套代码运行在微信、支付宝、抖音等不同平台小程序跨端框架:通过语法转换或运行时封装,实现多端代码复用的工具组件化开发。

小程序开发 1785

【2万字长文】深入浅出主流的几款小程序跨端框架原理

开发者(KaiFaX)面向全栈工程师的开发者专注于前端、Java/Python/Go/PHP的技术社区作者 |雾豹来源 |https://juejin.im/post/68815978...

AI研习社 1214

React开发小程序的四大框架深度解析

根据最新统计,微信小程序日活跃用户已突破4亿,支付宝、百度、字节跳动等平台的小程序生态也在快速增长。是阿里巴巴推出的跨端解决方案,虽然不完全等同于React,但对React开发者非常友好。的口号是"使用真正的React构建小程序",它采用了与其他框架不同的技术路线。是目前最成熟的React小程序开发框架之一,由京东团队开发并维护。:对React开发者友好,API设计贴近React标准。主要以Vue为核心,但其对React的支持也值得关注。:直接使用React运行时,保留完整的React特性。

wujiayu31415的博客 2899

初探Remax微信小程序

1.创建项目 npx degit remaxjs/template-wechat my-app cd my-app && npm install 2.运行项目 npm run dev 3.在微信开发者工具中,打开项目的dist目录,我们可以看到项目运行效果 水文,本文借鉴自官网 转载于:https://www.cnblogs.com/smart-girl/p/1...

weixin_30869099的博客 1159

Remax 中使用小程序插件完全指南

小程序插件是一种可被添加到小程序内直接使用的功能组件,它由第三方开发者开发并发布,供其他小程序开发者使用。插件开发者可以像开发小程序一样开发插件,但插件无法单独运行,必须嵌入小程序中才能被用户使用。 ## 为什么要在 Remax 中使用插件 在 Remax 项目中使用小程序插件可以带来以下优势: 1. **功能扩展**:快速集成第三方提供的成熟功能 2. **开发效率**:避免重复开发已有解...

gitblog_00981的博客 389

推荐阿里巴巴 15 个前端开源项目

阿里巴巴 15 个前端开源项目: Ant Design Element UI Egg.js Icejs UmiJS G2 ahooks Formily Rax LowCodeEngine Midway BizCharts Hilo XRender Fusion Design

wuliyouMaozhi的博客 2061

ANE代码全解:mil_dynamic.h运行时MIL生成器深度剖析(564行生成10个训练内核)

在 **ANE(Apple Neural Engine)** 上训练神经网络的核心难题是:Apple 官方只开放推理,而 ANE 编译器对每个进程有约 119 次编译上限。本项目通过逆向私有 API 实现纯 ANE 训练,而 [mil_dynamic.h](https://link.gitcode.com/i/c5ba64d79d6aaf9c11db48c0ed4b4d56) 正是这套方案的灵魂—

gitblog_00305的博客 479

使用Remax开发小程序中需注意的地方和学习的知识

前言: 以前开发小程序(微信小程序为主)都是使用微信小程序开发的那一套,从React跳转到此多多少少有些不适应,因此Remax(https://remaxjs.org/)由此而生,它是使用真正的 React 构建跨平台小程序 写在前面: 在开发时,尽量使每个页面的事件名、样式名、变量名统一。 比如有搜索功能的页面,声明搜索函数名时,可统一命名为:handleSearch; 搜索框的变量名统一为:searchValue; 返回的数组数据统一为dataList; 获取数据名的api名虽然不一样,但它的

Charles_Tian的博客 4037

【小程序】Remax 快速上手入门教程

这篇教程是Remax框架的快速入门指南,主要包含以下内容: Remax简介:介绍Remax的概念、优势和工作原理 环境准备:Node.js安装和Remax CLI配置 项目结构:详细说明目录结构和各文件作用 开发流程:页面编写、配置和组件开发 调试发布:调试和构建命令 核心API:常用API和组件的列表说明 生命周期:页面和应用的生命周期详解 踩坑指南:5个常见开发问题的吐槽和解决方案 教程采用活泼的语气,配合emoji和表格等可视化元素,适合前端开发者快速上手Remax框架开发小程序。

silverclayz的技术分享 1055

终极指南:Remax多端适配策略,轻松搞定小程序平台差异

Remax是一个使用真正的React构建跨平台小程序的框架,让开发者能够用熟悉的React语法编写一次代码,就能运行在多个小程序平台。本文将详细介绍Remax的多端适配策略,帮助开发者优雅处理不同平台间的差异,提升开发效率。 ## 了解Remax的多端架构 Remax通过一系列精心设计的模块来实现多端适配,其中核心的包包括`remax-ali`、`remax-wechat`和`remax-to

gitblog_00096的博客 505
上一篇: 干货 | 携程商旅订单系统架构设计和优化实践
下一篇: 干货 | 聊聊移动端安全加固
携程技术
博客等级 码龄10年 3716粉丝 324原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值