React基礎(chǔ)與項(xiàng)目搭建

網(wǎng)絡(luò)圖片

React簡介

React在2013年5月開源恃逻。
React可能是將來web開發(fā)的主流工具枪狂。
React不是一個(gè)完整的MVC框架桂躏,頂多充當(dāng)一個(gè)View層。

  • MVC(Model+View+Controller)

不適用于前端開發(fā)劳殖,因?yàn)閂iew不允許知道用戶的輸入督暂,用戶的輸入是從Controller這一層進(jìn)入。然而用戶直接通過view層交互解藻,所以不可能不監(jiān)聽View層。
MVVM(Model+View+ViewModel)——MVC的演變葡盗,更適合前端的開發(fā)模式螟左。

  • JSX 解析器

將JSX轉(zhuǎn)化成JS,在JS中直接編寫HTML觅够。
通過組建的state來維護(hù)改變HTML DOM中的內(nèi)容胶背。
所有和Dom有關(guān)的都應(yīng)該通過框架來維護(hù),
將各功能做成組建——模板(容器)喘先、控件钳吟。

  • React組件及數(shù)據(jù)傳遞

React是一個(gè)組件化的框架,在項(xiàng)目開發(fā)之初需要將組件分化


搭建React Start Kit

1. 新建項(xiàng)目文件夾

這里取名newReactproject窘拯。
在該目錄下打開終端红且,初始化package.json

npm init

(可以輸入項(xiàng)目的名稱,這里為new-react-project)

2. 安裝插件

npm install --dev-save browser-sync gulp gulp-webpack jsx-loader react react-dom

3. JSX轉(zhuǎn)換成JS的方法

在gulpfile.js中用webpack來將.jsx文件轉(zhuǎn)化為.js文件
(gulp的使用在其他的章節(jié)里面會(huì)詳細(xì)說明)

var webpackConfig = {
    output:{
        filename: 'index.js'
    },
    devtool: 'inline-source-map',
    module:{
        loaders:[
            {test: /\.jsx$/, loader: 'jsx-loader'}
        ]
    },
    resolve:{
        extensions:['','.js','.jsx']
    }
}

gulp.task('script',function(){
    gulp.src('./jsx/index.jsx') //以index.jsx為程序的入口
        .pipe(webpack(webpackConfig))
        .pipe(gulp.dest('./www/script/'))
        .pipe(browserSync.stream());//同步瀏覽器
})

如此一來涤姊,就可以在.jsx文件中撰寫開發(fā)代碼了暇番。

同時(shí),需要注意的是:index.jsx中需要引用react

var React = require('react');
var ReactDom = require('react-dom')

如果需要在index.jsx中引用的組件思喊,例如header,footer等壁酬,需要使用module.exports

module.exports = React.createClass({
    render:function(){
        return <p>這是一個(gè)React頁面</p>
    }
})

注意:實(shí)際項(xiàng)目中,node_modules文件會(huì)被刪除 恨课,那么運(yùn)行項(xiàng)目的時(shí)候需要在終端輸入以下命令:

npm install gulp-cli -g
npm install
gulp

4. render語法

render一個(gè)變量時(shí)舆乔,要用html的方法來寫。
例如:

ReactDom.render(<Main />,document.getElementById('main'));

前面一個(gè)指render的內(nèi)容剂公,后一個(gè)變量是render的目的地

注意:ReactDom.render是新版本的寫法希俩,舊版本是React.render()

//jsx語法中類名:
className="className";

//jsx語法中樣式:
style={{background:'#f00'}}
//jsx語法:
<tag prop={a:value}>{children}</tag>

//轉(zhuǎn)換成js是:
React.createElement(tag, {a:value}, children)

創(chuàng)建一個(gè)組件類,需要注意的幾點(diǎn):

  • React中創(chuàng)建的組件類以大寫字母開頭纲辽,駝峰命名法
  • 在React中使用React.createClass方法創(chuàng)建一個(gè)組件類
  • 核心代碼:每個(gè)組件類都必須實(shí)現(xiàn)自己的render方法颜武。輸出定義好的組件模板贫母。返回值:null、false盒刚、組件模板
  • 注意:組件類只能包含一個(gè)頂層標(biāo)簽

5. React Component

  • render:渲染html的方法
  • getInitialState: 返回初始化的State的方法
  • getDefaultProps:返回默認(rèn)props的方法
    (state維護(hù)component內(nèi)部的狀態(tài)變化腺劣,props是component的外部的參數(shù)傳入component的方式)
  • propTypes:定義props的類型的屬性
  • mixins:用來合并兩個(gè)組件的屬性
  • statics:定義靜態(tài)對(duì)象的屬性
  • displayName:定義該類在Debug信息中顯示的名稱

6. Props

Props是組件自身的屬性,一般用于嵌套的內(nèi)外層組件中因块,負(fù)責(zé)傳遞信息(通常是由父層組件向子組件傳遞)

注意:props對(duì)象中的屬性與組件的屬性一一對(duì)應(yīng)橘原,不要直接去修改props中的屬性值。

//定義WebName
var WebName = React.createClass({
    render:function(){
        return <h1>{this.props.webname}</h1>;
    }
})

//定義WebLink
var WebLink = React.createClass({
    render:function(){
        return <a href={this.props.weblink}>{this.props.weblink}</a>;
    }
})

//定義WebShow
var WebShow = React.createClass({
    render:function(){
        return (
            <div>
                <WebName webname={this.props.wname} />
                <WebLink weblink={this.props.wlink} />
            </div>
        );
    }
})

//渲染
ReactDOM.render(
    <WebShow wname="網(wǎng)站名稱" wlink="http://www.baidu.com" />,
    document.getElementById("container")
)
  • ...this.props:

Props提供的語法糖涡上,可以將父組件中的全部屬性都復(fù)制給子組件

例如:定義一個(gè)組件Link趾断,Link組件中只包含一個(gè)<a>,我們不給<a>設(shè)置任何屬性吩愧,所有屬性全部從父組件膚質(zhì)得到芋酌。代碼如下:

var Link = React.createClass({
    render:function(){
        return <a {...this.props}>{this.props.name}</a>
    }
});

ReactDOM.render(
    <Link  name="百度"/>,
    document.getElementById("container")
)
//這樣父組件上的屬性href和name都會(huì)被復(fù)制到子組件Link中的<a>上。
  • this.props.children:

children是一個(gè)例外雁佳,不是跟組件的屬性對(duì)應(yīng)的脐帝。children表示組建的所有子節(jié)點(diǎn)

var ListComponent = React.createClass({
    render:function(){
        return (
            <ul>
                {
                    /*
                    列表項(xiàng)數(shù)量以及內(nèi)容不確定,在創(chuàng)建模板時(shí)才能確定
                    利用this.props.children從父組件獲取需要展示的列表項(xiàng)內(nèi)容
                    
                    獲取到列表項(xiàng)內(nèi)容后糖权,需要遍歷children逐行進(jìn)行設(shè)置
                    使用React.Children.map方法
                    該方法的返回值:數(shù)組對(duì)象
                    */
                    React.Children.map(this.props.children, function(child){
                        //child是便利得到的父組件的子節(jié)點(diǎn)
                        return <li>{child}</li>
                    })
                }
            </ul>
        )
    }
});

//渲染
ReactDOM.render(
    (
        <ListComponent>
            <h1>百度</h1>
            <a >http://www.baidu.com</a>
        </ListComponent>
    ),
);

7. 屬性驗(yàn)證 propTypes

組件類的屬性堵腹,用于驗(yàn)證組建實(shí)例的屬性是否符合要求

var ShowTitle = React.createClass({
    propTypes: {
        //title數(shù)據(jù)類型必須為字符串
        title:React.PropTypes.string.isRequired
    },
    render:function(){
        return <h1>{this.props.title}</h1>
    }
});

ReactDOM.render(
    <ShowTitle title="123"  />,
    document.getElementById("container")
)
  • 設(shè)置組件屬性的默認(rèn)值

通過實(shí)現(xiàn)組件的getDefaultProps方法,對(duì)屬性設(shè)置默認(rèn)值星澳。

var MyTitle = React.createClass({
    getDefaultProps: function(){
        return {
            title: "百度"
        };
    },
    render: function(){
        return <h1>{this.props.title}</h1>
    }
});

ReactDOM.render(
    <MyTitle />,
    document.getElementById("container")
);

8. state:

state和props一樣都是組件自身的屬性疚顷,都可以用來傳遞數(shù)據(jù)。
在和用戶交互的過程中禁偎,組件的狀態(tài)可能需要更新腿堤,就會(huì)觸發(fā)組件的重新渲染。

先舉個(gè)例子說明React事件的引用:

//定義一個(gè)button組件如暖,綁定onClick事件

//React中的事件名稱首字母小寫笆檀,駝峰命名法

var MyButton = React.createClass({
    handleClick: function(){
        alert('點(diǎn)擊按鈕觸發(fā)的效果');
    },
    render: function(){
        return (
            <button onClick={this.handleClick}>{this.props.buttonTitle}</button>
        )
    }
});

ReactDOM.render(
    <MyButton buttonTitle="按鈕" />,
    document.getElementById("container")
);

在知道事件引用的方法后,再舉個(gè)經(jīng)典案例:

需求:創(chuàng)建一個(gè)CheckButton的組件装处,包含一個(gè)checkbox類型的input误债,復(fù)選框在選中和未選中的兩種狀態(tài)下回顯示不同的文字浸船,即根據(jù)狀態(tài)渲染妄迁。

var CheckButton = React.createClass({
    //定義初始狀態(tài)
    getInitialState: function(){
        return {
            //在這個(gè)對(duì)象中設(shè)置的屬性將會(huì)存儲(chǔ)在state中
            //默認(rèn)狀態(tài)是:未選中
            isCheck: false
        }
    },
    //定義事件綁定的方法
    handleChange: function(){
        //修改狀態(tài)值,通過this.state讀取設(shè)置的狀態(tài)值
        this.setState({
            isCheck: !this.state.isCheck
        });
    },
    
    render:function(){
        //根據(jù)狀態(tài)值李命,設(shè)置顯示的文字
        //在JSX語法中登淘,不能直接使用if..else函數(shù),使用三目運(yùn)算符
        var text = this.state.isCheck ? "已選中" : "未選中";
        
        return (
            <div>
                <input type="checkbox" onChange={this.handleChange} />
                {text}
            </div>
        );
    },
});

//渲染
ReactDOM.render(
    <CheckButton />,
    document.getElementById("container")
);

需要注意的時(shí):當(dāng)state發(fā)生變化時(shí)封字,會(huì)調(diào)用組件內(nèi)部的render方法

  • 表單

舉例說明:

需求:定義一個(gè)組件黔州,將用戶在輸入框內(nèi)輸入的內(nèi)容進(jìn)行實(shí)時(shí)顯示
分析:組件與用戶交互過程中耍鬓,存在狀態(tài)的變化,即輸入框的值流妻。

var Input = React.createClass({
    getInitialState: function(){
        return (
            value: "請(qǐng)輸入"
        )牲蜀;
    },
    handleChange: function(event){
        //通過event.target.value讀取用戶輸入的值
        this.setState({
            value: event.target.value
        });
    },
    render: function(){
        var value = this.target.value;
        return (
            <div>
                <input type="text" value={value} onChange={this.handleChange} />
                <p>{value}</p>
            </div>
        )
    },
});

ReactDOM.render(
    <input />,
    document.getElementById("container")
);

9. React Component生命周期時(shí)間

組件的生命周期分為三個(gè)狀態(tài)

  1. Mounting: 組件掛載,已插入真實(shí)DOM

    相關(guān)接口:

    (1)componentWillMount - 組件將要掛載绅这。
    在render之前執(zhí)行涣达,但僅執(zhí)行一次,即使多次重復(fù)渲染該組件证薇,或者改變了組件的state

    (2)componentDidMount - 組件已經(jīng)掛載度苔。
    在render之后執(zhí)行,同一個(gè)組件重復(fù)渲染只執(zhí)行一次

  2. Updating: 組件更新浑度,正在被重新渲染

    相關(guān)接口:

    (1)componentWillReceiveProps(object nextProps)- 已加載組件收到新的props之前調(diào)用寇窑,注意組件初始化渲染時(shí)則不會(huì)執(zhí)行

    (2)shouldComponentUpdate (object nextProps, object nextState) - 組件判斷是否重新渲染時(shí)調(diào)用。該接口實(shí)際是在組件收到了新的props或者新的state的時(shí)候會(huì)立即調(diào)用箩张,然后通過下面兩個(gè)方法來進(jìn)行更新

    (3)componentWillUpdate (object nextProps, object nextState) - 組件將要更新

    (4)componentDidUpdate (object prevProps, object prevState) - 組件已經(jīng)更新

  3. Unmounting: 組件移出甩骏,已移出真實(shí)DOM

    相關(guān)接口:

    componentWillUnmount - 在組件要被移除之前的時(shí)間點(diǎn)觸發(fā),可以利用該方法來執(zhí)行一些必要的清理組件的工作

生命周期中與props和state相關(guān)的接口:

(1)getDefaultProps - 設(shè)置props屬性默認(rèn)值

(2)getInitialState - 設(shè)置state屬性初始值

總結(jié)下來先慷,一共九個(gè)接口横漏,如下:

  • componentWillMount:組件的html即將加載時(shí)調(diào)用
  • componentDidMount:組件的html已經(jīng)加載時(shí)調(diào)用
  • componentWillReceiveProps:組件props改變時(shí)調(diào)用
  • shouldComponentUpdate:判定組件是否更新HTML
  • componentWillUpdate:組件即將更新HTML時(shí)調(diào)用
  • componentDidUpdate:組件HTML更新完后調(diào)用
  • componentWillUnmount:組件HTML即將卸載時(shí)調(diào)用
  • getDefaultProps:設(shè)置props屬性默認(rèn)值
  • getInitialState:設(shè)置state屬性初始值

組件的生命周期可分為四個(gè)階段創(chuàng)建實(shí)例化熟掂、更新缎浇、銷毀

生命周期個(gè)階段介紹

var Demo = React.createClass({
    /*
    一、創(chuàng)建階段
        流程:只調(diào)用getDefaultProps方法
    */
    getDefaultProps: function(){
        //在創(chuàng)建類的時(shí)候被調(diào)用赴肚,設(shè)置this.props的默認(rèn)值
        console.log("getDefaultProps");
        return {};
    },
    
    /*
    二素跺、實(shí)例化階段
        流程:
        getInitialState, 
        componentWillMount, 
        render, 
        componentDidMount
    */
    getInitialState: function(){
        //設(shè)置this.state的默認(rèn)值
        console.log("getInitialState");
        return {};
    },
    componentWillMount: functon(){
        //在render之前調(diào)用
        console.log("componentWillMount");
    },
    render:function(){
        //渲染并返回一個(gè)虛擬DOM
        console.log("render");
        return <div>Hello React</div>
    },
    componentDidMount: function(){
        //在render之后調(diào)用
        //在該方法中,React會(huì)使用render方法返回的虛擬DOM對(duì)象創(chuàng)建真實(shí)的DOM結(jié)構(gòu)
        //可以在這個(gè)方法中讀取DOM節(jié)點(diǎn)
        console.log("componentDidMount");
    },
    
    /*
    三誉券、更新階段
        流程:
        componentWillReceiveProps, 
        shouldComponentUpdate (如果返回值是false指厌,后三個(gè)方法不執(zhí)行),
        componentWillUpdate, 
        render, 
        componentDidUpdate
    */
    componentWillReciveProps: function(){
        console.log("componentWillReciveProps")
    },
    shouldComponentUpdate: function(){
        //是否需要更新
        console.log("shouldComponentUpdate");
        return true;
    },
    componentWillUpdae: function(){
        console.log("componentWillUpdae");
    },
    componentDidUpdate: functon(){
        console.log("componentDidUpdate")
    },
    
    /*
    四、銷毀階段
        流程:componentWillUnmount
    */
    componentWillUnmount: function(){
        console.log("componentWillUnmount")
    },
});

//第一次創(chuàng)建并加載組件
//將得到以下順序:getDefaultProps,getInitialState,componentWillMount,render,componentDidMount
ReactDOM.render(
    <Demo />,
    document.getElementById("container")
);

//第二次創(chuàng)建并加載組件
//將在第一次加載的基礎(chǔ)上踊跟,添加以下順序:componentWillReceiveProps,shouldComponentUpdate,componentWillUpdate,render,componentDidUpdate
ReactDOM.render(
    <Demo />,
    document.getElementById("container")
);

//移除組件
ReactDOM.unmountComponentAtNode(document.getElementById("container"))

10. 設(shè)置組件的樣式

  • 內(nèi)連樣式
  • 對(duì)象樣式
  • 選擇器樣式

注意:在ReactHTML5中踩验,樣式的書寫方式是有所區(qū)別的

主要體現(xiàn)在:

  • HTML5以;結(jié)尾商玫,React以箕憾,結(jié)尾
  • HTML5中key、value都不加引號(hào)拳昌,React中屬于JavaScript對(duì)象袭异,key的名字不能出現(xiàn)“-”,需要使用駝峰命名法炬藤。如果value為字符串御铃,需要加引號(hào)碴里。
  • HTML5中,value如果是數(shù)字上真,需要帶單位咬腋,React中不需要帶單位。
//樣式
<style>
    .pStyle {
        font-size:20px;
    }
</style>

//創(chuàng)建設(shè)置h1樣式對(duì)象
var hStyle = {
    backgroundColor:"green",
    color:"red"
}

var ShowMessage = React.createClass({
    render:function(){
        return(
            //內(nèi)連樣式
            <div style={{backgroundColor:"yellow",borderWidth:5,borderColor:"black",borderStyle:"solid"}}> 
                //對(duì)象樣式
                <h1 style={hStyle}>{this.props.firstRow}</h1>
                //選擇器樣式
                <p className="pStyle">{this.props.secondRow}</p>
            </div>
        )
    }
})

//渲染效果
ReactDOM.render(
    <ShowMessage firstRow="第一行" secondRow="第二行"/>,
    document.getElementById("container")
)

注意:在React中使用選擇器樣式設(shè)置組件樣式時(shí)睡互,屬性名不能使用class帝火,因?yàn)?code>class是React中的保留字,需要使用className替換湃缎。
類似的還有使用htmlfor替換for犀填,因?yàn)?code>for也是React中的保留字。

11. 復(fù)合組件 —— 也稱為組合組件嗓违,父子組件(創(chuàng)建多個(gè)組件合成一個(gè)組件)

//定義WebName組件
var WebName = React.createClass({
    render:function(){
        return <h1>網(wǎng)站名稱</h1>;
    }
});

//定義WebLink組件
var WebLink = React.createClass({
    render:function(){
        return <a >http://www.baidu.com</a>;
    }
});

//定義WebShow復(fù)合組件
var WebShow = React.createClass({
    render:function(){
        return (
            <div>
                <WebName />
                <WebLink />
            </div>
        );
    }
    
});

//渲染
ReactDOM.render(
    <WebShow />,
    document.getElementById("container")
);

注:以上所有內(nèi)容都是本人的學(xué)習(xí)筆記和總結(jié)九巡,僅供學(xué)習(xí)和參考,如果有遺漏或者不當(dāng)?shù)牡胤秸?qǐng)諒解蹂季,請(qǐng)勿轉(zhuǎn)載冕广。

@anMoo韓魔
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市偿洁,隨后出現(xiàn)的幾起案子撒汉,更是在濱河造成了極大的恐慌,老刑警劉巖涕滋,帶你破解...
    沈念sama閱讀 211,265評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件睬辐,死亡現(xiàn)場離奇詭異,居然都是意外死亡宾肺,警方通過查閱死者的電腦和手機(jī)溯饵,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來锨用,“玉大人丰刊,你說我怎么就攤上這事≡鲇担” “怎么了啄巧?”我有些...
    開封第一講書人閱讀 156,852評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長掌栅。 經(jīng)常有香客問我秩仆,道長,這世上最難降的妖魔是什么渣玲? 我笑而不...
    開封第一講書人閱讀 56,408評(píng)論 1 283
  • 正文 為了忘掉前任逗概,我火速辦了婚禮,結(jié)果婚禮上忘衍,老公的妹妹穿的比我還像新娘逾苫。我一直安慰自己,他們只是感情好枚钓,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,445評(píng)論 5 384
  • 文/花漫 我一把揭開白布铅搓。 她就那樣靜靜地躺著,像睡著了一般搀捷。 火紅的嫁衣襯著肌膚如雪星掰。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,772評(píng)論 1 290
  • 那天嫩舟,我揣著相機(jī)與錄音氢烘,去河邊找鬼。 笑死家厌,一個(gè)胖子當(dāng)著我的面吹牛播玖,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播饭于,決...
    沈念sama閱讀 38,921評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼蜀踏,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了掰吕?” 一聲冷哼從身側(cè)響起果覆,我...
    開封第一講書人閱讀 37,688評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎殖熟,沒想到半個(gè)月后局待,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,130評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡菱属,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,467評(píng)論 2 325
  • 正文 我和宋清朗相戀三年燎猛,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片照皆。...
    茶點(diǎn)故事閱讀 38,617評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡重绷,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出膜毁,到底是詐尸還是另有隱情昭卓,我是刑警寧澤,帶...
    沈念sama閱讀 34,276評(píng)論 4 329
  • 正文 年R本政府宣布瘟滨,位于F島的核電站候醒,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏杂瘸。R本人自食惡果不足惜倒淫,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,882評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望败玉。 院中可真熱鬧敌土,春花似錦镜硕、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至矩欠,卻和暖如春财剖,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背癌淮。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評(píng)論 1 265
  • 我被黑心中介騙來泰國打工躺坟, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人乳蓄。 一個(gè)月前我還...
    沈念sama閱讀 46,315評(píng)論 2 360
  • 正文 我出身青樓咪橙,卻偏偏與公主長得像,于是被迫代替她去往敵國和親栓袖。 傳聞我的和親對(duì)象是個(gè)殘疾皇子匣摘,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,486評(píng)論 2 348

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