react腳手架和深刻理解jsx語法

react的mvc和vue的mvvm

vue的mvvm屬於雙向綁定,view層,model數據層,vm實現雙向綁定的控制層javascript

此種模式,再某一類項目種頗有優點:管理系統 ( OA, ERP , CRM , CMS.....) ,由於其中存在着大量表單操做css

react的mvc屬性單向數據綁定,view層,model層(數據),controller(控制層)html

1.兩種都是操做數據來影響視圖的,告別了傳統操做DOM的時代前端

model層控制view層vue

  • Vue基於數據劫持,攔截到最新的數據,從而從新渲染視圖
  • React是提供對應的API,經過咱們操做API,讓最新數據渲染視圖

2.都必定存在DOM的差別化渲染 (DOM DIFF)java

每一次數據更改,只把須要改變的視圖部分進行渲染node

3.react默認只實現了單向控制(只有數據影響視圖),而vue基於v-model實現了雙向控制 (其實,在視圖影響數據方式上,咱們本身也能實現,即react也能實現雙向綁定)react

題外話:在先後端整個項目的結構上,vue和react也算是隻有v層,即視圖層,mvc也是整個項目架構的名詞(model層 :建立數據模型,controller:業務層,實現各類業務邏輯,view層,即前端層),這裏的react和vue都只能說是前端 局部 的mvc和mvvmwebpack

腳手架

官方腳手架:create-react-appgit

$npm i -g create-react-app
$create-react-app xxx 基於腳手架建立項目
$npm start / build 生成項目
$npm eject 暴露webpack配置項

還有其餘熱門腳手架DvaJs , UmiJs(阿里)

腳手架默認安裝

-react

-react-dom 開發HTML頁面程序 (react-native 開發原生App的)

-react-scripts

和Vue同樣,React腳手架也默認把配置好的webpack那些東西隱藏到node_modules中了

=> vue是提供了vue.config.js讓用戶本身去修改配置項 (詳情查看vue cli官方文檔)

=>想要修改React中的webpack配置項

1.先把配置項暴露出來 yarn eject / npm run eject

2.細節點: 不可逆轉(暴露了不能再隱藏回去)+ 若是有git 先要保存修改項

config webpack配置項

​ |-webpack.config.js

​ |-webpackDevServer.config.js

​ |-path.js 存放各配置的地址文件信息(入口文件等)

​ |.....

scripts

​ |-start.js 開發環境下 npm run start 先執行這個文件

​ |-build.js 生產環境下 npm build 先執行這個文件

​ |......


1.默認狀況下,咱們會把全部須要開發引入的資源(樣式|圖片。。。)和編寫的模塊等都放到SRC目錄中(webpack自己就是打包src目錄,更具入口的index.js)

2.可是有些東西咱們仍是須要寫在public下的 index.html中

=>頁面導入最後打包的css/js ,因爲打包後的文件比較大,第一次請求頁面須要一點時間,這個時間段內,咱們看到的就是白屏效果

1)爲了解決白屏效果,咱們會在index.html中設置loading效果(這些內容是一加載頁面就展現出來)=>這個有對應插件

2)給資源作304緩存

..........

=>有一些模塊不支持CommonJs /ES6Module這種導入導出規範,此時須要咱們把這些模塊在index.html中單獨script導入進來

=>還能夠把一些公共資源直接在這裏導入 (這樣webpack打包的時候就不會把內容打包在一塊兒了)

配置向後兼容

  • browserList
  • Polyfill

JSX基礎語法與JSX語法的優勢

jsx :javascript and xml

其實也能夠將xml理解爲html ,可是這裏的html代碼並非直接運行,更像是xml裏咱們爲標籤訂義意義

jsx的基本使用:

1.最外層只能有一個根節點(通常用空標記,由於若是用div,會真實渲染一個沒有真正意義只用來包裹的div)

2.動態數據綁定用 : {}  ,{}中存放js表達式(js執行代碼得有返回的結果)

    =>{}中能夠放數組:把數組中的每一項都呈現,不含逗號

    =>{}中通常狀況不能放對象,

    => 可是若是是jsx的虛擬DOM對象,是直接能夠渲染的   

3.設置行內樣式,必須是style = {{ color:'red'}}  ,設置樣式類名須要使用的是className而不是class

4.jsx中進行的判斷通常都要基於三元運算符來完成

5.jsx中遍歷數組中的每一項,動態綁定多個jsx元素,通常都是基於數組中的map來實現(map迭代數組的同時,支持返回值)(和vue同樣,循環的對象也要加key值)
    =>咱們要在ul  li中渲染 let arr= [{name:'張三',age:25},{name:'李四',age:26}]
    =>就須要這樣:<ul>
                    {arr.map((item,index)=>{
                    return <li>
                        姓名:{item.name}
                       年齡:{item.age}
                    })} 
                <ul>
JSX的優勢:
1.JSX語法具有很強的編程性,這是vue中模板語法不具有的,因此vue重新版本(v2.xx)開始,支持了jsx語法
    =>舉例:咱們傳回一個數據,根據這個數據的不一樣的,渲染不一樣的組件,在vue的template語法中,咱們要寫一堆html代碼,每一個不一樣的組件都須要寫出來,而後根據if-else來控制display的隱藏於顯示來控制具體須要展現哪個,而在jsx語法中,咱們可使用代碼將html結構動態的組建起來,好比'h'+this.i ,這個i就能夠控制要使用第幾檔的標題標籤
    =>這就是jsx的強編程性和template的弱編程性
2.JSX語法具有過濾效果(過濾非法內容),有效防止XSS攻擊
    =>自行了解XSS安全優化

把JSX語法=>虛擬DOM對象=>真實DOM

1.基於babel-preset-react-app把JSX語法變爲React.createElement的模式
    =>如div標籤都會轉換成React.createElement("div",null,React.createElement(..))
    =>React.createElement的第一個屬性爲div的標籤名,第二個爲標籤的屬性(對象),第三個爲子元素
    =>每遇到元素標籤(或者組件)都要createElement

React.createElement = function (type,props,...children){
    let jsxOBJ ={
        type:type
        props:{}
    };
    //=>傳遞了屬性,把傳遞的屬性都放置到jsx-OBJ的props中
    if(props !==null){
        //基於es6實現淺克隆
        jsxOBJ.props= {...props}
    }
    //=>若是傳遞了子元素,還須要給jsxOBJ的props中設置children屬性
    if(children.length > 0){
        jsxOBJ.props.children = children;
        //若是隻有一項,則把第一項賦值給jsxOBJ.props.children便可
        if(children.length ===1){
            jsxOBJ.props.children = children[0]
        }
    }
    
    return jsxOBJ;
};

2.基於React.createElement方法的執行,建立出虛擬DOM對象(jsx對象)
    =>首先是一個對象
    =>type屬性存儲的是標籤名(或者組件)
    =>props屬性:沒有傳遞任何屬性,也沒有任何的子元素,則爲空對象,把傳遞給createElement的屬性,都賦值給props;若是有子元素,則默認新增一個children的屬性,多是一個值,也多是一個數組
    
3.基於ReactDOM.render把建立的虛擬DOM對象渲染到頁面指定的容器中
    =>ReactDOM.render([JSX-OBJ],[container],[callback])
    =>參數意義:1.虛擬dom  2.容器   3.回調函數(在這個回調函數中,能夠獲取到真實的dom,只不過項目中通常不用這個參數)
    
    ReactDOM.render = function render (jsxobj ,container,callback){
        let {type ,props}= jsxOBJ;
        //=>建立dom元素
        if(typeof type === "string"){
            //建立dom對象(真實dom)
            let element = document.createElement(type);
            //給dom設置傳入的屬性
            for(let key in props){
                if( !props.hasOwnProperty(key)) break;
                if(key === 'className'){
                   element.setAttribute('class',props[key]);
                    continue;
                }
                if(key === 'style'){
                    let styOBJ = props['style']
                    for(let attr in styOBJ){
                        if(!styOBJ.hasOwnProperty(attr)) break;
                        element.style[attr] = styOBJ;
                    }
                }
                //關於子元素的處理
                if(key === 'children'){
                    //統一爲數組
                    let children = props['children'];
                    !Array.isArray(children) ? children = [children] : null ;
                    //循環子元素
                    children.forEach(item=>{
                       //若是是文本,直接建立文本節點賦值給element便可,若是是新的虛擬dom對象則須要重複調用render方法,把新建的dom對象增長給element(遞歸)
                        if(typeof item ==== "string"){
                            element.appendChild(document.createTextNode(item))
                            return;
                        }
                        render(item,element);
                    });
                    continue;
                }
                element.setAttribute(key,props[key]);
            }
            //增長到指定容器當中
            container.appendChild(element);
            //觸發回調函數
            callback && callback()
        };
        
    }
相關文章
相關標籤/搜索