淺扒react


  簡介:
      當2014年Facebook推出React時,給整個業界帶來全新的看待網頁應用開發的方式,和React一同問世的Flux,也克服傳統MVC框架的不少弊病。技術在不斷髮展,在2015年,Flux的一個變體Redux出現,進一步優化了Flux的功能。css

  優秀之處:
    一、 專一視圖層:(不處理理由,數據,以及邏輯的處理)
    二、 VirtualDom:只對dom更新,不對dom更新;只對dom進行必要的更新,實現的重繪的最小化;
    三、 jsx語法:
      1) 高內聚,低耦合
      2) onClick 不是原生dom中的onclick事件,這裏是onClict是經過react的事件委託方式,觸發掛在頂層dom節點上的一個事件處理函數(提升了性能);
      3) 能夠將樣式一塊兒寫入組件文件中;
      4) 關於jsx語法的說法:
       在jsx語法中能夠直接寫入組件,注意組件爲了和普通標籤區別,必須第一個字母大寫;
       jsx語法是歷史的進步仍是倒退;(樣式,結構,邏輯於一體)
    四、 活躍的生態圈:(開源項目)
    五、 組件式開發
  1、 手動搭建項目:
    一、npm init
    二、安裝項目依賴
      cnpm install --save-dev babel-core babel-loader babel-preset-stage-2babel-plugin-transform-react-jsx babel-plugin-transform-runtime babel-preset-es2015 babel-preset-react babel-preset-stage-0 css-loader html-loader html-webpack-plugin react react-dom style-loader url-loader webpack webpack-dev-server(還有一些依賴包能夠依照須要下載)html


    三、配置babelrc文件:
    {
      "presets": [
        "es2015",
        "stage-0",
        "react"
      ],
      "plugins": ["transform-runtime", "transform-react-jsx"]
    }
    四、webpack.config.js的配置文件:
      除了以下配置有更改,其餘能夠徹底遵守vue的配置
      {
        test: /\.js|.jsx$/,
        use: [
          "babel-loader",
        ],
        exclude: /node_modules/
      },
    五、在vsCode中開發react的配置:
      安裝jsx插件配置以下:

      安裝React/Redux/react-router Snippets插件,能夠幫助咱們快速生成必定的語句;
      全部的react組件使用jsx後綴來標識;
  2、 自動化構建項目:
    一、初始化:
      全局安裝:
      npm install –-global create- react- app
      初始化項目:
      create- react- app myReactApp
      啓動服務:
      cd myReactApp
      npm start
    二、組件寫法:vue

      importReact,{Component} from "react"
      importClickCount from "./ClickCount.jsx"html5

      class Main extends Component {
        constructor(props){
          super(props)
        }
      render(){
        return (
          <ul>
            <li><ClickCount name="first" num={1}></ClickCount></li>
            <li><ClickCount name="second" num={10}></ClickCount></li>
            <li><ClickCount name="third" num={7}></ClickCount></li>
          </ul>
        )
      }
    }
      export defaultMain
      注:對於jsx語法的解析必須引入React,雖然這裏不用,可是若是不引入會因沒法解析jsx而報錯;組件的定義必須遵循首字母大寫
    三、jsx語法使用:
      屬性:
        一、屬性值直接爲字符串
        二、動態解析屬性值
          constelement=(<imgsrc={user.avatarUrl}></img>);
          react的jsx:
          constelement=(
            <h1className="greeting">
              Hello,world!
            </h1>
          );node

      用React.createElement()一樣能夠達到一樣的效果;
        constelement=React.createElement(
          'h1',
          {className:'greeting'},
            'Hello, world!'
        );
    四、項目的分解:
      npm run eject 進行項目配置文件的彈射;
    五、react的工做方式:
      1) 從繁瑣的dom處理中解脫出來,響應式,函數式編程思惟;輸入相同的數據,將產出相同的效果;數據更新,dom同時作出更新;
      2) Virtual Dom
      Dom:結構化文本的抽象表達式;
      虛擬dom:對dom樹的抽象,不會觸及瀏覽器,只存在於js內存的空間樹形結構,每次的數據刷新,render函數的執行都會觸發一個新舊虛擬dom的對比,若是無改變,則不更新,有改變,只更新相應dom結構;
  3、 元素的渲染
    a) jsx語法將元素渲染到dom中
    b) 更新元素渲染:
      React 元素都是immutable 不可變的。當元素被建立以後,你是沒法改變其內容或屬性的;更新界面的惟一方法就是從新掛載節點
      function tick() {
        const element = (
          <h2>{newDate().toLocaleTimeString()}.</h2>
        );
        ReactDOM.render(
          element,
          document.getElementById('root')
        );
      }
      setInterval(tick, 1000);react

    c) 只會更新必要的部分(能夠在谷歌開發者工具中進行dom更新的查看)
    d) 在react的jsx語法中,若是標籤沒有子元素,能夠直接使用閉合標籤;
    e) 在react的組件必須首字母進行大寫,不然React.createEelement則沒法查找到組件,進行編譯;
    f) jsx支持標籤名爲表達式;,若是使用動態標籤名,則需先將表達式解析賦值給一個變量;webpack


  4、 React組件以及基本語法:
    一、 組件的設計要素:
      高內聚:把邏輯緊密相關的內容放在一個組件中;
      低耦合:不一樣組件之間的依賴關係要儘可能弱化;儘可能保持每一個組件的獨立性;
    二、 組件的生命週期:
      1) 裝載過程:
        a) Constructor:
          初始化state;
          綁定成員函數的this環境(bind、:: )防止以解構的方式進行全局做用域進行調用;
          例:this.fn=this.fn.bind(this)或this.fn=::this.fn
        b) GetInitialState:初始化state值,必須結合React.createClass()使用,使用es6的方式,此函數無效果;es6

          const Test=React.createClass({
            getInitialState:function(){
              return {
                name:"zhangsan"
              }
            },
            getDefaultProps:function(){
              return {
                name:"zhangsan"//這裏的zhangsan至關於默認值
              }
            }
           })web

      c) GetDefaultProps:初始化props值,必須結合React.createClass()使用,使用es6的方式,此函數無效果,用屬性defaultProps代替;vue-router


      class Test extends Component {
        constructor(props){
          super(props)
          this.state={data:new Date()}
        }
        render(){
          return (
            <ul>
              <li><ClickCount name="third" num={7}></ClickCount></li>
            </ul>
           )
          }
        }

      Test.defaultProps={
        return {
          name:"moren"
        }
      }


      d) ComponentWillMount:在render函數調用以前進行調用;
      e) Render:並不作實際的渲染動做,只返回一個jsx描述結構,最後渲染與否由react來決定;必須是個純函數,不能設計到數據的更變(this.setState);

        render(){
          return (
            <ul>
              <li><ClickCount name="third" num={7}></ClickCount></li>
            </ul>
          )
        }

     f) ComponentDidMount:在render函數調用以後進行調用;但不是在render函數調用以後當即調用,而是當全部的dom樹掛載並渲染完成後纔會調用,這是由於render函數並不進行渲染,而只是返回一個jsx對象,渲染的工做由react庫進行,只有當全部的組件的jsx對象組合完畢以後,react經過對比後纔會渲染,全部此鉤子函數是發生的全部組件的render函數都執行後纔會執行;(只能在瀏覽器端觸發)
    注:與angular中的link或者post函數有點類似,可是這裏不只指子組件,而是當前組件中的全部組件,包括兄弟組件;提供了dom操做的接口
    2) 更新過程:
      a) ComponentWillReceiveProps:傳入的props的改變或者組件進行刷新(forceUpdate函數觸發組件的刷新)都會觸發此函數,可是經過this.setState改變的數據則不會觸發此函數,
      b) ShouldComponentUpdate:react組件的鉤子函數兩個須要有返回值的鉤子函數之一,另外一個爲render,此鉤子函數的返回值爲一個bolen值,若是爲true時,則prop的改變以及state的改變都會引發組件的刷新,若是爲false時,則再也不進行渲染;此鉤子函數接受兩個參數,一個是nextProps,一個是nextState,能夠將將要更新的值和此時的作對比,而後返回true和false來進行性能的校優;
      c) ComponentWillUpdate:跟componentWillMount類似
      d) Render
      e) ComponentDidUpdate:跟componentDidMount類似
    3) 卸載過程:
      ComponentWillUnmount:此鉤子函數能夠在組件卸載前執行,能夠進行手動添加dom元素的刪除,以及計時器和事件監聽的移除;
  5、 React組件的數據
    組件內部數據類型:
      兩種數據結構,prop和state,這兩種數據的改變都會引發組件的從新渲染;
    一、 Prop:組件的外部接口,接受外部數據;跟html的屬性的書寫相似,可是除了接受字符串以外,還能夠接受js對象,數字等的;若是組件進行數據反饋給外界,能夠經過prop傳入組件一個函數;
       Prop的讀取:
        由class類的constructor函數接受,以及super()方法調用時的傳入;
        最後的props爲一個對象,鍵值分別爲傳入時的屬性名;這裏比較方便的是使用es6的解構賦值;
       PropTypes的檢查:
        能夠經過增長類的propTypes屬性來定義prop規格,在constructor函數中進行以下定義:
        This.propTypes={
          caption:PropTypes.string.isRequired,
          initValue:PropTypes.number
        }
      注意:此屬性不會影響組件的渲染,只是作到在開發過程當中輔助開發;
    二、 State:因爲組件不能改變出入的prop,因此當組件要進行本身的狀態紀錄時就須要用到state;
       初始化:state的初始化能夠在constructor中,經過this.state進行設置,值必須爲一個js對象的格式,一般將prop傳入的外部值賦給state,以便後續操做;設置默認值時,能夠用 ||操做符進行;
       讀取和更新state
      更新使用this.setState({count:this.state.count++})方法;
      讀取爲:this.state.count這種方式
    三、 Prop和state的對比:
      Prop:定義外部接口;賦值在外部環境使用組件時;組件內部不能更改
      State:紀錄內部狀態;賦值在組件內部;在組件內部能夠進行更改;

  6、 react中css的樣式書寫
    一、 全局引入css文件
      此種方式會將css文件在全局引入,也就是說當前樣式文件中書寫的全部樣式,在任何一個組件均可以引用,此種引用方式有可能會形成全局的污染,變量名衝突,又或者說不符合組件式開發的思想;因此此種方式通常是引入全局的css文件;
i      mport 「app.css」

    二、 局部做用域(css modules的方式)
      此種方式採用的是css modules的作法,經過此作法,最後會將css文件中類名和dom中類名造成惟一的hash值,這樣就不會形成類名的衝突了,使用場景,通常爲組件內部的樣式防止全局書寫形成的類名污染;
    好比以下寫法:
    app.css:
      .title {
        color: red;
      }
    jsx:
      import style from './App.css';

       export default ()=>{
        return(
          <h1 className={style.title}>
            Hello World
          </h1>
        );
        };
     最後會編譯成以下代碼:
      <h1 class="_3zyde4l1yATCOkgn-DBWEL">
        Hello World
      </h1>

    ._3zyde4l1yATCOkgn-DBWEL {
      color: red;
    }

    注:在css Modules中還提供了一種css全局做用域的書寫方式,也就是說若是經過此種方式註冊的css類名不會被替換爲hash值,書寫方式以下:
    css:
      :global(.title){
        color:red;
       }

    三、 行內樣式:
      在jsx的dom上直接使用style屬性進行樣式的設置,樣式的值爲一個對象,這種方式的書寫,能夠支持css樣式以js對象的方式進行書寫,若是不想將組件的內部樣式進行做用域隔離使用cssmodules的方式進行書寫,則能夠此種方式進行書寫,能夠直接在render函數中定義樣式對象,也能夠經過專門外部樣式js文件配置樣式對象,而後引入到dom進行使用,書寫方式以下:
      varstyle={
        color:red;
      }
      <divstyle={style}>天氣真好</div>
      注:在書寫css屬性時,必定要採用駝峯式寫法;
  7、 事件處理
    一、 react中的事件綁定屬性採用的是駝峯式寫法:
      <button onClick={this.clickfn}>點擊</button>
    二、 處理react使用class類定義方法時,沒法自動綁定this的弊端:
       在constructor中使用bind爲事件函數綁定this
      this.clickfn=this.clickfn.bind(this)
       在dom中調用函數時,先使用箭頭函數綁定this,箭頭函數的this是在定義時造成的
        <button onClick={()=>this.clickfn()}>點擊</button>

    三、 jsx的onClick和html的onclick不一樣之處

       html的onclick弊端:
      註冊的事件處理函數都是全局環境,污染了全局環境;
      使用onclick的dom元素,若是在dom樹中刪除時,必須手動的註銷事件處理器,不然會形成內容泄露;

       jsx的onClick:
        掛載的每個函數都是在組件內部,而不是全局;
        不管多少個onClick都是採用的事件委託的方式,在dom樹頂層添加一個事件監聽函數,此函數會根據具體組件分配具體的函數;

  8、 條件判斷:
    在react的jsx語法中,若是遇到js語句使用{}進行包裹;
    一、 if語句的使用:

      render() {
        var element=null
        if(this.state.stateT){
          element= <div > stateT爲true時< /div>
        }else{
          element= <div > stateT爲false時< /div>
        }
      return (
        <div>
          <button onClick={this.changeFn}>切換</button>
          {element}
        </div>
      )
    }

    二、 jsx與運算符&&的結合:

      render(){
        return (
          <div>
            <button onClick={this.changeFn}>切換</button>
            {this.state.stateT&&<div > stateT爲false時< /div>}
          </div>

        )
      }
    三、 三目運算符

      render(){
        return (
          <div>
            <button onClick={this.changeFn}>切換</button>
            {this.state.stateT?<div>stateT爲true時</div>:<div> stateT爲false時</div>}
          </div>
        )
      }
    四、 在jsx語法中,render能夠返回null,表示不進行任何dom的渲染,可是鉤子函數會執行;
  9、 列表和keys
    一、 基礎用法:(key通常採用數據id,或者數據在數組中的索引)

      render() {
        var element=this.state.list.map((i,index)=><li key={index}>{i}</li>)
        return (
          <div>
            <button onClick={this.changeFn}>切換</button>
            {element}
          </div>
        )
      }
    注:若是後續進行數據的從新排序,則最好不要使用索引看成key值,不然,因爲key值和dom的內容同時改變,則會引發所有dom節點的重繪;若是使用的是id,則只會調整dom節點的順序,不會引發重繪dom樹;(能夠用上面例子演示,推薦使用id做爲標識,而不是index)
    二、 key值只須要在兄弟元素之間惟一就能夠,不須要是在全局惟一的

      render() {
        var element=this.state.list.map((i,index)=><li key={i}>{i}</li>)
        var element2=this.state.list.map((i,index)=><li key={i}>{i+1}</li>)
        return (
          <div>
            <button onClick={this.changeFn}>切換</button>
            {element}
            {element2}
          </div>
        )
      }
    三、 在jsx中使用map進行遍歷

    render() {
      return (
        <ul>
          <button onClick={this.changeFn}>切換</button>
          {this.state.list.map((i)=><li key={i}>{i}</li>)}
        </ul>
       )
     }
  10、 表單
    在vue中,咱們知道因爲vue的mvvm架構,v與m之間是響應式的,能夠實時同步,可是在react中不存在數據的雙向數據綁定,只是負責view層的渲染,因此咱們在react中取表單中的值時須要必定的方式
    一、 受控組件(採用react的單向數據流方式實現vue同樣的雙向數據綁定)
      changeFn(event){
        this.setState({
          name:event.target.value
        })
       }
      render() {
        return (
          <div>
            <p>表單</p>
            <label htmlFor="name">name:</label>
            <input type="text" id="name" value={this.state.name} onChange={this.changeFn}/>
            <p>{this.state.name}</p>
          </div>
        )
      }
    若是想對從input中獲取到的值進行格式化時,則以下操做就能夠實現:
      this.setState({
        name:event.target.value.toUpperCase()
      })
    二、 textarea標籤在react中設置和讀取值都採用value的方式
    三、 在react中的使用select,並實時獲取其選擇的值:
      render() {
        return (
          <div>
            <p>表單</p>
            <label htmlFor="name">name:</label>
            <select value={this.state.name} onChange={this.changeFn}>
            <option value="one">one</option>
            <option value="two">two</option>
            <option value="three">three</option>
            </select>
            <p>{this.state.name}</p>
          </div>
        )
      }
    四、 在react中實現多表單元素值得獲取
      changeFnAll(event){
        let target=event.target
        let name=target.name
        let value=target.type==="checkbox"?target.checked:target.value
        this.setState({
          [name]:value
        })
      }
  // 實現多表單元素值的獲取
      render() {
        return (
          <div>
            <p>表單</p>
            <input type="checkbox" value={this.state.checkbox} onChange={this.changeFnAll} name="checkbox"/>
            <input type="text" value={this.state.text} onChange={this.changeFnAll} name="text"/>
            <p>{this.state.checkbox.toString()}</p>
            <p>{this.state.text}</p>
          </div>
        )
      }
  11、 組件間通信
    一、 父組件向子組件傳遞數據:
      a) 字符串常量的傳遞:
        <MyComponentmessage="hello world"/>
        <MyComponentmessage={'hello world'}/>
      b) 沒有給屬性傳值,它默認爲 true
        <MyTextBoxautocomplete/>
        不建議以下寫法,容易與es6的對象簡潔表示法衝突
        <MyTextBoxautocomplete={true}/>
      c) 使用擴張運算符進行屬性的設置
        constprops={firstName:'Ben',lastName:'Hector'};
        <Greeting {...props} />;

    二、 子組件向父組件傳遞數據
      只能經過將父組件的一個方法用prop的方式傳入子組件,在子組件觸發更變時,調用這個傳入的方法,而後把子組件更變後的值以參數的形式傳入父組件;從而達到父組件和子組件的通訊的效果;

    三、 兄弟組件間的通信
      a) 狀態提高
        對於沒有直接關聯關係的兩個節點,就如 Child_1 與 Child_2 之間的關係,他們惟一的關聯點,就是擁有相同的父組件。參考以前介紹的兩種關係的通信方式,若是咱們向由 Child_1 向 Child_2 進行通信,咱們能夠先經過 Child_1 向 Parent 組件進行通信,再由 Parent 向 Child_2 組件進行通信
      b) 觀察者模式
        也就是像angular和vue的事件派發機制,在這裏react沒有內置的事件派發模式,因此須要手動封裝一個事件派發機制;
      以下代碼:
        var watchObj = {
          arrFn: {},
          on(name, fn) {
          if (this.arrFn[name] === undefined) {
            this.arrFn[name] = []
          }
          this.arrFn[name].push(fn)
         },
        emit() {
        let name, args;
        if (arguments.length == 0) {
          returnfalse;
        }
        name = arguments[0]
        args = [].concat(Array.prototype.slice.call(arguments, 1));
        if (this.arrFn[name] !== undefined&&this.arrFn[name].length >0) {
          this.arrFn[name].forEach(function(i) {
            i(...args)
          }, this);
        }
       }
      }
      exportdefault watchObj

  12、 組合與繼承
    在vue中的有一種組件特性叫內容分發,能夠在父組件中自定義子組件的dom結構,在react中也提供了這麼一種機制
    一、 包含關係:(在子組件經過this.props.children獲取父組件中寫在子組件開閉標籤間的dom節點)
      父組件:
        render() {
          return (
            <div>
              <Children>
                <p>至關於vue的內容分發</p>
              </Children>
            </div>
          )
         }
      子組件:
        render() {
          return (
            <div>
              <p>這裏是子組件</p>
              {this.props.children}
            </div>
          )
        }


    二、 子組件中動態渲染其餘組件:(在父組件中將其餘組件動態綁定到prop屬性上,在子組件中經過相應的屬性來獲取)

      父組件:
        render() {
          return (
            var one= <span>這裏爲true</span>
            var two=<span>這裏爲false</span>
            return (
              <div>
                <Slot one={one} two={two}></Slot>
              </div>
            )

           )
          }
      子組件:
        render() {
          return(

            <div>
              <p>這裏是子組件</p>
              {this.state.state?this.props.one:this.props.two}
            </div>

          )
        }

  十3、 react-router
    2.0 徹底向後兼容 1.0,全部在 1.0 被棄用的 API 都會在控制檯以 warn 的形式打印出來,在 3.0 中將會徹底移除 1.0 所棄用的東西,如今最新版本是4.2.0版本;可是4.0版本後,有不少方法再也不向前兼容(這裏講解的爲2.8.1版本)

    (一) 基本用法:
     一、 首先咱們須要導入一些組件...
      import { Router, Route, Link } from 'react-router'
     二、 配置路由信息:
       使用jsx語法
      React.render((
        <Router>
          <Route path="/" component={App}>
            <Route path="about" component={About}/>
            <Route path="inbox" component={Inbox}/>
          </Route>
        </Router>
      ), document.body)
     使用js對象進行配置
      const routes ={
        path:'/',
        component: App,
        childRoutes:[
          { path:'about', component: About },
          { path:'inbox', component: Inbox },
        ]
      }

      React.render(<Router routes={routes}/>, document.body)
    三、 獲取參數
       經過動態路由片斷
      <Route path="messages/:id" component={Message}/>
      能夠經過以下方式進行獲取id:
      this.props.params.id
       經過query字符串
      /foo?bar=baz;
      this.props.location.query.bar
    (二) 路由的配置規則
      一、 路徑語法:
         :paramName – 匹配一段位於 /、? 或 # 以後的 URL。 命中的部分將被做爲一個參數
         () – 在它內部的內容被認爲是可選的
         * – 匹配任意字符(非貪婪的)直到命中下一個字符或者整個 URL 的末尾,並建立一個 splat 參數
          以下解釋:
            // 匹配 /hello/michael 和 /hello/ryan
            <Route path="/hello/:name">
            // 匹配 /hello, /hello/michael 和 /hello/ryan
            <Route path="/hello(/:name)">
            // 匹配 /files/hello.jpg 和 /files/path/to/hello.jpg 
            <Route path="/files/*.*">
    (三) 經常使用路由類型:

      browserHistory:react推薦使用(採用的是html5的瀏覽器路由紀錄)
      hashHistory:默認的(採用的是hash的瀏覽器路由紀錄)
      createMemoryHistory

    使用browserHistory以下:
      import{ browserHistory } from 'react-router'
      <Router history={browserHistory}>

    (四) 默認路由的設置:
      jsx:
        <IndexRoute component={Index}/>
      js對象:
        const routes = {
          path:'/',
          component:App,
          indexRoute:{
            component:Index
          },
          childRoutes: [
            { path:'list', component:List },
          ]
       }

    在嵌套路由中使用{this.props.children}來渲染動態路由,這裏至關於vue-router中的router-view

  十4、 PropTypes類型檢查
    在react的15.5版本後,React.PropTypes已經廢棄了,須要單獨引入prop-types庫進行驗證
      importPropTypes from 'prop-types'
      class Children extends Component {
        constructor(props) {
          super(props)
        }
        render() {
          return (
            <div>
              <p>這裏是子組件</p>
              {this.props.name}
            </div>
          )
         }
        }
        Children.propTypes={
          name:PropTypes.string
        }

      prop-types庫能夠校驗的類型以下:

      importPropTypes from 'prop-types';

      MyComponent.propTypes = {
        // 你能夠將屬性聲明爲如下 JS 原生類型
        optionalArray:PropTypes.array,
        optionalBool:PropTypes.bool,
        optionalFunc:PropTypes.func,
        optionalNumber:PropTypes.number,
        optionalObject:PropTypes.object,
        optionalString:PropTypes.string,
        optionalSymbol:PropTypes.symbol,

        // 任何可被渲染的元素(包括數字、字符串、子元素或數組)。
        optionalNode:PropTypes.node,

        // 一個 React 元素
        optionalElement:PropTypes.element,

        // 你也能夠聲明屬性爲某個類的實例,這裏使用 JS 的
        // instanceof 操做符實現。
        optionalMessage:PropTypes.instanceOf(Message),

        // 你也能夠限制你的屬性值是某個特定值之一
        optionalEnum:PropTypes.oneOf(['News', 'Photos']),

        // 限制它爲列舉類型之一的對象
         optionalUnion:PropTypes.oneOfType([
          PropTypes.string,
          PropTypes.number,
          PropTypes.instanceOf(Message)
         ]),

        // 一個指定元素類型的數組
        optionalArrayOf:PropTypes.arrayOf(PropTypes.number),

        // 一個指定類型的對象
        optionalObjectOf:PropTypes.objectOf(PropTypes.number),

        // 一個指定屬性及其類型的對象
        optionalObjectWithShape:PropTypes.shape({
          color:PropTypes.string,
          fontSize:PropTypes.number
        }),

        // 你也能夠在任何 PropTypes 屬性後面加上 `isRequired` 
        // 後綴,這樣若是這個屬性父組件沒有提供時,會打印警告信息
          requiredFunc:PropTypes.func.isRequired,

        // 任意類型的數據
        requiredAny:PropTypes.any.isRequired,

        // 你也能夠指定一個自定義驗證器。它應該在驗證失敗時返回
        // 一個 Error 對象而不是 `console.warn` 或拋出異常。
        // 不過在 `oneOfType` 中它不起做用。
          customProp:function(props, propName, componentName) {
            if (!/matchme/.test(props[propName])) {
              returnnewError(
                'Invalid prop `' + propName + '` supplied to' +
                ' `' + componentName + '`. Validation failed.'
              );
             }
           },

        // 不過你能夠提供一個自定義的 `arrayOf` 或 `objectOf`         // 驗證器,它應該在驗證失敗時返回一個 Error 對象。它被用        // 於驗證數組或對象的每一個值。驗證器前兩個參數的第一個是數組        // 或對象自己,第二個是它們對應的鍵。        customArrayProp:PropTypes.arrayOf(function(propValue, key, componentName, location, propFullName) {          if (!/matchme/.test(propValue[key])) {            returnnewError(              'Invalid prop `' + propFullName + '` supplied to' +              ' `' + componentName + '`. Validation failed.'             );            }           })          };

相關文章
相關標籤/搜索