react案例->新聞移動客戶端--(react+redux+es6+webpack+es6的spa應用)


今天分享一個react應用,應在第一篇作品中說要做一個react+redux+xxx的應用。已經做完一部分,拿出來分享。github地址為:點我就可以咯~

這里實現了一個新聞移動站的spa。本來想寫pc端的,但是比較懶,而且因為主要是react的項目,關於css和布局的細節就是糊弄人的了。T.T,這里只說關於這個項目的js部分。

這里的功能很簡單,有一下幾點:

1,按”心“排序

當比上一個多了,就會排到前面。

2.評論部分

新聞的評論部分類似qq空間的評論

當然,也可以點擊新聞回復的哦。

=============================================

大家看到了,功能比較簡單,大家clone 項目下來,直接能用的,里面已經傳了我用webpack打包好的文件。

=============================================

bundle.js有3m+,這個完全是因為我加了很多庫進去,比如輪播圖的swiper等等,而且這些東西都是沒有壓縮過的。你壓縮完之后,會覺得react做移動端也可以的。

就不要再問我為什么不用rn做這個。。因為我不會T.T

=============================================

要看懂本文也需要一定的基礎,比如es6基礎,react和redux基礎。

=============================================

最后一點廢話,這個東西還沒有做完,只是一部分,接下來會用redux的router把它作為一個完全的spa,並且完善它的測試部分。大家期待吧~

=============================================(主文分界線)

好,接下來介紹我們的主角redux,不會的可以轉到我的另一篇博文:點此

redux,昨天花了一上午,竟然看完了它全部的源碼。跟你們說,它未壓縮的redux.js僅有600行。angular已經1w+行了。。。

主要的是很簡單,源碼一看就懂,而且redux完全是fp,也就是函數式編程,它內置了一些函數式編程的例子。運用fp的庫還有lodas和underscore。我將會寫另一篇介紹fp與redux的博文~~

分析代碼之前,先給出文件目錄:

這個目錄是官方example的目錄,我就直接拿來用了。webpack整理的文件在public中,bootstrap沒有在webpack中打包,項目中一般也用不到,其他的css和js文件都打包進去了。

其中,fonts是字體,dist存放了webpack打包后的js和css文件,public里面是輪播圖js文件和圖片文件。test是測試文件,現在還沒寫。因為不是tdd。。

剩下的actions存放的是redux的action文件。components存放的是react的組件,containers是redux如何封裝組件的配置文件。reducers是redux的reducer文件,store是創建store的配置文件。

webpack主入口是index.js 它里面是添加了一些應用需要的文件,比如import Swiper from "./public/js/swiper-3.3.1.min.js"和import "./public/js/swiper.min.css",還有main.css

import React from 'react'
import { render } from 'react-dom'
import { Provider } from 'react-redux'
import App from './containers/App'
import configureStore from './store/configureStore'
import "./dist/main.css";

import Swiper from "./public/js/swiper-3.3.1.min.js"
import "./public/js/swiper.min.css"

import 'react-bootstrap';
const store = configureStore();

render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
)

 

大家會看到這個項目跟上一個redux入門中的項目結構,甚至代碼都類似,因為就是從上一個代碼的基礎上改的,不明白可以看上一篇文章

主頁就不多說了,開始的頁面布局和引入css文件和打包之后的js文件。

主要說一下上面提到的功能。

首先是排序。排序的原理是什么?根據心排序,心的多少。

Box是那三個新聞,這里會根據children來循環遍歷出來,那個children是啥呢?是redux的store的counter數據排序之后的數據。

可以看到,我自己寫了一個數據排序,根據數據的val屬性排序,然后遍歷,就是完成了心的特性。

state={
  counter:{
    one:{id:1,counter:0,title:"xxxx" ,time:1},
    two:{id:2,counter:0,title:"xxxx", time:1},
    three:{id:3,counter:0,title:"xxxx",time:1}
  }  
}

 

這里的counter數據,counter是心的數量。排序就不說了,看代碼吧。

評論功能呢,有三個難點。1是點擊回復彈出input框,2是如何回復當前的評論。比如我回復的評論必須是這個評論,而不是下一個。3就是如何把評論內容顯示出來

最難的就是2了。這個還要設計一下store的數據結構。我用了一個小方法避免了添加id。這個以后再說。

1。點擊彈出input框。

寫react或者ng應用也不能用jquery的思想寫了。點擊彈出不能用click事件操作dom了。轉變為react的思想,props和state。於是,要這樣寫。

這是根據state渲染dom阿,然后點擊操作state。對了,react有個操作state的方法和初始化state的方法來着。叫getInitialState。

這里有個隱藏的坑,es6的寫法不能用getInitialState。於是我就像上面這樣寫。es6怎么寫state呢。於是我在下面的組件里又這樣寫:

這個state成為了這個組件的一個屬性,但是確實沒法用getInitialState了。不過可以用  this.setState({display: false})。這樣寫。來操作state

2,這個比較麻煩,首先看一下我設計的評論的store:

 var data=[
      [
         {
            text:"這里是評論1",
            huifu:["huifuxxxxxxxxxxxxx",'2xxxxxxxxxxxxxxxxxxxx','3xxxxxxxxxxxxxxxxx']
          },
         {
            text:"這里是評論1.2",
            huifu:["huifuxxxxxxxxxxxxx"]
          }
      ],[
          {
            text:"這里是評論2",
            huifu:["huifuxxxxxxxxxxxxx",'2xxxxxxxxxxxxxxxxxxxx','3xxxxxxxxxxxxxxxxx']
          }
      ],[
          {
            text:"這里是評論3",
            huifu:["huifuxxxxxxxxxxxxx",'2xxxxxxxxxxxxxxxxxxxx','3xxxxxxxxxxxxxxxxx']
          }
        ]  
    ]

 

這是整個評論的部分,包括回復。如果你要添加評論就在data[文章id].push(一樣結構的評論數據),回復也是直接添加數據。

問題來了,那我們怎么保證這個回復是這個評論的呢,比如我回復123,你怎么知道是評論1的還是評論1.2(代碼中的評論1.2)的呢?

這里有個小方法。我的評論框是獨立於遍歷之外的,就是說,你不能給他傳一個文章id。那怎么辦?

它取本組件的state。然后評論操作state。就是這樣。評論在打開一個回復input的時候,傳入本評論的id,改變本組件的state,然后就不管它的事了。

這里的小方法避免了每個評論都加一個id屬性,而是一個評論數組,用的就是數組map方法的keys--

keys,是數組的鍵,也就是0,1,2,3用這個當作文章id。可以的!

注意這里你循環出子組件的時候,必須給他一個key的props,由於react的diff算法,必須保證子組件的位置和渲染正確,傳一個key,那正好,沒有id我就用這里的keys傳了:

這樣就沒問題了。

3。顯示的問題,就是上面的遍歷的問題了,輸入框的顯示就是組件自身state的問題了。

看組件是如何顯示:

{
          data[newId].map(function (items,keys) {
            return (
              <div key={keys} className="body-text">
                <h5>游客: <a onClick={that.handleClick.bind(that,keys)}>回復</a> <a href="">轉發</a></h5>
                <p>{items.text}</p>
                  {
                    items.huifu.map(function (item,keyss) {
                    return ( <div key={keyss}>
                                <h5 className="huifu-user">游客回復:<a onClick={that.handleClick.bind(that,keys)} >回復</a> <a href="">轉發</a></h5>
                                <p className="huifu">{item}</p>
                            </div>
                      )
                  }) 
                  } 
                  
              </div>
            )
          })
}

 

data數組是我們的數據,上面給了格式。循環遍歷。

主要的是回復框的顯示,操作state,這里給了他一個display屬性,但是他不是true和false,而是false和keys,這個keys就是當前評論的id,這個id成為遍歷的keys屬性。

1的時候那張圖就是根據display顯示,這就不多說了。

react的優勢

其實這么多文件夾,這么多js文件,用js寫,邏輯又清楚又快,而用react寫還帶有學習成本。為啥用react寫。拋開趕前端潮流不說。react的優勢在於維護起來爽翻天。

js寫這些邏輯剛開始寫完是很清晰,我覺得過一段時間以后,想維護就很難了吧。還有一點,我想改數據的時候直接修改state,想加一個新聞就復用我的組件,根據react的虛擬dom的算法,也是不慢的。

用redux的優勢就是等這個新聞項目做大,一堆一堆的js代碼,如果有redux維護那就簡單多了。因為純函數的關系,redux的測試也是非常好寫的。redux壓縮前600行代碼,加上react也是輕量級框架,這點也是很受人好評的。

用這些框架都是類似,都是數據流,他們讓你用數據控制頁面。ng也是如此,操作僅僅是修改數據,而不會頻繁的操作dom。這是框架的優點。react在此基礎上做到的低耦合,單項數據流。經常聽到有react維護比較爽的呼聲。-。-好維護,低耦合,輕量級。正好符合現在前端對框架的要求。於是好多人選擇了react。還有JSX的寫法也是比較爽的0.0react背后還有facebook撐腰。嗯,必火。。。

關於本新聞端的問題

問題在於這里:三篇新聞,每一篇當作一個事件來處理,於是--

export const LOVE_COUNTER_ONE = 'LOVE_COUNTER_ONE'
export const LOVE_COUNTER_TWO = 'LOVE_COUNTER_TWO'
export const LOVE_COUNTER_THREE = 'LOVE_COUNTER_THREE'

export const TXST_COUNTER_ONE = 'TXST_COUNTER_ONE'
export const TXST_COUNTER_TWO = 'TXST_COUNTER_TWO'
export const TXST_COUNTER_THREE = 'TXST_COUNTER_THREE'


export const HF_COUNTER_ONE = 'HF_COUNTER_ONE'
export const HF_COUNTER_TWO = 'HF_COUNTER_TWO'
export const HF_COUNTER_THREE = 'HF_COUNTER_THREE'

 

有人會說,如果100篇新聞,豈不是寫n多的action?

當初在寫的時候,想的是作為新聞的主頁,我只放3個新聞,后面加一個更多,點開打開新聞列表頁。當然,如果把這個作為新聞列表頁那確實要寫n多的xxx。。

那當這個新聞端改為新聞列表頁怎么寫呢?

首先構建一個store,把新聞id,新聞內容寫進去。當然也可以組合它的評論和回復,不組合,通過id關聯也是可以的。。(怎么感覺像數據庫了0.0)

那這里的action就變了,改為TXST_COUNTER_NEWS,當然,這個action需要傳文章的id。這個不麻煩。

reducer這里就根據文章id操作store,如果不組合評論和回復,那么,這個新聞store只需要刪減新聞內容。注意新聞刪了,對應的評論和回復也要刪除。

組合評論和回復呢,那么也是同樣,評論和回復的內容留給游客們去添加。

組件里就注意了,因為新聞組合了,那么上面就需要傳一個新聞id,智能組件根據id傳方法與數據給呆滯組件。。原理是這樣。大家可以試着修改一下,自己動手能學到很多東西。

 還有就是webpack打包文件太大怎么辦。我這個文件3m,本地加載都要143ms,這段時間3張下載完的圖片並排,很丑。。

這里的減少體積大小的方法就是關閉source map,devTool也關了。重復的文件打包成common.js,還有就是壓縮文件- -,當然這些都是生成環境下了。

這里測試了一下(未傳到github),未壓縮前可以弄到864k,當然公共庫,比如Swiper可以用cdn,壓縮完后這樣一個數量級的應用就可以用在移動端了。

這里的操作是-刪除沒用的react-bootstrap,刪除重復的style-loader,刪除source-map及webpack hot replace及一些webpack常用插件。

還有一點,把文件作為chunk按需加載,這個貌似這個場景下還是不需要的。

需要注意的就這么多,接下來會添加路由功能,使他真正的成為spa的應用。當然,大神的標志之一---會不會寫測試也會一並補齊。敬請期待~

最新更新:2016-04-25    單元測試已經補齊哦~ 博文地址:點我~    github地址:點我~

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM