当前位置: 首页 > 科技观察

前端编码如何实现人肉双向编译

时间:2023-03-14 00:23:16 科技观察

前端编码如何实现人肉双向编译React+flux是目前最流行的前端方案之一,但是flux有很多槽点,比如store比较混乱,使用起来比较麻烦等等,所以就有很多第三方的flux优化架构。有人盘点了目前主流的flux实现方案。如果您有兴趣,可以在这里阅读:WhichFluximplementationshouldIuse?其中redux是目前github上star最多的解决方案。这个解决方案完全独立于React,这意味着这个概念可以作为架构层应用到其他组件化方案中。同时还提供了官方的react-redux库,帮助开发者直接使用react+redux进行快速开发。个人对其主要特点的理解体现在以下几点:强制使用全局store,store只提供了几个简单的API(实际应该有4个),如subscribe/dispatch(订阅、发布)、getState、replaceReducer.store负责维护一个唯一的对象,称为状态树,其中状态存储了应用程序需要使用的所有数据。store和顶层组件使用connect方法绑定,并为props分配一个dispatch方法,可以直接在组件内部this.props.dispatch(action)。简单的说,去掉组件和storeinflux之间的unbind/bind链接。当状态发生变化时,组件会自动更新,无需手动操作。applyMiddleware方法是为异步操作提供的,并提供添加中间件的能力,例如打印日志以跟踪应用程序的所有状态变化。对全局数据状态的操作由多个reducer完成。每个reducer都是一个纯函数,它接收两个参数,state和action,并返回处理后的state。这类似于流水线的操作。接下来就可以回答题目的问题了,即:前端编码时如何实现人肉的双向编译(zi)和翻译(can)。其实就是用coffee来写react+redux的应用。让我们写一个简单的helloworld来好玩一下。视图部分与redux/flux无关。它是一个纯粹的反应实现。如果使用jsx,渲染部分的代码如下:render:function(){return(

timer:{interval}
{title}div>
)}那怎么用coffee来写这段代码呢?我们需要先把jsx编译成这样的js代码,注意是用脑编译的:render:function(){returnReact.createElement('div',null,React.createElement('div',{className:'timer'},'timer'+this.props.interval),React.createElement('div',null,this.props.title),React.createElement('input',{ref:'input'}),反应。createElement('button',null,'clickit.'));}然后将js代码反编译成coffee。这里我们可以用$代替React.createElement来简化代码(终于可以用jQuery的坑了),感谢coffee的语法,借助React.DOM,可以用更简单的方式实现:{div,input,button,span,h1,h2,h3}=React.DOM这里render部分就不单独放了,直接看完整代码:{Component,PropTypes}=React=require'react'$=React.createElement{div,input,button}=React.DOMclassAppextendsComponentclickHandle:->dom=this.refs.input.getDOMNode()this.props.actions.change(dom.value)dom.value=''render:->{title,interval}=this.propsdivclassName:'timer',divnull,'timer:'+intervaldivnull,titleinputref:'input'buttononClick:@clickHandle.bind(this),'clickit.'App.propTypes=title:PropTypes.stringactions:PropTypes.objectinterval:PropTypes.numbermodule。exports=App如果你能看到并理解这片咖啡,并在你的大脑中自动将其编译成js代码,再编译成jsx代码,恭喜你。连接store的作用主要是实现view层和store层的绑定。当商店数据发生变化时,视图可以自动更新。这里需要使用redux提供的createStore方法创建一个store,它接受2个参数,reducer和initialstate(应用初始数据)。store.coffee的代码如下:{createStore}=require'redux'reducers=require'./reducers'#reducerstate=require'./state'#Application初始数据module.exports=createStorereducers,state然后我们就进入applicationstore与App绑定,这里使用redux官方提供的react-redux库。{Provider,connect}=require'react-redux'store=require'./store'$=React.createElementmapState=(state)->staterootComponent=$Provider,store:store,->$connect(mapState)(应用)React.renderrootComponent,document.body可能有人会问,mapState和Provider是什么鬼?mapState提供了类似选择器的效果。当一个应用程序非常大时,你可以选择将某一部分状态数据连接到这个组件上。我们这里不需要,直接返回状态本身即可。Provider是经过特殊处理的React组件。官方文档是这样描述的:这使得我们的商店实例可用于下面的组件。connect方法用于连接state和App,然后App组件内部可以使用this.props.dispatch()方法。添加action和reducer***我们添加一个按钮点击事件和定时器来触发action,并编写相应的reducer来处理数据。this.props.actions.change(dom.value)是在之前的App里面添加的,这里是action.coffee的代码:module.exports=change:(title)->type:'change'title:titletimer:(interval)->type:'timer'interval:interval然后看reducer.coffeemodule.exports=(state,action)->switchaction.typewhen'change'Object.assign{},state,title:'hello'+action.titlewhen'timer'Object.assign{},state,interval:action.intervalelsestate至此,代码完成。其他一些这里只介绍一个中间件的思想,其他的特性比如异步action,或者dispatchapromise基本类似:dispatch=store.dispatchstore.dispatch=(action)->console.logaction#Printeveryactiondispatch。applystore,arguments由于时间关系,redux的一些特性和设计原则没有展示出来。有空我再单独说。完整的项目代码,有兴趣的同学可以看这里:请点我,或者直接私聊我。项目使用fis3作为构建工具,使用fis3release可以在本地查看效果。