美文网首页React Native相关Web前端之路让前端飞
Elm的RN的Redux版本改造(1)-模拟数据的获取

Elm的RN的Redux版本改造(1)-模拟数据的获取

作者: smartphp | 来源:发表于2017-05-12 21:44 被阅读637次

    看到那个elm的react-native练习项目还挺火的,所以想着用Redux来改造一下.
    elm RN项目

    1. 主要添加有mock-server作为后端数据模拟
    2. Redux的作为前端数据层
    3. Redux-saga对于管理异步操作数据流
    4. immutable对于不可变数据的管理
    5. 后续添加一些其他的东西例如导航系统和表单系统

    目的:在没有后台服务器的情况下,使用mock-server来模拟后台数据,形成完整的React-Redux的数据流.

    后端数据的模拟

    elm的RN的数据来源是一部分从data.js中获取,一部分是直接在页面中模拟.
    这么做对于写页面没有问题,但是对于远程请求的问题就没有办法了. 如果是直接在页面中通过fetch函数来获取,也是可行的,但是一旦数据来源很多的时候,管理和编写代码就变得很麻烦.拿elm的首页来说,如果在实际中要从网络服务请求的数据非常多,后面会讲到.这时候有必要引入Redux来对数据的请求和组织做集中处理.我考虑的不仅仅是数据请求的代码问题,其实还包括速度的问题.这个后面也会说到.

    我们直接到位,借用mock-server这个很牛的工具来模拟远程的数据.这个服务的设置和使用还是非常简单的.

    我觉得在使用中你要清楚三个问题,一是node.js的一些基础知识,mock-server是用think.js框架写的,您没看错,的确不是thinkphp.呵呵.
    这个框架里的写法和thinkphp很相像.可不是,名字都差不多.但是差的十万八千里了.有一点node.js的知识就行,我们不在这里写代码.二是如果遇到要真机调试的时候,懂代理的设置,意思是这个mock-server实际是运行在127.0.0.1下的,要想办法让外界的终端可以访问.当然如果是模拟器调试就没有问题.三是mysql数据库的,要能启动,mock-server是不自带mysql服务器的,需要自己启动和配置.这个我们按步骤来说明,mac下我使用的是mamppro这个软件,非常的方便.

    首先安装mock-server服务器

    非常简单没有什么难度.请参见简书文章:node.js web版 mock-server 让你更好的管理你的模拟数据
    https://github.com/flftfqwxf/mockserver

    1. 依赖包npm安装
    npm install
    
    1. mysql数据库的安装



      用了mac下的比较好的mamp pro这个集成环境,里面非常好用的是mysql的密码修改,很方便,总是记不住密码.使用brew 安装mysql也可以用.


    2. 根据mysql数据的用户名和密码更改mock-server的配置文件
    src/common/config/db.js
     mysql: {
                host: '127.0.0.1',
                port: '3306',
                database: 'mockserver',
                user: 'root', //根据你自己mysql用户名修改
                password: 'YES', //根据自己的mysql密码修改
                prefix: 'mock_',
                encoding: 'UTF8MB4_GENERAL_CI'
            },
    
    1. 导入.sql文件数据

    2. 进入文件夹目录运行npm start,运行在127.0.0.1:8003端口

    3. 就可看到下面的后台界面了


    4. 我们新建一个elm的项目,后面的的api都放到这里

    5. 举个例子 ,我们想要一个列表API:


    6. 修改


    7. 设置响应参数



      看到后面输出了统计结构,就可以使用了.

    8. 点击保存后,查看结果,地址栏就是api的链接,输出就是json数据

     [
      {
        "name": "田老师红烧肉(知春路店)",
        "isBrand": true,
        "logo": 27,
        "scores": 3.5,
        "sale": 4013,
        "bao": true,
        "piao": true,
        "ontime": true,
        "fengniao": true,
        "startPay": "¥20起送",
        "deliverPay": "配送费¥4",
        "evOnePay": "¥21/人",
        "journey": "250m",
        "time": "35分钟",
        "activities": [
          {
            "key": "减",
            "text": "满20减2,满30减3,满40减4(不与美食活动同享)"
          },
          {
            "key": "特",
            "text": "双人餐特惠"
          }
        ]
      },
      {
        "name": "稻麦香(金源店)",
        "isBrand": true,
        "logo": 21,
        "scores": 2.5,
        "sale": 2419,
        "bao": true,
        "ontime": true,
        "startPay": "¥0起送",
        "deliverPay": "配送费¥2",
        "evOnePay": "¥11/人",
        "journey": "150m",
        "time": "25分钟",
        "activities": [
          {
            "key": "减",
            "text": "满20减2,满30减3,满40减4(不与美食活动同享)"
          }
        ]
      },
      {
        "name": "米有理由(中关村店)",
        "logo": 11,
        "scores": 1.5,
        "sale": 1419,
        "startPay": "¥0起送",
        "deliverPay": "配送费¥5",
        "evOnePay": "¥12/人",
        "journey": "450m",
        "time": "45分钟"
      },
      {
        "name": "吉野家(鼎好店)",
        "isBrand": true,
        "logo": 16,
        "scores": 4.5,
        "sale": 3419,
        "ontime": true,
        "startPay": "¥0起送",
        "deliverPay": "配送费¥2",
        "evOnePay": "¥14/人",
        "journey": "150m",
        "time": "25分钟",
        "activities": [
          {
            "key": "减",
            "text": "满20减2,满30减3,满40减4(不与美食活动同享)"
          },
          {
            "key": "新",
            "text": "新品5折"
          },
          {
            "key": "特",
            "text": "双人餐特惠"
          }
        ]
      },
      {
        "name": "周大虾龙虾盖浇饭(中关村东路店)",
        "logo": 18,
        "scores": 4,
        "sale": 4013,
        "piao": true,
        "ontime": true,
        "fengniao": true,
        "startPay": "¥20起送",
        "deliverPay": "配送费¥4",
        "evOnePay": "¥21/人",
        "journey": "250m",
        "time": "35分钟",
        "activities": [
          {
            "key": "特",
            "text": "双人餐特惠"
          }
        ]
      },
      {
        "name": "轰咖咖喱饭(中关村东路店)",
        "isBrand": true,
        "logo": 17,
        "scores": 4,
        "sale": 4013,
        "piao": true,
        "fengniao": true,
        "startPay": "¥20起送",
        "deliverPay": "配送费¥4",
        "evOnePay": "¥21/人",
        "journey": "250m",
        "time": "35分钟"
      }
    ]
    

    一下的其他接口依次来处理,就不再多说了,这个讲的够详细了.需要注意json对象和javascript对象的写法的差异性.如果写不对json格式.可以在console里面使用JSON.stringify()函数来转一下(键名和键值加双引号).

    这是个工具,我们接着这个工具来完成模拟数据的工作

    用实际UI替代设计原型图

    首页的截图


    首页截图首页截图

    下面根据逻辑功能对可视的这一部分做一下分类标记, 屏幕下面没有显示的部分,我刻意没有标出来,这么做是从性能上考虑的,后面在获取远程数据的时候会讲到这一点.


    逻辑分区的分解

    1.地名和天气数据的获取

    实际的编码中应该是先从本机的gps获取地里位置,接着可以获取到地名和天气信息.

    getLocationData() //根据gps信息获取地里信息
     {
       
      
      "address": "三里屯CBD"
    }
    
    getWeatherData() //根据gps信息获取天气信息
    
    {
      "location": "北京",
      "district": "朝阳",
      "tempature": [
        19.2,
        25.3,
        37
      ],
      
      "pm2.5": 25,
      "wind": "breeze",
      "weather": "sunny",
      "ultravolvet": "strong",
      "clothing": "single"
    }
    

    2.关键词部分

    //getkeywords()
    {
     "keywords": [
      "肯德基","粥","必胜客","一品生煎","星巴克"
     ]
     ,
     "string": "Hello World"
    }
     
    

    3.搜索,这一块没有获取数据,所以暂时不处理

    4.swipe部分,这一部分的名称不动,但是可以根据网络状况选择在Wifi条件下去加载网络图片,在其他环境下从本地加载图片

    5. 每日图片.

    返回一张图片的url地址

    //everydayPic
    {
    "everydaypic": {
      "name": "测试",
      "url": "https://ww1.sinaimg.cn/large/006tNbRwly1ffdm6jl0ylj30rs04t3yy.jpg",
      "info": "测试信息",
      "picID": "图片有关介绍"
    }
    }
    

    6.推荐套餐

    //recommend
    {
    "array": [
      {
        "热卖套餐": {
          "keyword": "热卖",
          "价格": 100,
          "picurl": "https://ww4.sinaimg.cn/large/006tNc79ly1few6ck5q31j30rs06eabn.jpg"
        }
      },
      {
        "霸王餐": {
          "keyword": "20元折扣",
          "价格": 100,
          "picurl": "https://ww4.sinaimg.cn/large/006tNc79ly1few6ck5q31j30rs06eabn.jpg"
        }
      },
      {
        "年货到家": {
          "keyword": "年货节",
          "价格": 100,
          "picurl": "https://ww4.sinaimg.cn/large/006tNc79ly1few6ck5q31j30rs06eabn.jpg"
        }
      },
      {
        "5折优惠": {
          "keyword": "5折优惠",
          "价格": 100,
          "picurl": "https://ww4.sinaimg.cn/large/006tNc79ly1few6ck5q31j30rs06eabn.jpg"
        }
      }
    ],
    "keywords": "推荐套餐"
    }
    

    在首页可视的部分加载了几种数据,在整个页面中还有内容没有加载完,是不是考虑也要加载?肯定要的,但是这个可视的地方就是一个界限,为了保证速度,我觉得首先加载可视部分,不可见的部分稍后加载.在javascript的意思就是,先加的入队操作,后加的后操作,但是分开步骤来分布加载,首页加载的压力就小了.为什么要考虑这个问题?在f8 app中就出现这问题,作者指出来了.
    在f8 app的 f8APP.js文件(相当于初始化文件)中有这样的代码:

     // TODO: Make this list smaller, we basically download the whole internet
      //这个地方在先于UI组件之前加载了所有的state,
      //这里可以加载一部分首先需要的数据
         this.props.dispatch(loadNotifications());
      this.props.dispatch(loadMaps());
      this.props.dispatch(loadConfig());
      this.props.dispatch(loadSessions());
      this.props.dispatch(loadFriendsSchedules());
      this.props.dispatch(loadSurveys());
    

    在这个文件中使用了redux的dispatch方法,加载了大量的数据.要考虑到分别加载的问题. 这就是需要解决的问题出发点.

    我们同样也可以在一个入口文件(意思就是程序启动的文件,怎么能这样做呢?参考一下f8 app的做法吧.)中来加载首要显示的内容,不在可视区的数据我们在Home.js的生命周期函数中再加载.

    这是一个解决性能问题的思路.供参考.


    先写这么多. 利用好这些mock类的程序.这样把前后端的问题可以联系起来考虑.我这里指的是数据流的问题.这个流程和UI设计是独立的.
    在这里前端人员掌握mock-server的好处是,你可以根据模拟的接口来思考当你在React程序中引入Redux以后怎么来组织state树中的数据. 因为Redux中数据是单向从store中流向React的UI组件的,state有个整体性,所以需要整体考虑.当然这里是比较简单的,如果是社交和电商软件,需要考虑到数据的交叉引用问题,这就不是我一人能思考的问题了.在mock-server项目中的数据结构可以以利于你形成下面的state的基本结构. UI组件需要的数据都从下面这张图中来获取.

    相关文章

      网友评论

      • 龙49:我们这边的有些post接口URL是一样的,是通过入参的一两个字段不一样来返回不同的数据。但是目前的mock serve没法识别入参来返回对应的数据。请问有什么其它的方法来应对这样的问题吗?
      • 冷洪林:欢迎加入React Native交流群,群号:647393547
      • Eternaldream:题主,请教下,我按照你的方式做,提示我这个`ER_BAD_DB_ERROR: Unknown database 'mockserver'`,是什么原因呢?
      • 迷茫中成长:作者大大,我安装react native 新建的项目不能运行......MAC的
      • smartphp:今天又看了一下Rxjs是讲什么的.又理解了一点点东西.
        在f8 app setup.js中加载数据那里其实有点机械化了.完全可以利用Redux的异步控制流技术
        写一个 Homepage_loading_flow 的控制流,在这个流程中控制首页页面的数据加载的顺序步骤.
        这个首页数据的加载和首页和用户的交互是没有关系的. 如果是要根据用户的交互操作来执行这个任务,那么也可以监听 页面的滚动事件,在回调函数中加载不可见区域的数据.

      本文标题:Elm的RN的Redux版本改造(1)-模拟数据的获取

      本文链接:https://www.haomeiwen.com/subject/gwytxxtx.html