vue的mvvm屬於雙向綁定,view層,model數據層,vm實現雙向綁定的控制層javascript
此種模式,再某一類項目種頗有優點:管理系統 ( OA, ERP , CRM , CMS.....) ,由於其中存在着大量表單操做css
react的mvc屬性單向數據綁定,view層,model層(數據),controller(控制層)html
1.兩種都是操做數據來影響視圖的,告別了傳統操做DOM的時代前端
model層控制view層vue
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打包的時候就不會把內容打包在一塊兒了)
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安全優化
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() }; }