真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

React服務(wù)器端渲染怎么用-創(chuàng)新互聯(lián)

這篇文章給大家分享的是有關(guān)React服務(wù)器端渲染怎么用的內(nèi)容。小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,一起跟隨小編過來看看吧。

項(xiàng)城ssl適用于網(wǎng)站、小程序/APP、API接口等需要進(jìn)行數(shù)據(jù)傳輸應(yīng)用場景,ssl證書未來市場廣闊!成為創(chuàng)新互聯(lián)的ssl證書銷售渠道,可以享受市場價(jià)格4-6折優(yōu)惠!如果有意向歡迎電話聯(lián)系或者加微信:13518219792(備注:SSL證書合作)期待與您的合作!

React 提供了兩個(gè)方法 renderToString 和 renderToStaticMarkup 用來將組件(Virtual DOM)輸出成 HTML 字符串,這是 React 服務(wù)器端渲染的基礎(chǔ),它移除了服務(wù)器端對于瀏覽器環(huán)境的依賴,所以讓服務(wù)器端渲染變成了一件有吸引力的事情。

服務(wù)器端渲染除了要解決對瀏覽器環(huán)境的依賴,還要解決兩個(gè)問題:

  1. 前后端可以共享代碼

  2. 前后端路由可以統(tǒng)一處理

React 生態(tài)提供了很多選擇方案,這里我們選用 Redux 和 react-router 來做說明。

Redux

Redux 提供了一套類似 Flux 的單向數(shù)據(jù)流,整個(gè)應(yīng)用只維護(hù)一個(gè) Store,以及面向函數(shù)式的特性讓它對服務(wù)器端渲染支持很友好。

2 分鐘了解 Redux 是如何運(yùn)作的

關(guān)于 Store:

  1. 整個(gè)應(yīng)用只有一個(gè)唯一的 Store

  2. Store 對應(yīng)的狀態(tài)樹(State),由調(diào)用一個(gè) reducer 函數(shù)(root reducer)生成

  3. 狀態(tài)樹上的每個(gè)字段都可以進(jìn)一步由不同的 reducer 函數(shù)生成

  4. Store 包含了幾個(gè)方法比如 dispatch, getState 來處理數(shù)據(jù)流

  5. Store 的狀態(tài)樹只能由 dispatch(action) 來觸發(fā)更改

Redux 的數(shù)據(jù)流:

  1. action 是一個(gè)包含 { type, payload } 的對象

  2. reducer 函數(shù)通過 store.dispatch(action) 觸發(fā)

  3. reducer 函數(shù)接受 (state, action) 兩個(gè)參數(shù),返回一個(gè)新的 state

  4. reducer 函數(shù)判斷 action.type 然后處理對應(yīng)的 action.payload 數(shù)據(jù)來更新狀態(tài)樹

所以對于整個(gè)應(yīng)用來說,一個(gè) Store 就對應(yīng)一個(gè) UI 快照,服務(wù)器端渲染就簡化成了在服務(wù)器端初始化 Store,將 Store 傳入應(yīng)用的根組件,針對根組件調(diào)用 renderToString 就將整個(gè)應(yīng)用輸出成包含了初始化數(shù)據(jù)的 HTML。

react-router

react-router 通過一種聲明式的方式匹配不同路由決定在頁面上展示不同的組件,并且通過 props 將路由信息傳遞給組件使用,所以只要路由變更,props 就會變化,觸發(fā)組件 re-render。

假設(shè)有一個(gè)很簡單的應(yīng)用,只有兩個(gè)頁面,一個(gè)列表頁 /list 和一個(gè)詳情頁 /item/:id,點(diǎn)擊列表上的條目進(jìn)入詳情頁。

可以這樣定義路由,./routes.js

import React from 'react';
import { Route } from 'react-router';
import { List, Item } from './components';

// 無狀態(tài)(stateless)組件,一個(gè)簡單的容器,react-router 會根據(jù) route
// 規(guī)則匹配到的組件作為 `props.children` 傳入
const Container = (props) => {
 return (
  
{props.children}
 ); }; // route 規(guī)則: // - `/list` 顯示 `List` 組件 // - `/item/:id` 顯示 `Item` 組件 const routes = (           ); export default routes;

從這里開始,我們通過這個(gè)非常簡單的應(yīng)用來解釋實(shí)現(xiàn)服務(wù)器端渲染前后端涉及的一些細(xì)節(jié)問題。

Reducer

Store 是由 reducer 產(chǎn)生的,所以 reducer 實(shí)際上反映了 Store 的狀態(tài)樹結(jié)構(gòu)

./reducers/index.js

import listReducer from './list';
import itemReducer from './item';

export default function rootReducer(state = {}, action) {
 return {
  list: listReducer(state.list, action),
  item: itemReducer(state.item, action)
 };
}

rootReducer 的 state 參數(shù)就是整個(gè) Store 的狀態(tài)樹,狀態(tài)樹下的每個(gè)字段對應(yīng)也可以有自己的reducer,所以這里引入了 listReducer 和 itemReducer,可以看到這兩個(gè) reducer的 state 參數(shù)就只是整個(gè)狀態(tài)樹上對應(yīng)的 list 和 item 字段。

具體到 ./reducers/list.js

const initialState = [];

export default function listReducer(state = initialState, action) {
 switch(action.type) {
 case 'FETCH_LIST_SUCCESS': return [...action.payload];
 default: return state;
 }
}

list 就是一個(gè)包含 items 的簡單數(shù)組,可能類似這種結(jié)構(gòu):[{ id: 0, name: 'first item'}, {id: 1, name: 'second item'}],從 'FETCH_LIST_SUCCESS' 的 action.payload 獲得。

然后是 ./reducers/item.js,處理獲取到的 item 數(shù)據(jù)

const initialState = {};

export default function listReducer(state = initialState, action) {
 switch(action.type) {
 case 'FETCH_ITEM_SUCCESS': return [...action.payload];
 default: return state;
 }
}

Action

對應(yīng)的應(yīng)該要有兩個(gè) action 來獲取 list 和 item,觸發(fā) reducer 更改 Store,這里我們定義 fetchList 和 fetchItem 兩個(gè) action。

./actions/index.js

import fetch from 'isomorphic-fetch';

export function fetchList() {
 return (dispatch) => {
  return fetch('/api/list')
    .then(res => res.json())
    .then(json => dispatch({ type: 'FETCH_LIST_SUCCESS', payload: json }));
 }
}

export function fetchItem(id) {
 return (dispatch) => {
  if (!id) return Promise.resolve();
  return fetch(`/api/item/${id}`)
    .then(res => res.json())
    .then(json => dispatch({ type: 'FETCH_ITEM_SUCCESS', payload: json }));
 }
}

isomorphic-fetch 是一個(gè)前后端通用的 Ajax 實(shí)現(xiàn),前后端要共享代碼這點(diǎn)很重要。

另外因?yàn)樯婕暗疆惒秸埱螅@里的 action 用到了 thunk,也就是函數(shù),redux 通過 thunk-middleware 來處理這類 action,把函數(shù)當(dāng)作普通的 action dispatch 就好了,比如 dispatch(fetchList())

Store

我們用一個(gè)獨(dú)立的 ./store.js,配置(比如 Apply Middleware)生成 Store

import { createStore } from 'redux';
import rootReducer from './reducers';

// Apply middleware here
// ...

export default function configureStore(initialState) {
 const store = createStore(rootReducer, initialState);
 return store;
}

react-redux

接下來實(shí)現(xiàn) , 組件,然后把 redux 和 react 組件關(guān)聯(lián)起來,具體細(xì)節(jié)參見 react-redux

./app.js

import React from 'react';
import { render } from 'react-dom';
import { Router } from 'react-router';
import createBrowserHistory from 'history/lib/createBrowserHistory';
import { Provider } from 'react-redux';
import routes from './routes';
import configureStore from './store';

// `__INITIAL_STATE__` 來自服務(wù)器端渲染,下一部分細(xì)說
const initialState = window.__INITIAL_STATE__;
const store = configureStore(initialState);
const Root = (props) => {
 return (
  
              {routes}            
 ); } render(, document.getElementById('root'));

至此,客戶端部分結(jié)束。

Server Rendering

接下來的服務(wù)器端就比較簡單了,獲取數(shù)據(jù)可以調(diào)用 action,routes 在服務(wù)器端的處理參考 react-router server rendering,在服務(wù)器端用一個(gè) match 方法將拿到的 request url 匹配到我們之前定義的 routes,解析成和客戶端一致的 props 對象傳遞給組件。

./server.js

import express from 'express';
import React from 'react';
import { renderToString } from 'react-dom/server';
import { RoutingContext, match } from 'react-router';
import { Provider } from 'react-redux';
import routes from './routes';
import configureStore from './store';

const app = express();

function renderFullPage(html, initialState) {
 return `
  
  
  
   
  
  
   
    
     ${html}     
   
               `; } app.use((req, res) => {  match({ routes, location: req.url }, (err, redirectLocation, renderProps) => {   if (err) {    res.status(500).end(`Internal Server Error ${err}`);   } else if (redirectLocation) {    res.redirect(redirectLocation.pathname + redirectLocation.search);   } else if (renderProps) {    const store = configureStore();    const state = store.getState();    Promise.all([     store.dispatch(fetchList()),     store.dispatch(fetchItem(renderProps.params.id))    ])    .then(() => {     const html = renderToString(                        );     res.end(renderFullPage(html, store.getState()));    });   } else {    res.status(404).end('Not found');   }  }); });

服務(wù)器端渲染部分可以直接通過共用客戶端 store.dispatch(action) 來統(tǒng)一獲取 Store 數(shù)據(jù)。另外注意 renderFullPage 生成的頁面 HTML 在 React 組件 mount 的部分(

),前后端的 HTML 結(jié)構(gòu)應(yīng)該是一致的。然后要把 store 的狀態(tài)樹寫入一個(gè)全局變量(__INITIAL_STATE__),這樣客戶端初始化 render 的時(shí)候能夠校驗(yàn)服務(wù)器生成的 HTML 結(jié)構(gòu),并且同步到初始化狀態(tài),然后整個(gè)頁面被客戶端接管。

最后關(guān)于頁面內(nèi)鏈接跳轉(zhuǎn)如何處理?

react-router 提供了一個(gè) 組件用來替代 標(biāo)簽,它負(fù)責(zé)管理瀏覽器 history,從而不是每次點(diǎn)擊鏈接都去請求服務(wù)器,然后可以通過綁定 onClick 事件來作其他處理。

比如在 /list 頁面,對于每一個(gè) item 都會用 綁定一個(gè) route url:/item/:id,并且綁定 onClick 去觸發(fā) dispatch(fetchItem(id)) 獲取數(shù)據(jù),顯示詳情頁內(nèi)容。

感謝各位的閱讀!關(guān)于“React服務(wù)器端渲染怎么用”這篇文章就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,讓大家可以學(xué)到更多知識,如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到吧!

另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場景需求。


分享標(biāo)題:React服務(wù)器端渲染怎么用-創(chuàng)新互聯(lián)
網(wǎng)站鏈接:http://weahome.cn/article/dopgsh.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部