react項目學(xué)習(xí)筆記-總結(jié)-感悟

SPA(Single Page Application)

單頁面應(yīng)用,就是只有一張Web頁面的應(yīng)用较鼓。單頁應(yīng)用程序 (SPA) 是加載單個HTML 頁面并在用戶與應(yīng)用程序交互時動態(tài)更新該頁面的Web應(yīng)用程序措伐。

單頁面應(yīng)用的優(yōu)點

  1. 最大的好處是用戶體驗晦雨,對于內(nèi)容的改動不需要加載整個頁面巷嚣。
  2. 數(shù)據(jù)層和UI的分離克胳,可以重新編寫一個原生的移動設(shè)備應(yīng)用程序而不用大動干戈(同一套后端程序代碼中狂,不用修改就可以用于Web界面掸宛、手機、平板等多種客戶端)待牵。
  3. 高效其屏。它對服務(wù)器壓力很小,消耗更少的帶寬缨该,能夠與面向服務(wù)的架構(gòu)更好地結(jié)合偎行。

單頁面應(yīng)用的缺點

  1. 不利于SEO
  2. 初次加載耗時增多
  3. 導(dǎo)航不可用;前進贰拿、后退蛤袒、地址欄等,需要程序進行管理膨更;
    書簽妙真,需要程序來提供支持;

應(yīng)用場景

那么單頁應(yīng)用的應(yīng)用如何呢荚守?看了一些資料珍德,總覺出來單頁面應(yīng)用有兩個硬傷:
首屏加載慢(大量js導(dǎo)致首屏加載慢)、seo不友好
如何應(yīng)用SPA或者是否應(yīng)用SPA矗漾,大概需要考慮以下這幾點:

  1. 交互體驗
    不同的應(yīng)用面對不同人群锈候,會有不同的交互體驗需求。
  2. 工程代價
    大型網(wǎng)站轉(zhuǎn)spa會有很大的代價敞贡。
  3. 容錯問題
    SPA所有腳本都加進來泵琳,如果出現(xiàn)一個JS錯誤,那很可能整個網(wǎng)站就掛掉了,風(fēng)險很大获列。
  4. 是否必要
    簡單呈現(xiàn)內(nèi)容的網(wǎng)站谷市,沒有必要用spa。增加了開發(fā)和調(diào)試的復(fù)雜性击孩,但是除了效果更酷炫點迫悠,沒有多少實用價值。
  5. 是否需要兼容低版本的ie瀏覽器

SPA總結(jié)

綜合了解了這種SPA單頁應(yīng)用和傳統(tǒng)的多頁面應(yīng)用溯壶,在以后的開發(fā)中及皂,我可能會采取單頁和多頁相結(jié)合的方式甫男,該跳轉(zhuǎn)的地方還是跳轉(zhuǎn)且改,結(jié)合單頁模式的用戶體驗優(yōu)點,將用戶體驗發(fā)揮到極致板驳,因為我覺得用戶體驗是最重要的東西之一又跛。

項目安裝的模塊解釋

開發(fā)依賴模塊:

  • autoprefixer:postcss-loader的一個插件,使用一個數(shù)據(jù)庫根據(jù)當(dāng)前瀏覽器的普及度以及屬性支持自動給你的css添加前綴前綴:詳情點這里
  • babel-core:babel轉(zhuǎn)碼的核心,必須安裝bable詳情點這里(阮一峰)
  • babel-loader:babel加載器若治,配置babel編譯必備
  • babel-plugin-add-module-exports:babel對export default{}支持不好慨蓝,不想寫成module.exports就需要安裝點這里
  • babel-plugin-react-transform:代替react-hot-loader的插件,是基于Babel Plugin的端幼。這是一個基本的架子礼烈,要實現(xiàn)熱替換還要安裝其他插件。
  • react-transform-hmr:安裝這個才能實現(xiàn)熱替換的功能婆跑。
  • babel-preset-es2015:babel轉(zhuǎn)譯預(yù)設(shè)規(guī)則(轉(zhuǎn)es5)
  • babel-preset-react:babel轉(zhuǎn)譯預(yù)設(shè)規(guī)則(react的jsx)
  • css-loader:允許引入css文件
  • style-loader:為了在html中以style的方式嵌入css
  • postcss-loader:一個插件平臺此熬,這里只要用其autoprefixer功能
  • eslint-loader:代碼規(guī)范檢查點這里
  • extract-text-webpack-plugin:分離css文件
  • url-loader:圖片與字體加載器,file-loader的上層封裝,依賴file-loader
  • file-loader:圖片與字體加載器
  • html-webpack-plugin:這樣可以將輸出的文件名自動注入到html中,不用我們自己手寫
  • json-loader:處理json文件
  • koa:node框架
  • koa-router:koa路由
  • less:less編譯css
  • less-loader:less加載器
  • open-browser-webpack-plugin:打包完成自動打開瀏覽器的插件
  • webpack:一代神器
  • webpack-dev-server:一個小型的Node.js Express服務(wù)器滑进,可實現(xiàn)代碼修改自動看這里

上線依賴模塊:

  • es6-promise:使用fetch時為了兼容老版本需要安裝
  • immutable:react性能優(yōu)化犀忱,需要學(xué)習(xí)新的APIimmutable
  • react:
  • react-addons-css-transition-group:實現(xiàn)組件出現(xiàn)與消失的css3過渡動畫官方地址
  • react-addons-pure-render-mixin:用以替換shouldComponentUpdate,優(yōu)化性能
  • react-dom:
  • react-redux:
  • react-router:
  • react-swipe:輪播圖插件,引入swipe-js-iso,創(chuàng)建reat組件
  • swipe-js-iso:基于swipe.js的一個Pull Request
  • redux:
  • whatwg-fetch:fetch

webpack配置詳解

resolve

定義了解析模塊路徑時的配置扶关,常用的就是extensions;可以用來指定模塊的后綴阴汇,這樣在引入模塊時就不需要寫后綴

resolve:{extensions:['', '.js','.jsx']}

postcss

在加載css/less時,用到postcss,主要使用autoprefixer功能节槐,能自動加css3的瀏覽器前綴搀庶;

postcss:[
    require('autoprefixer)//調(diào)用autoprefixer插件,例如display:flex 針對不同品牌及版本的瀏覽器hack前綴
]

html-webpack-plugin

html模板插件

var HtmlWebpackPlugin = require('html-webpack-plugin');
plugins:[
    new HtmlWebpackPlugin({template:'./app/index.html'})
]

webpack.HotModuleReplacementPlugin

var webpack = require('webpack');
plugins:[
    new webpack.HotModuleReplacementPlugin()
]

看這里

open-browser-webpack-plugin

var OpenBrowserPlugin = require('open-browser-webpack-plugin');
plugins:[
    new OpenBrowserPlugin({url:'http://localhost:8080'})
]

DefinePlugin

可在業(yè)務(wù)js代碼中使用 DEV 判斷是否是dev模式(dev模式下可以提示錯誤铜异、測試報告等, production模式不提示,在package.json配置的dev腳本命令中定義了NODE_ENV的值哥倔,所以這里可以獲取到,也可以直接寫'true')

var webpack = require('webpack');
plugins:[
    new webpack.DefinePlugin({__DEV__:JSON.stringify(JSON.parse((process.env.NODE_ENV == 'dev') || 'false'))})
]

webpack-dev-server 代理

devServer: {
        proxy: {
          // 凡是 `/api` 開頭的 http 請求熙掺,都會被代理到 localhost:3000 上未斑,由 koa 提供 mock 數(shù)據(jù)。
          // koa 代碼在 ./mock 目錄中币绩,啟動命令為 npm run mock
          '/api': {
            target: 'http://localhost:3000',
            secure: false
          }
        },
        contentBase: "./public", //本地服務(wù)器所加載的頁面所在的目錄
        colors: true, //終端中輸出結(jié)果為彩色
        historyApiFallback: true, //不跳轉(zhuǎn)
        inline: true, //實時刷新
        hot: true  // 使用熱加載插件 HotModuleReplacementPlugin
    }

ExtractTextPlugin

webpack.production.config中配置蜡秽,實現(xiàn)上線css與js代碼分離

var ExtractTextPlugin = require('extract-text-webpack-plugin');
loaders: [
      { test: /\.less$/, exclude: /node_modules/, loader: ExtractTextPlugin.extract('style', 'css!postcss!less') },
      { test: /\.css$/, exclude: /node_modules/, loader: ExtractTextPlugin.extract('style', 'css!postcss') }
    ]
plugins:[
    new ExtractTextPlugin('[name].[chunkhash:8].css')
]

vender

entry: {
    app: path.resolve(__dirname, 'app/index.jsx'),
    // 將 第三方依賴 單獨打包
    vendor: [
      'react',
      'react-dom',
      'react-redux',
      'react-router',
      'redux',
      'es6-promise',
      'whatwg-fetch',
      'immutable'
    ]
  }
output: {
    path: __dirname + "/build",
    filename: "[name].[chunkhash:8].js",
    publicPath: '/'
  }
 plugins:[
    //提供公共代碼
     new webpack.optimize.CommonsChunkPlugin({
           name: 'vendor',
           filename: '[name].[chunkhash:8].js'
         })
 ]

import React from 'react'引用過程府阀?

npm 安裝的 react 的物理文件是存放在 ./node_modules/react中的,打開./node_modules/react/package.json找到"main": "react.js",芽突,這里的main即指定了入口文件试浙,即./node_modules/react/react.js這個文件。

react開發(fā)中的代碼分離

  • page層:按頁面拆分田巴,每個頁面有一個主頁面index.jsx
  • subPage層:對于復(fù)雜頁面壹哺,要將一個頁面拆封成多個子頁,不復(fù)雜的頁面只寫在index.jsx里即可
  • component層:只用來展示數(shù)據(jù)的組件,對于不同頁面內(nèi)相同的組件箩朴,寫在component層以便復(fù)用

react生命周期

組件在初始化的時候,會觸發(fā)5個鉤子函數(shù):

  1. getDefaultProps()
    設(shè)置默認的props埠居,也可以用dufaultProps設(shè)置組件的默認屬性拐格。

  2. getInitialState()
    在使用es6的class語法時是沒有這個鉤子函數(shù)的捏浊,可以直接在constructor中定義this.state金踪。此時可以訪問this.props。

  3. componentWillMount()
    組件初始化時只調(diào)用靶瘸,以后組件更新不調(diào)用屋剑,整個生命周期只調(diào)用一次唉匾,此時可以修改state。

  4. render()
    react最重要的步驟,創(chuàng)建虛擬dom逮诲,進行diff算法裆甩,更新dom樹都在此進行嗤栓。此時就不能更改state了叨叙。

  5. componentDidMount()
    組件渲染之后調(diào)用,可以通過this.getDOMNode()獲取和操作dom節(jié)點钮呀,只調(diào)用一次。

更新時觸發(fā)的5個鉤子函數(shù):

  1. componentWillReceivePorps(nextProps)
    組件初始化時不調(diào)用蚂四,組件接受新的props時調(diào)用田度。

  2. shouldComponentUpdate(nextProps, nextState)
    react性能優(yōu)化非常重要的一環(huán)。組件接受新的state或者props時調(diào)用奸笤,我們可以設(shè)置在此對比前后兩個props和state是否相同,如果相同則返回false阻止更新,因為相同的屬性狀態(tài)一定會生成相同的dom樹扣癣,這樣就不需要創(chuàng)造新的dom樹和舊的dom樹進行diff算法對比,節(jié)省大量性能,尤其是在dom結(jié)構(gòu)復(fù)雜的時候莱衩。不過調(diào)用this.forceUpdate會跳過此步驟。

  3. componentWillUpdate(nextProps, nextState)
    組件初始化時不調(diào)用,只有在組件將要更新時才調(diào)用勒极,此時可以修改state

  4. render()

  5. componentDidUpdate()
    組件初始化時不調(diào)用,組件更新完成后調(diào)用絮短,此時可以獲取dom節(jié)點。
    還有一個卸載鉤子函數(shù)

  6. componentWillUnmount()
    組件將要卸載時調(diào)用,一些事件監(jiān)聽和定時器需要在此時清除奖磁。

以上可以看出來react總共有10個周期函數(shù)(render重復(fù)一次)稠腊,這個10個函數(shù)可以滿足我們所有對組件操作的需求褐啡,利用的好可以提高開發(fā)效率和組件性能低飒。

常用的生命周期在項目中怎么用到?

  • comopentDidMount
    組件第一次加載時渲染loading組件,一般在此獲取網(wǎng)絡(luò)數(shù)據(jù)端仰,將數(shù)據(jù)賦值給狀態(tài),改變狀態(tài)重新渲染頁面。實際開始項目開發(fā)時,會經(jīng)常用到苍碟。
  • shouldComponentUpdate
    主要用于性能優(yōu)化抒钱,React 的性能優(yōu)化也是一個很重要的話題。
  • componentDidUpdate
    組件更新了之后觸發(fā)的事件,一般用于清空并更新數(shù)據(jù)。實際開始項目開發(fā)時,會經(jīng)常用到。
  • componentWillUnmount
    組件在銷毀之前觸發(fā)的事件,一般用戶存儲一些特殊信息,以及清理setTimeout事件等趴捅。

react性能優(yōu)化

  • 介紹PureComponent
    點這里
  • 性能檢測,檢測優(yōu)化結(jié)果
    npm i react-addons-perf --save
// 性能測試 
import Perf from 'react-addons-perf'; 
if (__DEV__) { window.Perf = Perf }

運行程序猎拨。在操作之前先運行Perf.start()開始檢測国觉,然后進行若干操作,運行Perf.stop停止檢測,然后再運行Perf.printWasted()即可打印出浪費性能的組件列表。在項目開發(fā)過程中蹂风,要經(jīng)常使用檢測工具來看看性能是否正常任内。

  • PureRenderMixin 優(yōu)化
    React 最基本的優(yōu)化方式
    組件中的props和state一旦變化會導(dǎo)致組件重新更新并渲染越除,但是如果props和state沒有變化也的觸發(fā)更新了(這種情況確實存在狼渊,比如調(diào)用setState方法米苹,但狀態(tài)并沒有改變)良瞧,這就導(dǎo)致了無效渲染
import React from 'react' ;
import PureRenderMixin from 'react-addons-pure-render-mixin' ;
class List extends React.Component { 
    constructor(props, context) { 
        super(props, context); 
        this.shouldComponentUpdate = PureRenderMixin.shouldComponentUpdate.bind(this); 
    } 
    //...
}

重寫組件的shouldComponentUpdate函數(shù),在每次更新之前判斷props和state亏较,如果有變化則返回true莺褒,無變化則返回false。
因此雪情,我們在開發(fā)過程中遵岩,在每個 React 組件中都盡量使用PureRenderMixin

  • Immutable.js 優(yōu)化
    React 的終極優(yōu)化是使用 Immutable.js 來處理數(shù)據(jù),Immutable 實現(xiàn)了 js 中不可變數(shù)據(jù)的概念(可以去查一下何為“不可變數(shù)據(jù)”)巡通。
    但是也不是所有的場景都適合用它尘执,當(dāng)我們組件的props和state中的數(shù)據(jù)結(jié)構(gòu)層次不深(例如普通的數(shù)組、對象等)的時候宴凉,就沒必要用它誊锭。但是當(dāng)數(shù)據(jù)結(jié)構(gòu)層次很深(例如obj.x.y.a.b = 10這種),你就得考慮使用了弥锄。
    之所以不輕易使用是丧靡,Immutable 定義了一種新的操作數(shù)據(jù)的語法,如下籽暇。和我們平時操作 js 數(shù)據(jù)完全不一樣温治,而且每個地方都得這么用,學(xué)習(xí)成本高戒悠、易遺漏熬荆,風(fēng)險很高。
var map1 = Immutable.Map({a:1, b:2, c:3}); 
var map2 = map1.set('b', 50);
 map1.get('b'); // 2 
 map2.get('b'); // 50

因此绸狐,建議優(yōu)化還是要從設(shè)計著手卤恳,盡量把數(shù)據(jù)結(jié)構(gòu)設(shè)計的扁平一些累盗,這樣既有助于優(yōu)化系統(tǒng)性能,又減少了開發(fā)復(fù)雜度和開發(fā)成本突琳。

react-router

注意:react-router4.0及以上版本語法有重大改變若债,老語法會報錯

 <Router history={hashHistory}>
      <Route path="/" component={App}>
        <IndexRoute component={Home}></IndexRoute>
        <Route path="city" component={City}></Route>
        <Route path='/Login(/:router)' component={Login}/>
        <Route path="user" component={User}></Route>
        <Route path="search/:category(/:keyword)" component={Search}></Route>
        <Route path="detail/:id" component={Detail}></Route>
        <Route path="*" component={NotFound}></Route>
      </Route>
    </Router>

目錄結(jié)構(gòu)

文件結(jié)構(gòu):

  • 入口文件,源碼文件夾app目錄下的index.js
    需要用redux傳遞信息的組件用Provider包住
const store = configureStore();
render(
  <Provider store={store}>
    <Hello/>
  </Provider>,document.querySelector('#app')
);
  • constants 常量文件夾
    定義了action的type的常量本今,方便修改復(fù)用
export const USERINFO_LOGIN='USERINFO_LOGIN';
export const UPDATE_CITY='UPDATE_CITY';
  • components 木偶組件文件夾
    負責(zé)渲染視圖
  • store文件夾
    創(chuàng)建store的函數(shù)拆座,需要引用reducers目錄內(nèi)的rootReducer
  • reducers文件夾
    reducers目錄下有index.js入口文件,可用combineReducers方法引用多個規(guī)則
import {combineReducers} from 'redux';
import userinfo from './userinfo';
import userinfo2 from './userinfo';
const rootReducer = combineReducers({userinfo,userinfo2});
export default rootReducer;
  • actions 文件夾
    存放派發(fā)方法
import * as actionTypes from '../constants/userinfo';
  export function login(data) {
    return {type:actionTypes.USERINFO_LOGIN,data}
  }
  export function updateCity(data) {
    return {type: actionTypes.UPDATE_CITYNAME, data}
  }
  • containers 頁面文件夾
    引入constants冠息,引入connect方法和bindActionCreators方法:
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import * as userinfoActions from '../actions/userinfo';

connect方法最后需要把組件包裝一下再輸出挪凑,目的是將派發(fā)后的狀態(tài)(userinfo)以及派發(fā)時的actions(userinfoActions)當(dāng)作組件的props傳遞給組件,userinfo是狀態(tài)數(shù)據(jù)逛艰,組件根據(jù)userinfo渲染視圖躏碳,userinfoActions是觸發(fā)狀態(tài)改變的方法,讓組件某事件綁定該方法后就可以有改變狀態(tài)的能力:

function mapStateToProps(state) {//一個自定義函數(shù)散怖,最為connect方法的第一個參數(shù)
  console.log(state);
  return {userinfo:state.userinfo}; //我的理解:state為rootReducer狀態(tài)菇绵,state.userinfo為rootReducer下的userinfo狀態(tài),rootReducer下可以掛載多個規(guī)則;state打印結(jié)果為一個實例對象镇眷,里面有對應(yīng)的各個規(guī)則以及其當(dāng)前的狀態(tài)
}
function mapDispatchToProps(dispatch) {//一個自定義函數(shù)咬最,最為connect方法的第二個參數(shù)
  return {userinfoActions:bindActionCreators(userinfoActions,dispatch)}
}

export default connect(mapStateToProps,mapDispatchToProps)(Hello);

組件渲染完成后,觸發(fā)redux狀態(tài)改變欠动,再重新渲染組件

componentDidMount(){
    this.props.userinfoActions.login({
      userid:'aaa',
      city:'北京'
    })
  }
}

fetch

  • jquery 不考慮兼容永乌,做dom查詢,事件綁定具伍,效果處理
    react開發(fā)為了用ajax函數(shù)去引用jq不值當(dāng)翅雏,而且js中ajax有一個詬病:復(fù)雜業(yè)務(wù)下callback的嵌套問題人芽;fetch是一種可替代ajax獲取/提交數(shù)據(jù)的技術(shù)望几,有些高級瀏覽器已經(jīng)可以window.fetch使用,相比與$.ajax更輕量萤厅,且原生支持promise橄抹,更符合現(xiàn)在的編程習(xí)慣
  • 解決異步嵌套問題除了promise還有2個方法:
    1.es6的generator函數(shù) 2.es7的async,await
  • fetch的坑
    http://blog.csdn.net/whbwhb1/article/details/53322451
options = { 
   catchs: 異常處理惕味,控制臺拋出的異常是否自己處理:true 是害碾,false 否 由公共方法統(tǒng)一處理優(yōu)化顯示給用戶 默認 false 
   credentials: 請求帶上cookies,是每次請求保持會話一直 
   method: 請求使用的方法赦拘,如 GET、POST 
   headers: 請求的頭信息芬沉,形式為 Headers 對象或 ByteString躺同。 
   body: 請求的 body 信息:可能是一個 Blob阁猜、BufferSource、FormData蹋艺、URLSearchParams 或者 USVString 對象剃袍。注意 GET 或 HEAD 方法的請求不能包含 body 信息。 
   mode: 請求的模式捎谨,如 cors民效、no-cors 或者same-origin。是否允許跨域請求 
   cache:  請求的 cache 模式: default, no-store, reload, no-cache, force-cache, or only-if-cached. 
 } 

es6-promise.js可以使它很好的支持IE9以上的版本涛救,IE8 需要改fetch.js源碼才能支持(見上一網(wǎng)址博客)

前端也需要掌握http

前端涉及到很多的數(shù)據(jù)操作:數(shù)據(jù)的獲取畏邢,數(shù)據(jù)的提交,數(shù)據(jù)的安全性检吆,數(shù)據(jù)性能的優(yōu)化

數(shù)據(jù) Mock

在目前互聯(lián)網(wǎng)行業(yè) web 產(chǎn)品開發(fā)中舒萎,前后端大部分都是分離開發(fā)的,前端開發(fā)過程中無法實時得到后端的數(shù)據(jù)蹭沛。這種情況下臂寝,一般會使用三種方式:

  1. 模擬靜態(tài)數(shù)據(jù):即按照既定的數(shù)據(jù)格式,自己提供一些靜態(tài)的JSON數(shù)據(jù)摊灭,用相關(guān)工具(如fis3)做接口來獲取這些數(shù)據(jù)咆贬。該形式使用不比較簡單的、只用 get 方法的場景帚呼,該項目不適用掏缎。
  2. 模擬動態(tài)接口:即自己用一個 web 框架,按照既定的接口和數(shù)據(jù)結(jié)構(gòu)的要求萝挤,自己模擬后端接口的功能御毅,讓前端項目能順利跑起來。該方式適用于新開發(fā)的項目怜珍,后端和前端同時開發(fā)端蛆。
  3. 轉(zhuǎn)發(fā)線上接口:項目開發(fā)中,所有的接口直接用代理獲取線上的數(shù)據(jù)酥泛,post 的數(shù)據(jù)也都直接提交到線上今豆。該方式適用于成熟項目中。

最外層組件的作用

在路由配置中柔袁,我們有一個最外層組件呆躲,App:

 <Router history={this.props.history}>
    <Route path='/' component={App}>
        <IndexRoute component={Home}/>
        <Route path='/city' component={City}/>
        <Route path='/User' component={User}/>
        <Route path='/search/:type(/:keyword)' component={Search}/>
        <Route path='/detail/:id' component={Detail}/>
        <Route path='*' component={NotFound}/>
    </Route>
 </Router>

其作用是:

  • 復(fù)用公共的頭部尾部組件
render() { 
    return (<div> 
            <Head/> 
            {this.props.children} 
            <Footer/> 
        </div>
        )
}
  • 加載loading組件
render() { 
    return ( 
        <div>{this.state.initDone ? this.props.children : <div>正在加載...</div> } 
        </div> 
    )        
}

module.exports與exports,export與export default之間的關(guān)系和區(qū)別

  • CommonJS模塊規(guī)范
    為了方便捶索,Node為每個模塊提供一個exports變量插掂,指向module.exports。可以直接在 exports 對象上添加方法辅甥,但是注意酝润,不能直接將exports變量指向一個值,因為這樣等于切斷了exports與module.exports的聯(lián)系璃弄。
  • ES6模塊規(guī)范
// 第一組
export default function crc32() { // 輸出
  // ...
}
import crc32 from 'crc32'; // 輸入

// 第二組
export function crc32() { // 輸出
  // ...
};
import {crc32} from 'crc32'; // 輸入

上面代碼的兩組寫法要销,第一組是使用export default時,對應(yīng)的import語句不需要使用大括號夏块;第二組是不使用export default時疏咐,對應(yīng)的import語句需要使用大括號。

export default命令用于指定模塊的默認輸出脐供。顯然浑塞,一個模塊只能有一個默認輸出,因此export default命令只能使用一次患民。所以缩举,import命令后面才不用加大括號,因為只可能對應(yīng)一個方法匹颤。

本質(zhì)上仅孩,export default就是輸出一個叫做default的變量或方法,然后系統(tǒng)允許你為它取任意名字印蓖。

js:判斷為null或者undefined

if(a==null)//這個判斷即可

開發(fā)時候遇到的問題

在開發(fā)detail的comment時候辽慕,遇到一個問題:
組件結(jié)構(gòu)是 父 => 子: (page)Detail => (subpage)Comment => CommentList => Item
數(shù)據(jù)是在Comment組件中獲取的,fetch獲取到數(shù)據(jù)后赦肃,將數(shù)據(jù)傳遞給CommentList溅蛉,再由CommentList傳遞給Item,由于Item中渲染的虛擬dom中一個參數(shù)寫錯了:

let data = this.props.data
<p>{item.comment}</p> {/*將data寫成item了*/}

結(jié)果導(dǎo)致在Comment組件里他宛,獲取到數(shù)據(jù)data后船侧,this.setState({data})不成功,當(dāng)時是用console.log調(diào)試厅各,在setState之前可以獲取到數(shù)據(jù)镜撩,但是在setState之后console沒有任何反映,而且setState顯示也沒有生效队塘,當(dāng)時一直以為是數(shù)據(jù)的問題袁梗,調(diào)試了半天,數(shù)據(jù)肯定沒問題憔古,就在子組件找問題遮怜,找到后改掉就正常了

debug調(diào)試發(fā)現(xiàn),才錯誤參數(shù)渲染之前獲取到的數(shù)據(jù)都是正常的鸿市,此時setState還沒生效,而控制臺也不會報錯
我的結(jié)論:setState后锯梁,由于state變化而導(dǎo)致的虛擬dom變化即碗,虛擬dom因為參數(shù)錯誤而無法渲染時,setState就一直無法完成;這中錯誤控制臺也不會報錯涝桅,通過再次測試拜姿,將Comment組件render里的一個參數(shù)故意寫錯,確實還是一樣的狀況冯遂,且不會報錯,在開發(fā)中要注意

this.setState()

http://www.tuicool.com/articles/zEfEfua
setState() 不會立刻改變 this.state 谒获,而是創(chuàng)建一個即將處理的 state 轉(zhuǎn)變蛤肌。在調(diào)用該方法之后訪問 this.state 可能會返回現(xiàn)有的值。

this.setState 是在 render 時, state 才會改變調(diào)用的, 也就是說, setState 是異步的. 組件在還沒有渲染之前, this.setState 還沒有被調(diào)用.這么做的目的是為了提升性能, 在批量執(zhí)行 State 轉(zhuǎn)變時讓 DOM 渲染更快.

  • setState是異步的
    很多開發(fā)剛開始沒有注意到 setState 是異步的批狱。如果你修改一些 state 裸准,然后直接查看它,你會看到之前的 state 蚜迅。這是 setState 中最容易出錯的地方莱坎。 setState 這個詞看起來并不像是異步的陨献,所以如果你不假思索的用它,可能會造成 bugs 权悟。

另外, setState 函數(shù)還可以將一個回調(diào)函數(shù)作為參數(shù), 當(dāng) setState 執(zhí)行完并且組件重新渲染之后. 這個回調(diào)函數(shù)會執(zhí)行, 因此如果想查看通過 setState 改變后的 state, 可以這樣寫:

this.setState({myState: nextState}, ()=>{console.log(this.state.myState)})
  • setState會造成不必要的渲染
    每次調(diào)用都會造成重新渲染。很多時候推盛,這些重新渲染是不必要的峦阁。不必要的渲染有以下幾個原因:
  1. 新的 state 其實和之前的是一樣的。這個問題通吃懦桑可以通過 shouldComponentUpdate 來解決榔昔。也可以用 pure render 或者其他的庫賴解決這個問題。
  2. 通常發(fā)生改變的 state 是和渲染有關(guān)的瘪菌,但是也有例外撒会。比如,有些數(shù)據(jù)是根據(jù)某些狀態(tài)來顯示的师妙。
  3. 有些 state 和渲染一點關(guān)系都沒有诵肛。有一些 state 可能是和事件、 timer ID 有關(guān)的疆栏。

所以:和渲染無關(guān)的狀態(tài)盡量不要放在 state 中來管理

通常 state 中只來管理和渲染有關(guān)的狀態(tài) 曾掂,從而保證 setState 改變的狀態(tài)都是和渲染有關(guān)的狀態(tài)。這樣子就可以避免不必要的重復(fù)渲染壁顶。其他和渲染無關(guān)的狀態(tài)珠洗,可以直接以屬性的形式保存在組件中,在需要的時候調(diào)用和改變若专,不會造成渲染许蓖。
避免不必要的修改,當(dāng) state 的值沒有發(fā)生改變的時候,盡量不要使用 setState 膊爪。雖然 shouldComponentUpdate 和 PureComponent 可以避免不必要的重復(fù)渲染自阱,但是還是增加了一層 shallowEqual 的調(diào)用,造成多余的浪費米酬。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末沛豌,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子赃额,更是在濱河造成了極大的恐慌加派,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,427評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件跳芳,死亡現(xiàn)場離奇詭異芍锦,居然都是意外死亡,警方通過查閱死者的電腦和手機飞盆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評論 3 395
  • 文/潘曉璐 我一進店門娄琉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人吓歇,你說我怎么就攤上這事孽水。” “怎么了照瘾?”我有些...
    開封第一講書人閱讀 165,747評論 0 356
  • 文/不壞的土叔 我叫張陵匈棘,是天一觀的道長。 經(jīng)常有香客問我析命,道長主卫,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,939評論 1 295
  • 正文 為了忘掉前任鹃愤,我火速辦了婚禮簇搅,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘软吐。我一直安慰自己瘩将,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,955評論 6 392
  • 文/花漫 我一把揭開白布凹耙。 她就那樣靜靜地躺著姿现,像睡著了一般。 火紅的嫁衣襯著肌膚如雪肖抱。 梳的紋絲不亂的頭發(fā)上备典,一...
    開封第一講書人閱讀 51,737評論 1 305
  • 那天,我揣著相機與錄音意述,去河邊找鬼提佣。 笑死吮蛹,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的拌屏。 我是一名探鬼主播潮针,決...
    沈念sama閱讀 40,448評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼倚喂!你這毒婦竟也來了每篷?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,352評論 0 276
  • 序言:老撾萬榮一對情侶失蹤务唐,失蹤者是張志新(化名)和其女友劉穎雳攘,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體枫笛,經(jīng)...
    沈念sama閱讀 45,834評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,992評論 3 338
  • 正文 我和宋清朗相戀三年刚照,在試婚紗的時候發(fā)現(xiàn)自己被綠了刑巧。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,133評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡无畔,死狀恐怖啊楚,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情浑彰,我是刑警寧澤恭理,帶...
    沈念sama閱讀 35,815評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站郭变,受9級特大地震影響颜价,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜诉濒,卻給世界環(huán)境...
    茶點故事閱讀 41,477評論 3 331
  • 文/蒙蒙 一周伦、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧未荒,春花似錦专挪、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,022評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至率寡,卻和暖如春迫卢,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背勇劣。 一陣腳步聲響...
    開封第一講書人閱讀 33,147評論 1 272
  • 我被黑心中介騙來泰國打工靖避, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留潭枣,地道東北人。 一個月前我還...
    沈念sama閱讀 48,398評論 3 373
  • 正文 我出身青樓幻捏,卻偏偏與公主長得像盆犁,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子篡九,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,077評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 項目地址 從頭開始建立一個React App - 項目基本配置 npm init 生成 package.json ...
    瘦人假嚕嚕閱讀 89,535評論 33 78
  • 最近看了一本關(guān)于學(xué)習(xí)方法論的書谐岁,強調(diào)了記筆記和堅持的重要性。這幾天也剛好在學(xué)習(xí)React榛臼,所以我打算每天堅持一篇R...
    gaoer1938閱讀 1,685評論 0 5
  • 深入JSX date:20170412筆記原文其實JSX是React.createElement(componen...
    gaoer1938閱讀 8,070評論 2 35
  • 原教程內(nèi)容詳見精益 React 學(xué)習(xí)指南伊佃,這只是我在學(xué)習(xí)過程中的一些閱讀筆記,個人覺得該教程講解深入淺出沛善,比目前大...
    leonaxiong閱讀 2,840評論 1 18
  • 早上起來航揉,總能看到特別的東西。醒目的警示牌金刁,非常難的帅涂。
    10086好閱讀 294評論 0 0