资讯专栏INFORMATION COLUMN

Thinking in React Implemented by Reagent

maochunguang / 1601人阅读

摘要:前言本文是学习这一章后的记录,并且用实现其中的示例。因此得到如下结构而数据则从顶层组件往下流动,各层提取各自数据进行渲染。而交互的意思是,对的操作会影响应用数据,从而刷新。更新值更新值注意中使用时,需要定义一个返回函数的高阶函数来实现。

前言

 本文是学习Thinking in React这一章后的记录,并且用Reagent实现其中的示例。

概要

构造恰当的数据结构

从静态非交互版本开始

追加交互代码

一、构造恰当的数据结构

Since you’re often displaying a JSON data model to a user, you’ll find that if your model was built correctly, your UI (and therefore your component structure) will map nicely.

 VDom让我们可以将Model到View的映射交出,而更专注于数据和数据结构本身,即是折腾数据和数据结构才是我们的主要工作。因此我们要设计出与View中组件结构对应的数据结构,然后将不符合该数据结构的数据做一系列转换,然后将数据交给React就好了。
 居上所述那么可以知道,数据结构就依赖View的结构,那么如何设计View的结构呢?是采用Top-down还是Bottom-up的方式呢?对于小型应用我们直接采用Top-down即可,对于大型应用则采用Bottom-up更合适。(根据过往经验将大规模的问题域拆分成多个小规模的问题域,然后对小问题域采用Top-down方式,若无法直接采用Top-down方式则继续拆分,然后将多个小问题域的值域组合即可得到大问题域的值域)
 无论是Top-down还是Bottom-up方式,都要将View构建为树结构(这很符合DOM结构嘛)。因此得到如下结构

FilterableProductTable
|_SearchBar
|_ProductTable
  |_ProductCategoryRow
  |_ProductRow

 而数据则从顶层View组件往下流动,各层提取各自数据进行渲染。

二、从静态非交互版本开始

It’s best to decouple these processes because building a static version requires a lot of typing and no thinking, and adding interactivity requires a lot of thinking and not a lot of typing.

 从设计(他人或自己)那得到设计稿或HTML模板,我们就可以开始着手重构模板、添加交互效果和填充业务逻辑和服务端交互等功能了。且慢,我们先不着急动手,而是要先分清工作步骤,才能有条不紊地包质保量工作哦!

目标:得到符合React规范的View结构

目标:得到最低标准的可交互的React应用

目标:补充业务逻辑,细化交互

目标:连接远程数据源,细化交互

(ns demo.core
  (:require [reagent.core :as re])

(def products [
  {:category "Sporting Goods", :price "$49.99", :stocked true, :name "Football"}
  {:category "Sporting Goods", :price "$9.99", :stocked true, :name "Baseball"}
  {:category "Sporting Goods", :price "$29.99", :stocked false, :name "Basketball"}
  {:category "Electronics", :price "$99.99", :stocked true, :name "iPod Touch"}
  {:category "Electronics", :price "$399.99", :stocked false, :name "iPhone 5"}
  {:category "Electronics", :price "$199.99", :stocked true, :name "Nexus 7"}
])


(declare 
         
         
         
         )

(declare get-rows)

(defn 
  [products]
  [:div
    []
    [ products]])

(defn 
  []
  [:form
    [:input {:placeholder "Search..."}]
    [:input {:type "checkbox"}]
    "Only show products in stock."])

(defn 
  [products]
  [:table
    [:thead
      [:tr
        [:th "Name"]
        [:th "Price"]]]
    [:tbody
      (get-rows products)]])

(defn assemble-rows
  [products]
   (reduce
    (fn [{:keys [cate] :as rows-info} product]
      (let [curr-cate (:category product)
            curr-rows (if (not= curr-cate cate)
                        (list ^{:key curr-cate}[ curr-cate])
                        (list))
            rows (cons ^{:key (:name product)} [ product] curr-rows)]
        (-> rows-info
          (assoc :cate curr-cate) ;; 更新cate值
          (update
            :rows
            (fn [o rows]
              (concat rows o))
            rows)))) ;; 更新rows值
    {:cate nil :rows "()}
    products))

(defn get-rows
  [products]
  (-> (assemble-rows products)
    :rows
    reverse))

(defn 
  [cate]
  [:tr
    [:td {:colSpan 2} cate]])

(defn 
  [product]
  [:tr
    [:td (when (:stocked product) {:style {:color "red"}})
      (:name product)]
    [:td (:price product)]])


 这一步我们并没有提供交互功能,因此只会用到prop传递数据,绝对不会用到state的。而交互的意思是,对View的操作会影响应用数据,从而刷新View。

三、追加交互代码

 交互实质上就是触发View状态变化,那么就必须提供一种容器来暂存当前View的状态,而这个在React就是state了。

(ns demo.core
  (:require [reagent.core :as re])

(def products [
  {:category "Sporting Goods", :price "$49.99", :stocked true, :name "Football"}
  {:category "Sporting Goods", :price "$9.99", :stocked true, :name "Baseball"}
  {:category "Sporting Goods", :price "$29.99", :stocked false, :name "Basketball"}
  {:category "Electronics", :price "$99.99", :stocked true, :name "iPod Touch"}
  {:category "Electronics", :price "$399.99", :stocked false, :name "iPhone 5"}
  {:category "Electronics", :price "$199.99", :stocked true, :name "Nexus 7"}
])


(declare 
         
         
         
         )

(declare get-rows
         validate-product)


(defn 
  [products]
  (let [search-text (re/atom "")
        stocked? (re/atom false)
        on-search-text-change #(reset! search-text (.. % -target -value))
        on-stocked?-change #(reset! stocked? (.. % -target -checked))]
    (fn []
      [:div
        [ on-search-text-change on-stocked?-change]
        [ (filter (partial validate-product @search-text @stocked?) products)]])))

(defn validate-product
  [search-text stocked? product]
  (and (if stocked? (:stocked product) true)
       (as-> search-text %
         (re-pattern (str "(?i)" %))
         (re-find % (:name product)))))

(defn 
  [on-search-text-change on-stocked?-change]
  [:form
    [:input {:placeholder "Search..."
             :onChange on-search-text-change}]
    [:input {:type "checkbox"
             :onChange on-stocked?-change}]
    "Only show products in stock."])

(defn 
  [products]
  [:table
    [:thead
      [:tr
        [:th "Name"]
        [:th "Price"]]]
    [:tbody
      (get-rows products)]])

(defn assemble-rows
  [products]
   (reduce
    (fn [{:keys [cate] :as rows-info} product]
      (let [curr-cate (:category product)
            curr-rows (if (not= curr-cate cate)
                        (list ^{:key curr-cate}[ curr-cate])
                        (list))
            rows (cons ^{:key (:name product)} [ product] curr-rows)]
        (-> rows-info
          (assoc :cate curr-cate) ;; 更新cate值
          (update
            :rows
            (fn [o rows]
              (concat rows o))
            rows)))) ;; 更新rows值
    {:cate nil :rows "()}
    products))

(defn get-rows
  [products]
  (-> (assemble-rows products)
    :rows
    reverse))

(defn 
  [cate]
  [:tr
    [:td {:colSpan 2} cate]])

(defn 
  [product]
  [:tr
    [:td (when (:stocked product) {:style {:color "red"}})
      (:name product)]
    [:td (:price product)]])

注意:reagent中使用state时,需要定义一个返回函数的高阶函数来实现。

(defn  [data]
  (let [local-state (re/atom nil)
        on-change #(reset! local-state (.. % -target -value))]
    (fn []
      [:div
        [:input {:onChange on-change}]
        [:span @local-state]])))

(re/render [ 1]
           (.querySelector js/document "#app"))
总结

 尊重原创,转载请注明转自:http://www.cnblogs.com/fsjohn... ^_^肥仔John

参考

https://reactjs.org/docs/thin...

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/89173.html

相关文章

  • 学习React系列2-[解读]Thinking in React

    摘要:扩展单一职责原则又称单一功能原则,面向对象五个基本原则之一。马丁表示此原则是基于汤姆狄马克和的著作中的内聚性原则发展出的。 [解读]Thinking in React 原文:http://facebook.github.io/react/docs/thinking-in-react.html 前言 Thought is the seed of action 这是放置在官方的QUICK ...

    tomorrowwu 评论0 收藏0
  • 【译】渲染Elements

    摘要:注不做翻译是中最小的构建部件。在里渲染让我们看一下在下面有在你文件中无处不在的标签我们会把这元素成为元素因为的所有东西都会放在这个元素里面。通过方法,我们能吧渲染到我们根节点上。更新被渲染的是不可变的。 下面是react官方文档的个人翻译,如有翻译错误,请多多指出原文地址:https://facebook.github.io/re...特别感谢Hevaen,同时也向豪大React群所有...

    LoftySoul 评论0 收藏0
  • Compress image using JavaScript directly from the

    You might be working on a project which has an image upload feature that takes images from the user and uploads it to your storage server. Once you have implemented it then you start thinking of optim...

    Eastboat 评论0 收藏0
  • 【Change Detection系列一】$digest 在Angular新版本中重生

    摘要:感谢您的阅读如果喜欢这篇文章请点赞。它对我意义重大,它能帮助其他人看到这篇文章。对于更高级的文章,你可以在或上跟随我。 I’ve worked with Angular.js for a few years and despite the widespread criticism I think this is a fantastic framework. I’ve started w...

    legendaryedu 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<