邂逅React 2020-7-22

前言:

終于結(jié)束了緊張的一個學(xué)期梢卸,網(wǎng)課上的挺有趣蛤高,就是課程太擠了點。這個暑假塞绿,就從React開始吧异吻。

一诀浪、為什么學(xué)習(xí)React雷猪?

首先求摇,React殊者、Vue幽污、Angular合稱當(dāng)前前端最為流行的三大框架距误,就是前端的三大將吧准潭。而國內(nèi)因為Angular相對其他兩者來說不是很受歡迎刑然,前面4月份的時候我是先學(xué)習(xí)了Vue的泼掠,由于國內(nèi)Vue和React的使用都是很多的,所以肯定都是要學(xué)習(xí)的挡逼。React是facebook于2013年開源的JS框架家坎,在HackerRank一份關(guān)于2020年最想要學(xué)習(xí)的框架中React是排名第一的虱疏。

二做瞪、邂逅React開發(fā)

React和Vue一樣都是聲明式的編程范式穿扳,這在我學(xué)習(xí)Vue的時候就嘗到了甜頭国旷,這種編程范式相對于傳統(tǒng)使用jQuery的命令式編程來說跪但,最大的區(qū)別就是將變量交給Dom元素來展示之后屡久,不管是發(fā)生了什么被环,如果想要頁面進行實時變化的話,修改那個變量的值就好了浸锨,不需要再拿到這個Dom元素然后進行重新的掛載相應(yīng)的數(shù)據(jù)柱搜。

下面通過一個案例分別使用原生和React進行實現(xiàn)來邂逅一下React的開發(fā)聪蘸。

image-20200721235019260.png

就是這么一個案例控乾,一開始顯示Hello World阱持,點擊之后顯示Hello React

原生實現(xiàn)

<h2 class="text"></h2>
    <button class="btn">改變文本</button>
    <script>
        //文本
        let message = "Hello World!!!";
        //拿到文本元素
        const textElt = document.getElementsByClassName("text")[0];
        //拿到按鈕元素
        const btnElt = document.getElementsByClassName("btn")[0];
        //設(shè)置文本內(nèi)容
        textElt.innerHTML = message;
        //添加監(jiān)聽事件
        btnElt.addEventListener("click",e=>{
            //打印點擊信息
            // console.log("點擊了文本");
            message = "Hello React!!!";
            textElt.innerHTML = message;
        })
    </script>

不管是原生也好衷咽,jQuery也好镶骗,在掛載的數(shù)據(jù)想要進行改變的時候鼎姊,都需要拿到那個Dom元素相寇,然后進行數(shù)據(jù)的修改钮科,而且設(shè)置和修改時進行的步驟是一樣的绵脯,就是重新設(shè)置了一次。

React閃亮登場

添加依賴

使用一個框架赃承,第一件事情肯定是添加依賴啦瞧剖,不同于Vue筒繁,React需要添加三個庫才能進行開發(fā)巴元。這也是React功能的多元性所引起的逮刨,業(yè)務(wù)多元也就意味著體量得越大,React在0.14版本之前沒有react-dom這個概念恢总。由于擴展了移動端的業(yè)務(wù)片仿,出現(xiàn)了React-native砂豌,所以為了分離web端和移動端開發(fā)的依賴光督,將它們共有的核心代碼放在React包中结借。而react-dom在web端和移動端完成的事情不同,在web端react-dom將jsx語法渲染成真實DOM顯示在瀏覽器中咖熟,移動端則是將jsx渲染成Android或者ios的原生控件馍管。

除了React和React-dom之外呢還需要添加一個庫咽斧,那就是Babel张惹。這個之前接觸過了岭洲,在使用ES6語法的時候就需要通過Babel給它轉(zhuǎn)成大多數(shù)瀏覽器所支持的ES5語法。而在React中其實默認下是可以不適用Babel的雷激,但是不使用Babel就需要通過React.createElement這種方式來進行React開發(fā)屎暇,代碼就非常的繁瑣并且可讀性很差根悼。而解決這種繁瑣的編寫方式的方法是使用JSX(JavaScript XML)語法進行開發(fā)挤巡,但是React默認是不能認識這種方式的矿卑,所以就要靠babel給轉(zhuǎn)成React.createElement這種方式母廷。

引入這三個庫

    <!-- 通過CDN引入React依賴 -->
    <!-- 
        為什么使用crossorigin屬性? 
        因為crossorigin屬性使得我們能夠接收到跨域的腳本錯誤消息苔悦,
        然后打印在控制臺玖详,從CDN上引入的腳本是跨域的勤讽。
    -->
    <!-- React核心庫 -->
    <script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
    <!-- React-Dom庫 -->
    <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
    <!-- babel庫向臀,將jsx語法轉(zhuǎn)換成render.createElement這種方式 -->
    <!--  你可以在任何 <script> 標簽內(nèi)使用 JSX诸狭,方法是在為其添加 type="text/babel" 屬性。-->
    <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>

初識React

    <div>Header</div>
    <div id="app">app</div>
    <div>Footer</div>
    <!-- 使用React來管理app的文本內(nèi)容 -->
    <!-- 注意:為了讓babel解析JSX語法芹彬,也就是下面render函數(shù)中的第一個參數(shù)舒帮,
        必須在script標簽這里添加一個屬性玩郊,type="text/babel" -->
    <script type="text/babel">
        let message = "hello world";
        // ReactDom.render(渲染內(nèi)容,掛載元素);渲染的內(nèi)容可以是HTML元素译红,也可以是React組件
        ReactDOM.render(<h2>{message}</h2>,document.getElementById("app"));
    </script>
    <!-- 
        React的語法和Vue還是挺大不同的临庇,Vue是直接New一個對象,然后掛載到某個元素上(使用el時),而React這里
        是直接使用一個庫中導(dǎo)出的對象已卷,然后用它的一個render函數(shù)
        淳蔼。而且React中取變量數(shù)據(jù)的語法是{}一個單花括號讳癌,而Vue中使用的是雙花括號{{mustache}}語法

        Vue中是這樣來開發(fā)
        <div id="app">
            {{message}}
        </div>
        <script src="../js/vue.js"></script>
        <script>
            const app = new Vue({
                el: '#app',
                data: {
                    message: 'Hello Vue!'
                }
            });
        </script>
     -->

現(xiàn)在就能夠?qū)essage的內(nèi)容在瀏覽器中進行一個顯示了晌坤,接下來就是實現(xiàn)上面的案例骤菠。

React案例實現(xiàn)

ReactDOM.render(
            <h2>{message}</h2>
            <button>改變文本</button>,//JSX語法這里根標簽是只能有一個的商乎,這里就和Vue相同
            //Vue在定義組件的時候也是只能有一個根標簽
            //我上面這個打出來就報錯了
            document.getElementById("app")
        )

這樣子就正確了

<script type="text/babel">
        let message = "Hello world!!!";
        function btnClick(){
            //測試是否確實能夠激發(fā)點擊事件處理函數(shù)
            console.log("the button is clicked");
            message = "Hello React!!!";
            //打印message
            console.log(message);
            /*
                對于Vue來說鹉戚,如果message改變了抹凳,那么頁面也會做出實時的響應(yīng)
                對頁面UI進行修改却桶,這里就測試React是不是也能這樣
            */
        }
        ReactDOM.render(
            <div>
                <h2>{message}</h2>
                <button onClick={btnClick}>改變文本</button>
            </div>,
            document.getElementById("app")
        )
        //在執(zhí)行了這個render函數(shù)之后颖系,app這個元素里面包含的內(nèi)容將會被這里render函數(shù)的第一個參數(shù)完全替換
        //這一點和Vue也是一樣的
    </script>
image-20200722171744393.png

經(jīng)過實測嘁扼,確實在這里react和vue是不同的趁啸。在這里不傅,如果想要UI進行重新渲染,我們就需要進行再一次的render函數(shù)商虐,就是重復(fù)的工作在做一遍秘车,一開始怎么掛載上去數(shù)據(jù)的叮趴,再掛載一次就實現(xiàn)了UI的變化眯亦。

<div id="app">
        <h2>this is app</h2>
    </div>
    <!-- jsx語法不能像這樣寫 -->
    <button onClick="btnClick();">改變文本</button>
    
    <script type="text/babel">
        let message = "Hello world!!!";
        function btnClick(){
            //測試是否確實能夠激發(fā)點擊事件處理函數(shù)
            console.log("the button is clicked");
            message = "Hello React!!!";
            //打印message
            console.log(message);
            /*
                對于Vue來說搔驼,如果message改變了,那么頁面也會做出實時的響應(yīng)
                對頁面UI進行修改扔字,這里就測試React是不是也能這樣
            */
            render();
        }
       function render(){
           /*   
                <button onClick="window.alert('hello');">改變文本</button>jsx這里和原先的html還不一樣
                事件句柄后面是不能直接添加雙引號括起來的js代碼的,必須要將這些js代碼封裝在一個函數(shù)中扭粱,然后
                通過{}語法來引用這個函數(shù)
           */
        ReactDOM.render(
            <div>
                <h2>{message}</h2>
                <button onClick={btnClick}>改變文本</button>
            </div>,
            document.getElementById("app")
        )
        //在執(zhí)行了這個render函數(shù)之后琢蛤,app這個元素里面包含的內(nèi)容將會被這里render函數(shù)的第一個參數(shù)完全替換
        //這一點和Vue也是一樣的
       }
       render();
    </script>
image-20200722172632578.png

案例確實是實現(xiàn)了,但是這其實不是我們想要的那種抛虏,因為還是像是命令式編程范式那樣進行編程博其,我們想要的應(yīng)該是message修改了,不需要我們進行操作UI就進行實時的更新的那種迂猴,那才是聲明式編程慕淡。

三、React組件化開發(fā)

想要實現(xiàn)我們上面的那種要求就需要進行組件化開發(fā)了沸毁,由于只是邂逅React開發(fā)峰髓,所以我們就先從一種組件化開發(fā)的方式進行入手傻寂。

初識React組件化

錯誤示范案例:

<div id="app"></div>
    <script type="text/babel">
        //通過React組件化的方式來實現(xiàn)上面的文本案例
        //ReactDOM.render(HTML標簽|React組件,掛載的元素)
        //React如何來定義和使用組件呢,這里介紹第一種携兵,聲明類繼承React.Components這種定義組件的方式
        //定義組件
        class App extends React.Component{
            constructor(){
                super();/*這是必須的疾掰,如果我們不寫這里會有默認的實現(xiàn),
                          但是我們一當(dāng)覆蓋了constructor函數(shù)凛虽,我們就
                          必須手動加上這一句*/
                this.message = "Hello world~~~";
            }
            //組件名首字母要大寫,為了和HTML標簽進行區(qū)分
            //組件如何告訴ReactDom.render函數(shù)需要渲染什么內(nèi)容呢?
            //答案是定義一個render函數(shù),然后返回你想要渲染的內(nèi)容,一定是render函數(shù)哈
            render(){
                /*將文本內(nèi)容抽離到成員變量中草戈,然后監(jiān)聽按鈕的點擊涨颜。
                發(fā)生了點擊后就改變變量的內(nèi)容见擦,講道理這樣就可以實時改變UI了*/
                return (
                    <div>
                        <h2>{this.message}</h2>
                        <button onClick={this.btnClick.bind(this)}>改變文本</button>
                    </div>
                )

            }
            btnClick(){
                // console.log("this button is clicked~~~~");
                //講道理,這里修改成員變量就闊以完成案例了
                this.message = "Hello React~~~";//啊這里不行啊肪凛,這里的this顯示是undefined
                /*
                                我們這個btnClick是在啥時候調(diào)用的戳葵?
                    是在button點擊后戏自,在它的事件處理函數(shù)中去回調(diào)這個這個函數(shù)见芹,在onClick內(nèi)部
                    是通過btnClick.apply(undefined)的方式去回調(diào)的缨睡,所以這里的this就給綁定了
                    undefined
                    解決方法:在事件句柄那里傳入回調(diào)函數(shù)的時候通過bind給他綁定上一個this怕午,
                    bind(obj){
                        return function() {
                            return func.apply(obj, arguments);
                        }
                    }
                    bind內(nèi)部類似做了一個這種操作羽戒,返回的這個函數(shù)在執(zhí)行的時候就算是又使用
                    apply放入了一個undefined也是無濟于事的包蓝,綁定的都是我們希望的this

                    其實在開發(fā)中this是非常靈活的硅瞧,所以為了以防以后亂掉坑四苇,不知道this到底指向哪里
                    建議去看coderwhy老師在公眾號發(fā)布的this的一篇文章
                    https://mp.weixin.qq.com/s/hYm0JgBI25grNG_2sCRlTA
                */
                 
                console.log(this.message);
                /*OK榆骚,到這里我們就能夠改變了成員變量message了碉钠,但是你會發(fā)現(xiàn)污筷,雖然成員變量確實是進行了改變了揪惦,
                但是畫面完全沒發(fā)生改變诊县,然后你猛的一驚胸嘁,一拍大腿想到诬辈,對哦,React中改變了掛載的數(shù)據(jù)是要進行再
                次的刷新的Render的秘蛔,但是挺尷尬叠赐,需要再次的是下面的ReactDOM.render而不是我們組件中的render
                惹苗,這根本調(diào)不到咋辦呢儡首?其實啊鹅髓,正如我們之前想要的一樣,雖然底層確實要再次render错蝴,但是我們不
                希望是由我們自己來調(diào)用,就跟每個女孩紙都希望自己不說男朋友都能知道自己在想啥一樣玛界。而React就
                有這么種機制,約法三章馅精,嗯嗯,建議每個女孩紙也和你的那個Ta約法三章壮不,這樣他才能知道自己有時候
                錯在哪了*/
            }
        }
        ReactDOM.render(<App/>,document.getElementById("app"));
    </script>

正確的案例實現(xiàn)

 <script type="text/babel">
        class App extends React.Component{
            constructor(){
                super();
                //React說,好吧褪贵,今天咱來約法三章躲庄,你將掛載的數(shù)據(jù)丟到state里來。這樣你要是想要改變數(shù)據(jù)了
                //請通過setState來改效扫,知會我一聲兒倔监,我就給你把UI給刷新一遍。咦菌仁,這有點像Vue中那個分發(fā)事件
                //進行狀態(tài)維護那種感覺了浩习。
                this.state = {
                    message:"Hello world~~~"
                }
            }
            render(){
                //這個事件處理函數(shù)一定要一直bind(this),不然下面都找不到this.setState
                return (
                    <div>
                        <h2>{this.state.message}</h2>
                        <button onClick={this.btnClick.bind(this)}>改變文本</button>
                    </div>
                )
            }
            btnClick(){
                this.setState({
                    message:"Hello React~~~"
                })
            }
        }
        ReactDOM.render(<App/>,document.getElementById("app"));
    </script>

這樣就實現(xiàn)了掘托,修改成員變量然后UI實時改變咯。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末籍嘹,一起剝皮案震驚了整個濱河市闪盔,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌辱士,老刑警劉巖泪掀,帶你破解...
    沈念sama閱讀 222,183評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異颂碘,居然都是意外死亡异赫,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來塔拳,“玉大人鼠证,你說我怎么就攤上這事】恳郑” “怎么了量九?”我有些...
    開封第一講書人閱讀 168,766評論 0 361
  • 文/不壞的土叔 我叫張陵,是天一觀的道長颂碧。 經(jīng)常有香客問我荠列,道長,這世上最難降的妖魔是什么载城? 我笑而不...
    開封第一講書人閱讀 59,854評論 1 299
  • 正文 為了忘掉前任肌似,我火速辦了婚禮,結(jié)果婚禮上诉瓦,老公的妹妹穿的比我還像新娘川队。我一直安慰自己,他們只是感情好垦搬,可當(dāng)我...
    茶點故事閱讀 68,871評論 6 398
  • 文/花漫 我一把揭開白布呼寸。 她就那樣靜靜地躺著,像睡著了一般猴贰。 火紅的嫁衣襯著肌膚如雪对雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,457評論 1 311
  • 那天米绕,我揣著相機與錄音瑟捣,去河邊找鬼。 笑死栅干,一個胖子當(dāng)著我的面吹牛迈套,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播碱鳞,決...
    沈念sama閱讀 40,999評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼桑李,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了窿给?” 一聲冷哼從身側(cè)響起贵白,我...
    開封第一講書人閱讀 39,914評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎崩泡,沒想到半個月后禁荒,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,465評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡角撞,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,543評論 3 342
  • 正文 我和宋清朗相戀三年呛伴,在試婚紗的時候發(fā)現(xiàn)自己被綠了勃痴。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,675評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡热康,死狀恐怖沛申,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情褐隆,我是刑警寧澤污它,帶...
    沈念sama閱讀 36,354評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站庶弃,受9級特大地震影響衫贬,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜歇攻,卻給世界環(huán)境...
    茶點故事閱讀 42,029評論 3 335
  • 文/蒙蒙 一固惯、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧缴守,春花似錦葬毫、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至村砂,卻和暖如春烂斋,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背础废。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評論 1 274
  • 我被黑心中介騙來泰國打工汛骂, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人评腺。 一個月前我還...
    沈念sama閱讀 49,091評論 3 378
  • 正文 我出身青樓帘瞭,卻偏偏與公主長得像,于是被迫代替她去往敵國和親蒿讥。 傳聞我的和親對象是個殘疾皇子蝶念,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,685評論 2 360