zoukankan      html  css  js  c++  java
  • react服务端/客户端,同构代码心得

    FKP-REST是一套全栈javascript框架

    react服务端/客户端,同构代码心得

    作者:webkixi

    react服务端/客户端,同构代码心得

    服务端,客户端同构一套代码,大前端的梦想,为了省略重复的代码,却平添了不少烦恼,头发也白了,。。。。,妹子还在家等我.

    目录结构问题

    我们引用了很多的库,在开发前端代码的时候,习惯性的我们不会考虑到node端对于库的引用,这就是开始同构最大的痛点。整个目录结构需要调整。

    减少调用层级

    比如说开发前端时,有一个libs的库,在react的前端组件开发时,我们多次调用到libs里面的若干方法,这个时候,为了同构,需要将libs库做一个抽离,既是从前端代码中抽离到中间的部分。

    这么说有点不好理解,简单配一个图吧。

    FKP原来的结构

    node -> fed -> libs -> component -> pages

    大致上我们原来的结构都类似于这样,调整好之后的结构,如下:

    node <-> libs <-> fed -> component -> pages

    这样,我们将libs抽离到中间的部分,相对来说,在同构时,require的层级少了很多。但是还不够,为了 将react同构,我们还需要调整component的结构,如下:

    node <-> libs <-> component <-> fed -> pages

    如此这般,大致的结构算调整好了,接下来解决require的坑,让webpack和node端require做到无缝切换。 让require('libs/index'),这种引用兼容于两端。 在这里FKPJS用到了一个好用的包文件app-module-path,指定node端require的目录优先级,及自写了一个 include的方法(封装require),来简化require的调用深度。 并对libs库做更细化的抽象与提取,最后,FKPJS的libs结构做到如上所述。

    组件结构问题

    解决了目录结构问题后,为了做到同构,我们需要合理的组件结构,以方便两端的调用,经过本人的实践,FKPJS将组件分为三层,原子组件组合组件组件封装,如下图

    原子 -> 组合 -> 封装

    1. 原子组件(react/widgets)

    适用node/fed,复用型组件,最小粒度化,产出纯结构,纯粹的react组件,封装了对数据的处理

    2. 组合组件(react/modules/xxx/_component/xxx)

    适用node/fed,组合不同的原子组件,并引入相关mixins,实现like redux,产出纯结构,纯react组件,传输数据

    3. 组件封装(react/modules/xxx/yyy)

    适用于前端,最表层,处理配置文件,可导入JQ等库实现内部逻辑、效果,并响应由业务层传导进来的方法,数据等等。

    在FKPJS中封装的比较好的有两个组件,react/modules/pagination/pagireact/modules/list/base_list.jsx,list组件有点复杂,我们先说下 pagi这个组件吧

    pagi这个组件,用于分页,可前后端同构

    Demo

    前端业务中实现的代码

    varPagi=require('modules/pagination/pagi'),// 初始化分页数据
        pageData ={
         total:60,
          per:20,
         url:'/',
          query:'page='}Pagi(pageData,{
        container:'pagi',begin:{ start:0, off:5},
        itemMethod: bindItem
    })

    服务端同构的代码

    // pages/pagi.jsvar _props ={
            itemMethod:false,
            listMethod:false,
            itemClass:'',
            listClass:'pagenation wid-12',
            data:{
                total:60,
                per:20,
                url:'/',
                query:'page='},begin:{ start:0, off:5}}var reactHtml =yield react2html('react/modules/pagination/pagi', _props)
        reactHtml[0]='<div class="pagi" id="pagi" >'+reactHtml[0]+'</div>'
        oridata.pagi = reactHtml[0]return.....

    组件封装

    封装部分

    // 封装方法function pagination(data, opts ){// 处理配置文件  var noop =false,
            dft ={
                container:'',
                globalName:'_Pagi',
                itemMethod: noop,
                listMethod: noop,
                itemClass:'',
                listClass:'pagenation wid-12',
                data:{
                    total:200,
                    per:10,
                    url:'/',
                    query:'page='},begin:{ start:0, off:7}}
    
        dft = _.assign(dft, opts)if(!dft.container)returnfalse;if(data){
            dft.data = data
        }// fkp redux// 初始化组件数据// FKPJS使用SA代替redux// 需要在组合组件中引入,store的minxin
    
        SA.set(dft.globalName,{
            data: data,begin: dft.begin})// fkp redux // 将组建的action放到 SA 的全局名字中// 需要在 _Pagi组件中引入 store 这个mixinsvarPagi=_Pagi(dft.globalName)// 渲染组件
        render(<Pagi data={data}begin={dft.begin} itemDefaultMethod={idm} itemMethod={dft.itemMethod} listMethod={dft.listMethod} itemClass={dft.itemClass} listClass={dft.listClass}/>,
            document.getElementById(dft.container))}// 服务端同构,执行这个部分
    pagination.server =function(){return_Pagi(true)};module.exports = pagination

    组合组件

    这里不贴出所有代码,部分

    varList=require('../../../widgets/listView/list');varStore=require('../../../mixins/store');//引入这个就完成了reduxvar _storeName;var _jump =false;// List的item组件varPageItem=React.createClass({
        componentDidMount:function(){var ele =React.findDOMNode(this),
                mtd =this.props.itemMethod,
                dmtd =this.props.itemDefaultMethod;if(dmtd &&typeof dmtd==='function'){
                dmtd.call(ele, _storeName, mtd);}},.......

    组合组件-算法部分

    render:function(){if(this.state.data){var data =this.state.data,
                newData =[],
                pages = data.total/data.per,
                pre,
                aft,
                half,begin=this.state.begin,........

    组合组件-实现部分

    function actRct( storeName ){// 根据storeName,可以实现多个组件,并redux化// for serverif(storeName===true){returnReact.createClass( pagenation );}// for client
        _storeName = storeName||'_Pagi';var _rct = _.cloneDeep(pagenation);if( _rct.mixins && _rct.mixins.length ){
      _rct.mixins.push(Store( _storeName ))//实现redux}else{
      _rct.mixins =[Store( _storeName )]}returnReact.createClass( _rct );//返回react组件

    原子组件

    1. List List source
    2. Item Item source
    3. Item 算法部分 Item算法实现

    综上所述,做到两端同构的话,需要有一个全局的眼光,从基础的目录结构开始,到组件的结构,其实还有css的结构,html的结构,这里就不一一说明了,希望能抛砖引玉

    文章目录

      • 目录结构问题
      • 组件结构问题
     
  • 相关阅读:
    ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint......
    模拟Executor策略的实现
    设计3D标签
    创建被图像填充的组件
    netty基础09_利用EmbeddedChannel做单元测试
    netty基础08_引导类
    netty基础07_Netty提供的消息处理器和编码解码器
    netty基础06_编码器和解码器
    netty基础05_管道和消息处理器
    netty基础04_数据缓冲区
  • 原文地址:https://www.cnblogs.com/yzf851348507/p/5601060.html
Copyright © 2011-2022 走看看