React Native相关Web前端之路让前端飞

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

2017-05-12  本文已影响637人  smartphp

看到那个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组件需要的数据都从下面这张图中来获取.

上一篇 下一篇

猜你喜欢

热点阅读