用react写小程序_react 写 小程序 - CSDN
  • 从去年微信小程序的诞生,到今年的逐渐火热,以及异军突起的轻应用、百度小程序等的出现,前端可以延伸的领域已经越来越广,当然也意味着业务在不断扩大。这时候,如何通过技术手段来提升开发效率,应对不断增长的...

    在互联网不断发展的今天,前端程序员们也不断面临着新的挑战,在这个变化多端、不断革新自己的领域,每一年都有新的美好事物在发生。从去年微信小程序的诞生,到今年的逐渐火热,以及异军突起的轻应用、百度小程序等的出现,前端可以延伸的领域已经越来越广,当然也意味着业务在不断扩大。这时候,如何通过技术手段来提升开发效率,应对不断增长的业务,就是一个值得探索的话题。本文将对 Taro 诞生的故事,进行深入浅出地介绍,记录下这个忙碌的春夏之交发生的故事。

    让人又爱又恨的微信小程序

    2017-1-9 微信小程序(以下简称小程序)诞生以来,就伴随着赞誉与争议不断。从发布上线时的不被大多数人看好,到如今的逐渐火热,甚至说是如日中天也不为过,小程序用时间与实践证明了自己的价值。同时于开发者来说,小程序的生态不断在完善,许多的坑已被踩平,虽然还是存在一些令人诟病的问题,但已经足见微信的诚意了。这个时候要是还没有上手把玩过小程序,就显得非常OUT了。

    小程序对于前端程序员来说应该算得上是福音了,用前端相关的技术,获得丝般顺滑的 Native 体验,前端们又可以在产品小姐姐面前硬气一把了。可以说小程序给前端程序员打开了一扇新的大门,大家都应该感谢微信,但是从开发的角度来说,小程序的开发体验就非常值得商榷了,不仅语法上显得有些不伦不类,而且有些莫名其妙的坑也经常让人不经意间感叹一下和谐社会,从市面上层出不穷的小程序开发框架就可见一斑。以下就盘点部分小程序开发的痛点。

    代码组织与语法

    在小程序中,一个页面 page 可能拥有 page.jspage.wxsspage.wxmlpage.json 四个文件

    5ff8e9fe34d77eb6092c0099daa76edd2841869b

    这样在开发的时候就需要来回进行文件切换,尤其是在同时开发模板和逻辑的时候,切来切去会显得尤其麻烦,影响开发效率,但小程序原生只支持这么写,就显得比较尴尬了。

    而在语法上,小程序的语法可以说既像 React ,又像 Vue,不能说显得有点不伦不类吧,但在使用上总是感觉有些别扭,对于开发者来说,等于又要学习一套新的语法,提升了学习成本。而且,小程序的模板由于没有编辑器插件的支持,书写的时候也没有智能提示与 lint 检查,书写起来显得有些麻烦。

    命名规范

    在小程序中到处可见规范不统一的情况

    例如组件的属性,以最简单的 <button /> 组件为例,在小程序官方文档中,该组件的属性部分截图如下,大家可以感受下

    49f91f876d5419a5b0b0a2df9718b19b1d1b7cd6
    <button /> 组件属性名既有以中划线分割多个单词的情况 session-form,也有多个单词连写的情况 bindgetphonenumber。当然这也不是最严重的,你可以说事件绑定的规范就是 bind + 事件名 ,而其他属性的规范就是中划线分割单词,我一度以为小程序就是这个作为标准,直到我看到了 <progress /> 组件
    f123ad89825171170c089ab7ccfffd6c406f1207
    这和说好的不一样啊喂!
    b797db39e37d0e3a50a72c3ddfe3c786844261a0

    同样的情况也出现在 页面组件 的生命周期方法中,页面 的生命周期方法有 onLoadonReadyonUnload 等,但到了 组件 中则是 createdattachedready 等,这样规范又不统一了,为啥 页面 的生命周期方法是 on+Xxx 的格式,但到了 组件 里缺不一样了呢,有点费解。

    开发方式

    小程序官方提供了 微信开发工具 作为开发编译工具,而对于代码本身没有提供一个类似 webpack 的工程化开发工具,来解决开发中的一些问题,所以小程序原生的开发方式显得不那么现代化,这也是很多小程序开发框架致力于解决的问题。例如,在小程序开发中

    • 不能使用 npm 管理依赖,在小程序中需要手动把第三方代码文件下载到本地,然后再 reuqire 进行使用,显得不那么优雅
    • 不能使用 Sass 等 CSS 预处理器,由于没有预编译的概念,小程序开发中无法使用市面上流行的 CSS 预处理器,这样会使得样式代码难以管理
    • 不完整的 ES Next 语法支持,小程序默认只能支持极少一部分 ES6 规范的语法,而 ES 是不断往前发展的,一些非常优秀的新语法特性就不能使用了
    • 手动的文件处理,像图片压缩、代码压缩等等的一些文件操作,必须手工来处理,显得有些繁琐

    以上就是从开发者的角度看到的一些小程序的开发问题,不过纵然有千般困难,我们总要面对,作为新时代的前端开发工程师,我们不能一味忍受问题,要保持技术的头脑,以技术作为武器,用技术手段去提升的我们开发体验。

    突发奇想:我能不能用React来写小程序

    目前前端界言及前端框架,必离不开依然保持着统治地位的 ReactVue,这两个都是非常优秀的前端 UI 框架,而且在网上也经常能看到两个框架的粉丝之间热情交流,碰撞出一些思想火花,显得社区异常活跃。

    而我们团队也在去年勇敢地抛弃了历史包袱,非常荣幸地引入了 React 开发方式,让我们团队丢掉了煤油灯,开始通上了电。而且也研发出了一款优秀的类 React 框架 Nerv ,让我们和 React 开发思想结合得更深。

    与小程序的开发方式相比,React 明显显得更加现代化、规范化,而且 React 天生组件化更适合我们的业务开发,JSX 也比字符串模板有更强的表现力。那么这时候我们就在思考,我们能不能用 React 来写小程序?

    理性地探索

    类比

    通过对比体验 小程序和 React ,我们还是能发现两者之间相似的地方

    生命周期

    小程序的生命周期和 React 的生命周期,在很大程度上是类似的,我们甚至能找到他们之间的对应关系

    app 及页面的生命周期

    583d099937858adeaed778edb4d65d47a88b935c

    可以看出,对于 app页面 来说,除了 onShowonHide 两个方法,其他方法都能在 React 中找到对应。

    数据更新方式

    React 中,组件的内部数据是用 state 来进行管理的,而在小程序中组件的内部数据都是用 data 来进行管理,两者具有一定相似性。而同时在 React 中,我们更新数据使用的是 setState 方法,传入新的数据或者生成新数据的函数,从而更新相应视图。在小程序中,则对应的有 setData 方法,传入新的数据,从而更新视图。

    两者都是以数据驱动视图的方式进行更新,而且 api 神似。

    事件绑定

    小程序中绑定事件使用的是 bind + 事件名 的方式,例如点击事件,小程序中是 bindtap



    <view bindtap="handlClick">1</view>
    

    而在 React 里,则是 on + 事件名 的方式,例如点击事件, React web 中是 onClick


    <View onClick={this.handlClick}>1</View>
    

    虽然看上去不一样,但其实是可以类比的,我们只需要在编译时将 on + 事件名 的形式编译成 bind + 事件名 的形式就可以了。

    如此看来,两者之间有些相似,用 React 来写小程序貌似是可行的,但接下来我们就发现了巨大的差异。

    巨大的差异

    React 与小程序之间最大的差异就是他们的模板了,在 React 中,是使用 JSX 来作为组件的模板的,而小程序则与 Vue 一样,是使用字符串模板的。这样两者之间就有着巨大的差异了。

    JSX


    render () {
      return (
        <View className='index'>
          {this.state.list.map((item, idx) => (
            <View key={idx}>{item}</View>
          ))}
          <Button onClick={this.goto}>走你</Button>
        </View>
      )
    }
    

    小程序模板

     <view class="index">
       <view wx:key={idx} wx:for="{{list}}" wx:for-item="item" wx:for-index="idx">{{item}}</view>
       <view bindtap="goto">走你</view>
     </view>
    

    众所周知,JSX 其实本质上就是 JS,我们可以在里面写任意的逻辑代码,这样一来就比字符串模板的表现力与操作性要强多了,况且,小程序的字符串模板功能比较羸弱,只有一些比较基本的功能。那这样的话,要如何来实现用 JSX 来写小程序模板呢。

    编译原理的力量

    我们可以仔细来分析我们的需求,我们期望使用 JSX 来书写小程序模板,但小程序显然是不支持执行 JSX 代码的(要是支持的话,Taro 应该也就不存在了吧),我们也不能期望微信能给我们开个后门来跑 JSX。那么这个时候我们就想,我们要是能够将 JSX 编译成小程序模板就好了。

    事实上在我们平时的开发中,这种编译的操作到处可见,babel 就是我们最常用的 JS 代码编译器,一般浏览器是不能支持一些非常新的语法特性的,但我们又想使用它们,这个时候就可以借助 babel 来将我们的高版本的 ES 代码,编译成浏览器可以运行的 ES 代码。而我们像要将 JSX编译成小程序模板,也是同样的道理。我们首先来了解一下 Babel 的运行机制。

    Babel 作为一个 代码编译器 ,能够将 ES6/7/8 的代码编译成 ES5 的代码,其核心利用的就是计算中非常基础的编译原理知识,将输入语言代码,通过编译器执行,输出目标语言的代码。编译原理的一般过程就是,输入源程序,经过词法分析、语法分析,构造出语法树,再经过语义分析,理解程序正确与否,再对语法树做出需要的操作与优化,最终生成目标代码。

    15daf43a8aa0e0e5aff9ebfaa45188df3a71747e

    Babel 的编译过程亦是如此,主要包含三个阶段

    • 解析过程,在这个过程中进行词法、语法分析,以及语义分析,生成符合 ESTree 标准 虚拟语法树(AST)
    • 转换过程,针对 AST 做出已定义好的操作,babel 的配置文件 .babelrc 中定义的 presetplugin 就是在这一步中执行并改变 AST 的
    • 生成过程,将前一步转换好的 AST 生成目标代码的字符串

    为了更好地理解这些过程,大家可以利用 Ast Explorer 这个网站接一下自己的代码,感受一下每一部分代码所对应的 AST 结构。

    9f51fef1f648ff4e455f787957c6d4bb08d1cdd4
    可以看到,一份源码经过编译器解析后,会变成类似如下的结构

    {
      type: "Program",
      start: 0,
      end: 78,
      loc: { start, end }
      sourceType: "module",
      body: [
        { type: "VariableDeclaration", ... },
        { type: "VariableDeclaration", ... },
        { type: "FunctionDeclaration", ... },
        { type: "ExpressionStatement", ... }
      ]
      ...
    }
    

    其中,body 里包含的就是我们示例代码的语法树结构,第一个 VariableDeclaration 对应的是 const a = 1,第三个 FunctionDeclaration 对应的则是 function sum (a, b) { },分别就是 JS 中的变量定义与函数定义,每一个树节点里都会包含许多子节点,这样就形成了一个树形结构,更多的节点类型,请参考 babel types

    当然我们在这儿只是简单介绍下编译原理与 babel,编译原理是一门非常深奥的课程, babel 也是一个非常优秀的工具,希望在后续的文章中能和大家再详细探讨这一部分内容。

    再次回到我们的需求,将 JSX 编译成小程序模板,非常幸运的是 babel 的核心编译器 babylon 是支持对 JSX 语法的解析的,我们可以直接利用它来帮我们构造 AST,而我们需要专注的核心就是如何对 AST 进行转换操作,得出我们需要的新 AST,再将新 AST 进行递归遍历,生成小程序的模板。

    JSX 代码


    <View className='index'>
      <Button className='add_btn' onClick={this.props.add}>+</Button>
      <Button className='dec_btn' onClick={this.props.dec}>-</Button>
      <Button className='dec_btn' onClick={this.props.asyncAdd}>async</Button>
      <View>{this.props.counter.num}</View>
      <A />
      <Button onClick={this.goto}>走你</Button>
      <Image src={sd} />
    </View>
    

    编译生成小程序模板

    <import src="../../components/A/A.wxml" />
    <block>
      <view class="index">
        <button class="add_btn" bindtap="add">+</button>
        <button class="dec_btn" bindtap="dec">-</button>
        <button class="dec_btn" bindtap="asyncAdd">async</button>
        <view>{{counter.num}}</view>
        <template is="A" data="{{...$$A}}"></template>
        <button bindtap="goto">走你</button>
        <image src="{{sd}}" />
      </view>
    </block>
    

    这时候,聪明的你应该就能发现问题的难点所在了,要知道小程序的模板只是字符串,而 JSX 则是真正的 JS 代码扩展,其语法之丰富,显然不是字符串模板所能比,在这一步中,我们要做的操作,包括但不仅限于如下

    • 理解三目运算符与逻辑表达式,例如三目运算符 abc ? : <View>1</View> : <View>2</View> 需要编译成 <view wx:if="{{abc}}">1</view><view wx:else>2</view>
    • 理解数组 map 语法,例如 map 的使用 abc.map(item => <View>item</View>) 需要编译成 <view wx:for="{{abc}}" wx:for-item="item">item</view>
    • 等等

    以上仅仅是我们转换规则的冰山一角,JSX 的写法极其灵活多变,我们只能通过穷举的方式,将常用的、React 官方推荐的写法作为转换规则加以支持,而一些比较生僻的,或者是不那么推荐的写的写法则不做支持,转而以 eslint 插件的方式,提示用户进行修改。目前我们支持的 JSX 转换规则,大致能覆盖到 JSX 80% 的写法操作。

    关于 JSX 转小程序模板这一部分,我们将在后续的技术原理分析系列文章中,详细为大家介绍。

    还能不能干点别的

    经过我们一次次的探索,以及一波波猛如虎的操作,我们已经可以将类 React 代码转成小程序可以跑的代码了,也就是说我们已经可以正式以 React 的方式来写小程序的代码了。喜大普奔!但是我们激动之余,冷静下来继续思考,我们还能不能干点别的有意思的事情呢。

    分析一下需求

    我们发现,在平常的工作中,我们业务通常有一些多端的需求,就是要求小程序要有,H5 要有,甚至 RN 也能有就最好了,我猜产品经理还看不上快应用,不然肯定要求我们快应用也上一套吧,反正你们不是经常号称代码优秀、高度可复用么。这个时候,你就会发现,差不多的界面和逻辑,你可能需要重复写上好几轮,这时候要是有个多端代码生成工具就好了,只写一份代码,可以多端运行。Write once, run anywhere,相信是所有工程师的梦想。

    依然编译原理的力量

    这时候我们回忆一下前文的内容,将一份代码编译成多端代码,这不正是编译原理干的事么,我们可以输入一份源代码,针对不同的端设定好对应的转换规则,再一键转换出对应端的代码。而且由于我们已经遵循 React 语法了,那我们再转成 H5 端(使用 Nerv)与 RN 端(使用 React)也就有了天然的优势。


    8a5caa29295a26b9dc55fb77c901ee0250c622e0

    设计思路补完

    但是仔细思考我们又会发现,仅仅将代码按照对应语法规则转换过去后,还远远不够,因为不同端会有自己的原生组件,端能力 API 等等,代码直接转换过去后,可能不能直接执行。例如,小程序中普通的容器组件用的是 <view />,而在 H5 中则是 <div />;小程序中提供了丰富的端能力 API,例如网络请求、文件下载、数据缓存等,而在 H5 中对应功能的 API 则不一致。

    所以,为了弥补不同端的差异,我们需要订制好一个统一的组件库标准,以及统一的 API 标准,在不同的端依靠它们的语法与能力去实现这个组件库与 API,同时还要为不同的端编写相应的运行时框架,负责初始化等等操作。通过以上这些操作,我们就能实现一份一键生成多端的需求了。在 Taro 最初的设计中,我们组件库与 API 的标准就是源自小程序的,因为我们觉得既然已经有定义好的组件库与 API 标准,那为啥不直接拿来使用呢,这样不仅省去了定制标准的冥思苦想,同时也省去了为小程序开发组件库与 API 的麻烦,只需要让其他端来向小程序靠齐就好。

    可能有些人会有疑问,既然是为不同的端实现了对应的组件库与端能力 API (小程序除外,因为组件库和 API 的标准都是源自小程序),那么是怎么能够只写一份代码就够了呢?因为我们有编译的操作,在书写代码的时候,只需要引入标准组件库 @tarojs/components 与运行时框架 @tarojs/taro ,代码经过编译之后,会变成对应端所需要的库。

    d88feeb41eb5c95e474fb34c4ab042569437c7a6
    既然组件库以及端能力都是依靠不同的端做不同实现来抹平差异,那么同样的,如果我们想为 Taro 引入更多的功能支持的话,有时候也需要按照这个套路来。例如,为了提升开发便利性,我们为 Taro 加入了 Redux 支持,我们的做法就是,在小程序端,我们实现了 @tarojs/redux 这个库来作为小程序的 Redux 辅助库,并且以他作为基准库,它具有和 react-redux 一致的 API,在书写代码的时候,引用的都是 @tarojs/redux ,经过编译后,在 H5 端会替换成 nerv-reduxNervRedux 辅助库),在 RN 端会替换成 react-redux。这样就实现了 Redux 在 Taro 中的多端支持。
    d001d76bc5f7e5550a3b4d26082dc770394caaff

    以上就是 Taro 的整体设计思路,里面还有很多细节没有展开去阐述,可能大家会觉得有些意犹未尽,后续我们将会产出一系列的文章来阐述 Taro 的技术细节,例如 《Taro 开发工具原理分析》、《Taro 代码编译的背后》、《深入浅出 JSX 转小程序模板》等等。

    最后的最后

    Taro 从立项之初到现在已经差不多有了三个月左右的时间,从最初的激烈讨论方案,各种思想的碰撞,到方案逐渐成型,进入火热的开发迭代,再到现在的小程序端和 H5 端顺利支持,从而决定走向开源。这一路走来,收获颇丰,既有跟团队小伙伴一起创造的激动,也有无数个日夜加班的苦思。Taro 是凹凸实验室的诚意之作,我们也将会一直维护下去,希望 Taro 能越来越好,帮助更多人创造更多价值。


    原文发布时间为:2018年06月25日
    原文作者:凹凸实验室
    本文来源:掘金      如需转载请联系原作者

    展开全文
  • React小程序现状

    2018-09-08 00:31:33
    (点击上方公众号,可快速关注)作者:司徒正美zhuanlan.zhihu.com/p/41144332现在做React小程序,一个是taro,一个是anujs。anuj...
        

    (点击上方公众号,可快速关注)

    作者:司徒正美

    zhuanlan.zhihu.com/p/41144332


    现在做React转小程序,一个是taro,一个是anujs。

    anujs的React小程序一开始是群的方正搞的,后来神烦IT狗接手。当我们想抄袭时,已经有一个可以运行的demo。taro那时名声很大,但实质并不如意。我研究了好久taro的源码,发现可以使用tempate元素避开小程序的自定义组件不能在构造器传参的问题,就正式动工了。

    小程序的自定义组件不能在构造器传参的问题, 用过React的同学都知道,React的组件构造器有两个传参props与context,这都是react帮你传入的。props是JSX中同名的标签的属性组成的对象,context是上方组件的getChildContext()产生的对象的并集。而小程序的Component只是一个方法,你传什么它就有什么,不会帮你加东西。

    开发了大概有三个星期,已经脱离方正大大的源码。组件的思路使用双模板机制——即用户编写时是React风格编写的(es6与jsx),通过我们一番神操作,它会产生三个文件,第一个是js文件,es5与createElement风格,类机制改由ReactWX的miniCreateClass方法实现,第二个是json配置对象,涉及路由的title与窗口颜色的定义,第三个是wxml文件,我们将render方法的jsx抽取出来,变成这个文件。

    现在我们的React小程序有如下优势

    1. 支持npm安装

    2. 支持less与sass

    3. 支持小程序的自带UI库

    4. 支持在JSX直接使用p, div, i, b等HTML标签,它们会在wxml转换成view与text标签。

    5. 支持在JSX中使用函数体与复杂的对象传参,即onClick={function(){ console.log() }}onClick={this.changeAge.bind(this, index, {aaa:111,bbb: 222})}

    6. 支持React完整的生命周期,并保证顺序。

    7. 对wx所有接口进行重新包新,将回调风格转换成Promise风格


    640?wx_fmt=jpeg

    anu的React转小程序的性能是有保证的,它不会mpvue或taro那样使用nextTick,而是在一个页面的虚拟DOM更新完才发一次setData。这样就避免了复杂data diff与data 序列化。

    小程序的setData性能很差,不能传入过大的对象,它会对data进行序列化。 因此一些转译框架会进行diff操作。但只要减缓它setData的频率,这一步就可以略去。

    640?wx_fmt=jpeg

    事件系统上,支持onXXX与catchXXX。catchXXX是模拟阻止事件冒泡实现的API。微信小程序的同学说,用户事件是异步的,所以这里只有定义式接口,没有过程式的

    640?wx_fmt=jpeg
    640?wx_fmt=jpeg

    与React的差异

    1. 微信小程序的事件机制有瑕疵,不支持stopPropagation与preventDefault。我们将e.detail当成事件对象,在它基础上添加type,target,touches,timeStamp等属性与空的stopPropagation与preventDefault方法
    2. 事件的绑定,不要使用this.props.fn或this.state.fn,要用this.fn这种形式,微信在给模板填数据时,会对数据进行JSON.stringify,清掉所有事件。
    3. 组件系统是基于小程序的template元素,由于不支持slot,因此无法使用{this.props.children}实现显式的组件套嵌
    4. 不完整支持ref机制(refs可以放入组件实例,但不能放DOM,因为没有DOM)
    5. 无状态组件还没有实现
    6 还没有支持findDOMNode
    7. 不支持render props
    8. 不支持dangerouslySetInnerHTML属性

    关于组件标签套组件标签,需要官方的slot机制支持,目前得到的回复是这样的:

    640?wx_fmt=jpeg

    使用

    从“RubyLouvre/anu下” git clone下来, 命令行定义到packages/cli目录下,执行npm link
    使用mpreact <project-name> 创建工程
    定位到 <project-name> 目录下 mpreact start 开始监听文件变化,
    用微信开发工具打开当中的dist目录,自己收在src目录中进行开发.

    小程序在它的体积还是1mb时,开发体验是很好的,性能也很好。但随着体积的限制放开了,产品经理开始乱搞,小程序原生的API与组件机制就跟不上了。不可能一个APP上有10个弹层,每一个都写一次吧。缺乏继承是它的硬伤。事件机制与我们熟悉的机制差太远。createSelectQuery也设计得非常弱智,wxs过于奇怪。因此有了webview标签后,许多人直接引入页面了。。。因此才有这么转译框架的诞生,包括TX内部的weby。

    目前市面上许多转译框架是vue风格的,这对React技术栈的同学不公平,于是有了taro与anu的转译器。anu保留了虚拟DOM的模板,因此会比taro,mpvue更能突破小程序的桎棝。


    【关于投稿】


    如果大家有原创好文投稿,请直接给公号发送留言。


    ① 留言格式:
    【投稿】+《 文章标题》+ 文章链接

    ② 示例:
    【投稿】《不要自称是程序员,我十多年的 IT 职场总结》:http://blog.jobbole.com/94148/

    ③ 最后请附上您的个人简介哈~



    觉得本文对你有帮助?请分享给更多人

    关注「前端大全」,提升前端技能

    640?wx_fmt=png

    640?wx_fmt=jpeg

    展开全文
  • 铺垫 随着大前端蓬勃发展, 冒出越来越多的端, 最火的当数最近出现的微信小程序. 但是无论是 微信小程序 , ...虽然小程序使用类似Vue, angular的模板渲染, 实现了类MVVM的开发方式.但是小程序的开发方式相当蛋疼. 以...

    铺垫

    随着大前端蓬勃发展, 冒出越来越多的端, 最火的当数最近出现的微信小程序. 但是无论是 微信小程序 , 还是 支付宝小程序, 或者 快应用 都有一个明显的缺点, 虽然他们还是按照一定的 js html css 标准作为开发方式, 但是他们都与当前所有主流技术有相当大的壕沟.

    虽然小程序使用类似Vue, angular的模板渲染, 实现了类MVVM的开发方式.但是小程序的开发方式相当蛋疼. 以下是一个简单小程序的目录结构:

    上述目录只包含页面内容, 开发过程中需要不断在不同文件中切换. 相比React的Component+css 和 Vue的单文件来看, 开发体验不太好. 并且很多小程序开发者都是vue、React、angular等等前端框架的使用者, 使用熟悉的开发栈对他们来说更容易上手.

    小程序的本质

    在开发一个工具前要理解运行载体的原理. 正如我们希望用React去开发小程序, 那么我们必须要了解小程序的原理.

    因为小程序是闭源的, 我只能在自己的猜想上分析. 但是小程序的底层是Native 这是前提. 那么我猜想小程序的实现原理应该跟ReactNative类似, 通过js bridge搭建js和原生通信的桥梁, 由js及模板, 实现对页面的渲染描述.

    但是小程序与ReactNative的不同点是, ReactNative对js层开放renderer api. 而小程序则对这层进行了封装. 这让我们无法通过重新实现React的renderer来使用React的一些特性(如vdom).

    所以我的思路是通过语法转换, 把React文件转换成小程序工程文件. 并实现小程序的框架, 来对接小程序与react的生命周期方法.

    期望

    我希望能把React文件, 经过编译后, 变成可执行的微信小程序

    import Page from '../wechat'
    import './page.css'
    
    class P extends Page {
      onClick(){
        
      }
      render() {
        return (
          <div className="app" onClick={this.onClick} style={{posistion:"relative"}}>
            威武
          </div>
        )
      }
    }
    复制代码

    开始我们的旅程

    有了开发小程序的思路, 那我们就来动手. 我使用了babel作为语法转换的工具, 我们先开个头. 下面是转换的核心代码

    function transform(code, sourcePath) {
      let output = {
        wxml:'',
        wxss:'',
        js:'',
        json:'',
        type:''//App||page||component
      }
      sharedState.sourcePath = sourcePath;
      const result = babel.transform(code, {
        babelrc: false,
        plugins: [
          '@babel/plugin-syntax-jsx', 
          transformPlugin, 
          '@babel/plugin-proposal-object-rest-spread',  
          ['@babel/plugin-proposal-decorators',{"legacy": true}] 
        ]
      })
      // tranform后, 结果都会写入sharedState.output
      output = sharedState.output;
      const obj = t.objectExpression(sharedState.methods);
      output.js = generate(obj).code;
      sharedState.reset();
    
      switch(output.type){
        case 'App':
          output.js = CodeWrapper('App', output.js);
          break;
        default: //Page
          output.js = CodeWrapper('Page', output.js);
          break;
      }
    
      return output;
    }
    复制代码

    该部分代码实际上就是通过babel 对React代码文件进行处理, 处理后把结果写入到output. 重点在于, 我们通过babel.transform这个方法, 把代码拆分成四块, 分别写入到sharedState.output中.

    最终通过一些简单处理后, 返回output, 不难看出output中的wxss, js, json, wxml就是一个小程序页面/组件的代码文件.

    其中 transformPlugin 是自定义的编译插件. 今天有点晚先到这里, 下期继续讨论插件开发思路.

    项目代码: https://github.com/PepperYan/react-miniapp)

    喜欢这篇文章的大佬, 点个赞和star, ٩(๑´0`๑)۶

    该项目参考了mpvue, taro, weact等. babel-traverse和babylon babel

    还有感谢 @方正 提点

    原文链接: https://zhuanlan.zhihu.com/p/38102065

    展开全文
  • react与微信小程序

    2019-08-03 20:20:52
    都说react和微信小程序很像,但是像在什么部分呢,待我稍作对比。 生命周期 1.React React的生命周期在16版本以前与之后发生了重大变化,原因在于引入的React Fiber,Fiber的引入是为了解决庞大的组件树在更新的时候...

    由组员完成 原文链接

    都说react和微信小程序很像,但是像在什么部分呢,待我稍作对比。

    生命周期

    1.React
    React的生命周期在16版本以前与之后发生了重大变化,原因在于引入的React Fiber,Fiber的引入是为了解决庞大的组件树在更新的时候产生的性能问题。我们知道,组件树是一层一层的,在更新的时候,同样也是一层一层深入的,对于层级特别深的组件树,无疑需要耗费大量的时间,用户若在这段时间内进行操作,由于主线程用于UI更新,会无暇顾及用户的操作。而Fiber将一个耗时很长的任务分解成一个一个小片,每完成一个小片就去检查现在是否有需要执行的紧急任务,而Fiber就是维护分片的数据结构。
    但是Fiber的出现会造成反复渲染的情况,所以生命周期需要作出改变

    0*OoDfQ7pzAqg6yETH.

    图片来自于 https://medium.com/@baphemot/understanding-react-react-16-3-component-life-cycle-23129bc7a705

    • getDerivedStateFromProps为一个纯函数,可以进行无副作用的操作
    • ajax一类的操作放在componentDidUpdate中

    2.微信小程序

    微信小程序的生命周期我们可以从文档中略知一二
    page-lifecycle.2e646c86.png
    我们在新建一个页面的时候,会实例化一个page,里面有onLoad等等的函数

    事件处理

    1. React
      React的事件处理并非同步的,这也是使用setState的原因。根据变量isBatchingUpadates判断为直接更新还是放在队列中,默认状态为false,也就是同步更新
      2.微信小程序
      微信小程序中使用setData更新数据,基本格式相同

    组件

    两者都有组件化的概念,不过在学习中,小程序涉及的好像并不多。

    转载于:https://www.cnblogs.com/Phoenix-blog/p/10907539.html

    展开全文
  • 由于上一篇文章比较突兀就进入转换入口. 考虑了一下还是需要补全一些前置说明. 书接上回, 我们已经整理了小程序的前置知识....转成小程序代码后, 为何还考虑增加react-miniapp-core包. 有以下几...

    由于上一篇文章比较突兀就进入转换入口. 考虑了一下还是需要补全一些前置说明. 书接上回, 我们已经整理了小程序的前置知识. 这次先来补齐一些设计.

    代码转换可以使用 webpack, rollup等打包工具作为入口, 如webpack设置entry. 然后通过babel及自定义插件进行编译, 转换成小程序代码.

    转成小程序代码后, 为何还考虑增加react-miniapp-core包. 有以下几方面考虑.

    • 方便扩展
    • 生命周期Bridge

    生命周期Bridge

    我们知道一个 React组件 的包括从构造函数开始(getInitialState替代品), 到getDerivedStateFromProps, 到render等等一系列的生命周期钩子. 这些生命周期函数将会在React渲染中的对应各个阶段被调用.

    但是在小程序中, 这一系列生命周期将会失效. 因为 在小程序中, 渲染各个周期的生命函数钩子由小程序生命周期API指定, 在小程序中, React 生命周期钩子无法直接使用, 但是我们又希望拥有原汁原味的React开发体验. 这时就需要我们在runtime实现Page和Component的生命周期,并唤起React组件相应的生命周期钩子. 由于我的工程未实现runtime部分功能. 以下为 taro 的生命周期bridge代码:

      const weappPageConf = {
        onLoad (options) {
          page._init(this)
          page.$router.params = options
          componentTrigger(page, 'componentWillMount')
        },
        onReady () {
          componentTrigger(page, 'componentDidMount')
        },
        onShow () {
          componentTrigger(page, 'componentDidShow')
        },
        onHide () {
          componentTrigger(page, 'componentDidHide')
        },
        onUnload () {
          componentTrigger(page, 'componentWillUnmount')
        },
        ...
      }
    复制代码

    下面我们来开始正题, 对babel插件开发说明

    Babel

    使用es6开发的人都不会对这个库陌生. 我们通常使用 Babel 时会创建.babelrc 进行以下配置

    {
     "presets": [ ... ],
     "plugins": [ ... ],
    }
    复制代码

    配置中包含presets和plugins. 其实presets也只是一堆插件的集合. 那么其实我们需要开发一款把React代码转换为小程序代码的babel插件.

    那么我们先来看看Babel有那些部分

    Babel 编译

    Babel有很多很多的子库, 其中最核心的就是 @babal/core.

    但是其实涉及核心编译生命周期主要是以下三步:

    • parse 是指把源码解析成AST.
    • traverse 通过对AST进行解析, 可对原AST进行相应转换.
    • generate 把AST再次生成目标版本代码.

    @babel/core 分别使用相应的子库来实现这三个生命周期. 这里不深入讨论, 有兴趣的可以去看babel的源码. babel主要插件也分两部分: parser plugin 和 traverse plugin. 而我们需要自行实现的plugin就是traverse plugin.

    到这里我们完成了铺垫. 下次会继续说明插件的实现方式 如果时间足够还可以讨论实现思路.

    项目代码: https://github.com/PepperYan/react-miniapp)

    喜欢这篇文章的大佬, 点个赞和star, ٩(๑´0`๑)۶

    该项目参考了mpvue, taro, weact等.

    展开全文
  • 使用 React 开发小程序

    2020-05-15 11:10:49
    为什么要 React 开发小程序 大家知道微信小程序在商业上取得了非常大的成功,正是因为小程序在商业上的成功,导致后面不管是支付宝还是其他厂商在推出自己的小程序时,都参考了微信小程序的 API 设计。但是作为...
  • react小程序 对比

    2019-03-22 19:49:35
    主要从以下几个方面对比下react和微信小程序 生命周期 react 小程序 onLoad: 页面加载时触发。一个页面只会调用一次,可以在onload的参数options中获取打开当前页面路径中的参数。 onReady: 页面初次渲染完成时...
  • 无论是 Vue, react 还是小程序对于组件化开发都有很好的支持,要想掌握好组件化开发,组件之间的通信是无法绕过的话题,最近技术栈从 Vue 转向了 react + 小程序,便总结了一下在进行 react小程序开发时,组件...
  • 公司使用微信小程序做了不少东西,发现的痛点越来越多。没有组件化,配置繁锁,生命周期名字不一。基于它才有了vue系列的解决方案,我在想,能不能搞一套React的解决方案呢。毕竟以React为技术栈的公司不在少数,...
  • 文章目录1. Hybrid App1.1 优势1.2 技术原理1.3 现有方案2. React Native的底层框架2.1 总体框架2.2 UI渲染2.3 通信机制2.4 小结3. 小程序的底层框架3.1 双线程...本文是学习React Native与小程序官方开发指南的笔...
  • 今天跟大家分享的主题是 React 开发小程序的探索之路 。 在目前市面上已经有非常多的小程序开发框架,其中的佼佼者如 wepy 以及 mpvue ,他们都是非常优秀的小程序开发框架。但是它们都有一个共同的特点,都是通过...
  • React转微信小程序:双模板联动 这是本系列的最后一篇。小程序封死了操作DOM的可能性,并且也不让我们操作视图,所有与视图有关的东西一律接触不了。而它的自定义组件是非常恶心,基本不配叫组件,不能继承叫什么...
  • https://remaxjs.org/quick-start/wechat
1 2 3 4 5 ... 20
收藏数 38,616
精华内容 15,446
关键字:

用react写小程序