reactJs 基礎

react不是一個完整的mvc,mvvm框架。javascript

react跟web components 不衝突  背景原理:基於React進行開發時全部的DOM構造都是經過虛擬DOM進行,每當數據變化時,React都會從新構建整個DOM樹,而後React將當前整個DOM樹和上一次的DOM樹進行對比,獲得DOM結構的區別,而後僅僅將須要變化的部分進行實際的瀏覽器DOM更新css

react的特色就是‘輕’html

組件化的開發思路java

應用場景:複雜場景下的高性能  重用組件庫,組件組合react

ReactDOM.render()是React最基本方法 ,用於將模版轉爲HTML語言,並插入指定的DOM節點。webpack

React.createClass()方法 就用於生成一個組件類  每一個組件類都必須有本身的 render: 方法,用於輸出組件。git

                                   注意:1 組件類第一個字母大寫  2 組件類只能包含一個頂層標籤 如用<div> 包裹github

                 <HelloMessage name="John"> 組建的屬性能夠在 組件類的 this.props 對象上獲取,this.props.name能夠獲取到web

this.props.children 表示此組件的全部子節點  三種結果:1 沒有子節點 undefined 2 有一個子節點 object   3 有多個子節點 arrayajax

React.Children.map() 遍歷子節點

組件類的PropTypes 屬性,用來驗證組件實例的屬性是否符合要求 

        propTypes:{title:React.PropTypes.string.isRequired,}

getDefaultProps 方法用來設置組件屬性的默認值  getDefaultProps:function(){return{title:'Hello World'};}

ref屬性  能夠從組件中獲取真實DOM節點   父組件引用子組件

    this.refs.[name] 返回真實的DOM節點 須要等到click事件後調用

var MyComponent = React.createClass({
     handleClick:function(){
         this.refs.myTextInput.focus();
},
render:function(){
   return(
     <div>
         <input type="text" ref=」myTextInput「 />
         <input type = "button" value="Focus the text input" onClick = {this.handleClick} />
) 
}
})    

組件中getInitialState 方法用於定義初始化狀態(對象),能夠經過this.state屬性讀取。

 

var Input = React.createClass({
  getInitialState: function() {
    return {value: 'Hello!'};
  },
  handleChange: function(event) {
    this.setState({value: event.target.value});
  },
  render: function () {
    var value = this.state.value;
    return (
      <div>
        <input type="text" value={value} onChange={this.handleChange} />
        <p>{value}</p>
      </div>
    );
  }
});

this.setState方法就修改狀態值,每次修改後 自動調用this.render 方法,再次渲染組件。

this.props 表示那些一旦定義 就再也不改變的特性;

this.state 是會隨着用戶互動而產生改變的

上面代碼中,文本輸入框的值,不能用 this.props.value 讀取,而要定義一個 onChange事件的回調函數,經過 event.target.value 讀取用戶輸入的值。textarea 元素、select元素、radio元素都屬於這種狀況

 

引入解析jsx的文件  <script src='http://cdnjs.cloudflare.com/ajax/libs/react/0.13.3/JSXTransformer.js'></script>  type=''text/javascript"

reactComponent 是指建立的dom節點

 

react component lifecycle的生命週期:

1 Mounted --- React.renderComponent()    React Components被render解析生成對應的DOM節點 並被插入瀏覽器的DOM結構的一個過程

 componentWillMount 前被調用 --> render --> componentDidMount  後被調用

 getDefaultProps()   

getInitialState() 初始化

2 Update --- setState() / setProps() 至render()   一個mounted的ReactComponents被從新render的過程

  componentWillUpdate / componentDidUpdate   / shouldComponentUpdate /componentWillReceiveProps

3 Unmounted --- React.unmountAndReleaseReactRootNode()  一個mounted的React Components對應的DOM節點 被從DOM結構中移除的這樣一個過程

  componentWillUnmount

總結:每個狀態 react都封裝了對應的hock函數

 

組件的生命週期:初始化——運行中——銷燬

初始化:可以使用的鉤子

1  getDefaultProps  只調用一次,實例之間共享引用

2 getInitialState  初始化每一個實例特有的狀態,都須要調用

3  componentWillMount  render以前最後一次修改狀態

4 render  只能訪問this.props和this.state  不容許修改狀態和DOM輸出

5 componentDidMount  渲染完成以後觸發,可對dom進行操做。

運行中:

1 componentWillReceiveProps 父組件修改屬性觸發,能夠修改新屬性,修改狀態

2 shouldComponentUpdate  返回faulse 會阻止render調用

3 componentWillUpdate  不能修改屬性和狀態

4 render 只能訪問this.props 和 this.state,不容許修改狀態和DOM輸出

5 componentDidUpdate 能夠修改DOM

銷燬:

componentWillUnmount

屬性 組件本身不能修改屬性,能夠從父組件獲取屬性,父組件也能夠修改它的屬性,他也能夠修改子組件的屬性 :自己具備的,屬性的四種用方式:

1  <HelloWorld name=? />  出入鍵值對  "字符創"  「item」

 2 {「time」}{123}數字、字符串、等  var props={one:'123',two:321} <HeeloWorld{...props}/>   {...props}展開對象的方式,取到的是值;{props}此方法取到的是對象

3 {【1,2,3】}數組

4 {變量}

狀態 只和本身相關 與父組件子組件都不相關,有本身維護 :事物所處的情況,不斷變化的

狀態用法:

1 getInitialState:初始化每一個實例特有的狀態

2  setState:更新組件狀態

setState-----diff-----dom

區分:組件在運行中須要修改的數據就是 狀態。

 

 

極客react 

非dom節點:

一、 dangerouslySetInnerHTML = {rawHTML}

var rawHTML = {__html:"<h1>i'm inner HTML"}
React.render(<div style={style} dangerouslySetInnerHTML={rawHTML}></div>,  )

二、ref  

三、key  列表類相同的節點 li 必定要加上key值 <li key='1'></li><li key='2'></li>

 

事件用法:組件(1,React自有方法:render  、componentWillUpdate、componentDidMount

                       2. 用戶定義方法:handleClick、handleChange、handleMouseover)

綁定事件處理函數:

觸摸:onTouchCancel

onTouchEnd

onTouchMove

onTouchStart

鍵盤:onKeyDown

onKeyPress

onKeyUp

剪切:onCopy

onCut

onPaste

表單:onChange

onInput

onSubmit

焦點:onFocus

onBlur

UI元素:onScroll

滾動:onWheel

鼠標:onDrop/onDrag/onDragEnd/onDragEnter/onDragExit/onDragLeave/onDragOver/onDragStart

onClick/onContextMenu/onDoubleClick/onMouseDown/onMouseEnter/onMouseLeave/onMouseLeave/onMouseMove/onMouseOut/onMouseOver/onMouseUp

事件對象的屬性:

事件和狀態關聯:

handleChange:function(e){this.setState({inputText:e.target.value})}

組件協同:

1 組件嵌套: 父子關係  父組件-屬性-》子組件;子組件-委託(觸發事件)-》父組件

2 mixin:React雙向綁定Minxin

組件要可控:符合react的數據流;數據存儲在state中,便於使用;

表單元素:

<label htmlFor="name">對應相應的input的id</label>

<input><textarea><select><option></option></select>

事件處理函數複用:

一、bind複用:

    handleChange:function(name,event){....}

  {this.handleChange.bind(this,'input')}

二、name複用:

  handleChange:function(event){var name=event.target.name}

  {this.handleChange}

 

 

React性能調優:

提升性能的方式:虛擬DOM,diff算法,將dom操做減小到最小,可是

        問題1:父組件更新默認出發全部子組件更新;解決方法:子組件覆蓋shouldComponentUpdate方法,返回true,觸發更新流程,生成新的虛擬DOM節點與以前的進行比較,不一樣則進行操做;返回false,自行解決是否更新。

        問題2:列表類型的組件默認更新方式比較複雜;解決方法:給列表中的組件添加key屬性

性能調優:分析性能熱點

控制檯輸入React.addons.Perf.start()--->進行一次操做---->React.addons.Perf.stop()  ;完成後臺記錄消耗時間

      查看記錄結果:React.addons.Perf.printInclusive();

如何解決性能問題:1;PureRenderMixin判斷是否須要進入更新流程,本質上就是判斷狀態和屬性是否改變(只能處理原始值,不能處理對象)

  在shouldComponentUpdate(nextProps,nextStates)內判斷!shallowEqual(this.props,nextProps)||!shallowEqual(this.state,nextState);

2;不可變插件Immutability Helpers,實現js不可變對象

  基本語法:update(obj,cmd)

組件嵌套:

 鉤子函數:

初始化:getDefaultProps  只調用一次

getInitialState

componentWillMount  渲染以前最後一次修改狀態this.setState({}),觸發render()函數;

render

componentDidMount  操做或修改真正的dom

運行中:componentWillReceiveProps  父組件修改屬性以前觸發,此函數能夠修改新屬性、修改狀態

shouldComponentUpdate  返回false,根據須要使用

componentWillUpdate :不能修改屬性和狀態

render:只能訪問this.props和this.state,不能修改

componentDidUpdate :能夠修改dom

銷燬:componentwillUnmount  在刪除組件以前進行清理操做,好比計時器和事件監聽器,必須手動清理。方法1.在子組件中componentwillUnmount:function(){}  方法2:在子組件的handle函數中,調用:React.unmountComponentAtNode(document.getElementsByTagName('body')[0]);//傳入的必須是裝載入的節點。

React.findDOMNode()

 

react添加css動畫:

var ReactCSSTransitionGroup = React.addons.CSSTransitionGroup; 引入react-addons-t

調用:return(<ReactCSSTransitionGroup transitionName="example">{items}</ReactCSSTransitionGroup>)

react添加js動畫:

componentDidUpdate:function(){if(this.props.position){setTimeout(this.resolveSetTimeout,this.props.timeoutMs);}},

render:function(){var divStyle={marginLeft:this.state.position};return <div style={divStyle}>this will animate!</div>}})

React.render(<Positioner></positioner>,document.body);

React.render(<Positioner position={100} timeout={10}></Positioner>,document.body);第二次調用,改變屬性值props,觸發componentDIdUpdate();從而達到動畫效果

 

項目實戰:

 1.分析目標-肯定開發順序:頁面上有組件->組件能正常顯示內容->內容的樣式正確->設置項能夠正常工做->交互功能正常

 

在jsx中使用循環,通常會用到Array.prototype.map

class Hello extends React.Component{
      render(){
         const arr = ['a','b','c'];
         return (
           <div>
             {arr.map((item,index) => {
       return <p key={index}> this is {item}</p>  
})}
    </div>
    )
    }
}        

參考連接:http://www.imooc.com/article/14500

代碼分離

page層  ./app/containers/Hello/index.jsx

subpage層  ./app/containers/Hello/subpage/...jsx

component層  ./app/components/...  把多個頁面均可能用到的功能,封裝到一個組件中,放到此目錄下。

數據傳遞&數據變化

props:通常只用做父組件給子組件傳遞數據用,不能被自身修改。

每一個頁面引用Header時,設置獨自的title屬性值,<Header title='Hello頁面'/>;而在子組件中這樣取到 render(){return(<p>{this.props.title}</p>)}  

state:自身組件狀態發生變化,constructor(props,context){super(props,context);this.state = {now:Date.now()}}  render(){return (<div><p>hello world {this.state.now}</p></div>)}}

智能組件&木偶組件

智能組件:./app/containers   簡稱「頁面」,只對數據負責,只需獲取數據、定義好數據操做的相關函數,而後將這些數據、函數直接傳遞給具體的實現組件。

木偶組件:作一些展現的工做,展現給用戶。 ./app/components/...

 

性能檢測優化:參考https://github.com/wangfupeng1988/react-simple-o2o-demo/tree/getready-redux-width-react   本地切換到對應的分支

1安裝react的性能檢測工具npm install react-addons-perf --save  在./app/index.jsx中import Perf from 'react-addons-perf'   if(__DEV__){window.Perf = Perf}

使用:Perf.start()開始檢測,Perf.stop中止檢測,Perf.printWasted()便可打印出浪費性能的組件列表。

2安裝react的優化插件 PureRenderMixin,npm install react-addons-pure-render-mixin --save

使用:在constructor(props,context){super(props,context);this.shouldComponentUpdate = PureRenderMixin.shouldComponentUpdate.bind(this);}}  重寫組件shouldComponentUpdate函數,在每次更新以前判斷props和state,若是有變化返回true。

3 Immutable.js優化:使用此來處理數據,實現js中不可變數據的概念。適用於數據結構層次很深(obj.x.y.a.b=10)其定義了新的語法,不輕易使用。

React-router

安裝 npm install react-route --save

1 建立子頁面./app/containers/App.jsx 全部頁面的外殼 ./app/containers/Home等主頁、列表頁、詳情頁

2 配置router 建立./app/router/routerMap.jsx 文件

class RouteMap extends React.Component{
    updateHandle(){
        //每次router變化以後都會觸發
   }
    render(){
        return (
            <Router history={this.props.history}  onUpdate={this.updateHandle.bind(this)}>
                <Route path='./'  component={App}>
                        <IndexRoute component={Home}/>
                        <Route path='list' component={list}/>
                        <Route path='detail/:id'  component={Detail}/>     //id表示參數
                        <Route path="*" component={NotFound}/>
                </Route>                                                  //route能夠嵌套
            </Route>
        )
    }
}

3 使用Route

./app/index.jsx

import React from 'react'
import {render} from 'react-dom'
import {hashHistory} from 'react-router'

import RouteMap from './router/routeMap'

render(
    <RouteMap history={hashHistory}/>,         //hashHistory規定hash來表示router localhost:8080/#/list
    document.getElementById('root')
)

頁面跳轉

1 <link to='/list'>to list </link>

2 js跳轉

return(<ul>

      {arr.map((item,index) => {

        return <li key={index} onClick={this.clickHandle.bind(this,item)}>js jump to {item} </li>})}

    </ul>)}

clickHandle(value){

  hashHistory.push('/detail/' + value)

}}

 

性能優化--靜態資源懶加載  huge-apps 

他將react-router自己和webpack的require.ensure結合起來,解決此問題。

相關文章
相關標籤/搜索