腳手架:javascript
解壓兩個文件:在項目的根目錄下執行npm install////npm I 會按照package.json的配置安裝依賴模塊。css
安裝完成後,會出現一個node_modules,裏面是安裝的全部依賴的模塊。html
都是項目的根目錄。前端
npm installjava
代理是哪裏進去哪裏出來。node
.babelrc: babel轉譯的配置文件。 (放的是預設值)環境信息,插件等。react
.gitignore(忽略的信息)webpack
Index.html(網頁的HTML顯示信息,發佈的站點根目錄)ios
Jsconfig.json(vscode本身所用的)git
LICENSE()
.npmrc() 鏡像庫
Package.js(依賴信息)
README.md()
Src(js的插件信息)
App.js
Appstate.js
Index.html
Node_moudles(npm包管理器設置之後全部的依賴文件)
Webpack.config.dev.js 開發時候使用的
Webpack.config.prod.js 生產環境使用的
Npm 產生的文件,裏面記錄項目信息,全部項目依賴。
裏面包括的是版本等信息。
Start:啓動webpack的dev server開發用的web server,提供的靜態文件加載、自動刷新和熱替換HMR(hot module replacement)
HMR能夠在應用程序運行中替換,添加和刪除模塊,不須要從新加載模塊,只是變化部分替換掉,不用HMR則自動刷新頁面。
--HOT 啓動HMR
--inline默認模式,使用HMR的時候建議使用inline模式,熱替換時候會有消息顯示在控制檯。
Build使用webpack構建打包,對應npm run build
開發時候的依賴,不會打包到目標文件中。例如轉譯代碼等。不必到生產中去。
Dependencies運行的時候的依賴必須帶到項目中去,
版本號:
指定安裝版本號:
~安裝指定中和最新的版本。
^安裝指定中最高的版本,不低於指定的版本。*******建議經常使用
Latest:最新版本。
Babel轉譯的。
Css樣式:
Css-loader樣式表相關的模塊。
React-hot-loader熱加載插件。
運行時候的依賴:
Antd ant design基於react實現,後臺管理較方便。
Axios 異步請求
Polyfiill解決瀏覽器api不支持的問題,磨平差別化。
React開發的主框架。
React-router路由
React-router-dom dom綁定路由
Mobx狀態管理庫,透明化
Mobx-react mobx-react-devtools mobx和react結合的模塊。
React和mobx是一個強強聯合。
Babel轉譯的配置文件
(1)webpack.config.dev.js
符合commonjs的模塊。
Devtools:’source-map’
調試時候映射處理。
Entry入口:從入口直接找到須要打包的文件。
Output輸出:
Resolve解析
Module模塊
Test匹配條件的。
Exclude排除的,
Use使用模塊的useentries列表中的loader,
Rules中.js結尾的但不在node_modules目錄的文件使用轉譯babel-loader和熱加載loader。
加載器:
style-loader經過<style>標籤吧css添加到dom中。
Css-loader加載css
Less-loader對less的支持
Less:控制h2標記的。
Devserver,開發使用的server
Compress啓動gzip
Port啓動端口3000
Hot啓動HMR
Proxy執行訪問/api開頭路徑都代理到http://127.0.0.0:8080中
Jsconfig.json是vscode的配置文件,覆蓋當前配置。
上面的配置文件,須要更改name,version,description,須要修改repository倉庫地址,須要修改author、license信息。修改完成後,進行開發。
App-xxxxx的文檔必須放在根目錄,對於Windows下的是磁盤的根目錄。
npm start
React是Facebook開發的並開源的前端框架。
2013年開源的,react解決的是前端的MVC框架中的view視圖層的問題。
DOM是什麼?
DOM(文檔對象模型document object model)
是HTML和xml文檔,把其解析成爲dom對象,展現成爲樹的模型。
Js在瀏覽器端多數狀況下都是操做dom樹的。
選擇節點問題,經過id等進行查找等。
The document
The dom tree
將網頁全部內容映射到一顆樹形的結構的層級對象模型上,瀏覽器提供對dom支持,用戶能夠用腳本調用dom api來動態的修改dom節點,從而達到修改網頁的目的,這種修改在瀏覽器中完成,瀏覽器胡根據dom的修改重繪dom的節點部分。
修改dom從新渲染的代價比較高,前端框架爲了提升效率,儘可能減小DOM的重繪,提出了virtual DOM,全部的修改都是如今的virtual dom上面完成,經過比較算法,找出瀏覽器和dom之間的差別,使用這個差別操做dom,瀏覽器只是須要渲染這個部分變化就好了。
React實現了dom diff算法能夠高效比對vir dom和 dom的差別。
Jsx是一種Javascript和xml混寫的語法,是Javascript的擴展。
直接插入HTML語句等。
import React from 'react';
import ReactDOM from 'react-dom';
// import { render } from 'react-dom';
// import { AppContainer } from 'react-hot-loader';
// import AppState from './AppState';
// import App from './App';
// const appState = new AppState();
// render(
// <AppContainer>
// <App appState={appState} />
// </AppContainer>,
// document.getElementById('root')
// );
// if (module.hot) {
// module.hot.accept('./App', () => { render(App) })
// }
class Root extends React.Component{
render(){
return <div>javascript excise</div>;
}
}
ReactDOM.render(<Root/>,document.getElementById('root'));
Return的必須是jsx的語法。單標計必須是封口的。
Render()渲染函數,必須有return值,必須有頂級元素返回,全部元素必須閉合。
單行省略小括號,多好使用小括號。
class Root extends React.Component{
render(){
return <div>javascript <br/> excise</div>;
}
}
<br/>換行符
class Root extends React.Component{
render(){
return React.createElement('div',null,'javascript');
//return <div>javascript <br/> excise</div>;
}
}
//ReactDOM.render(<Root/>,document.getElementById('root'));
ReactDom.render(React.createElement(Root),document.getElementById('root'));
更改屬性的值:大括號等信息。
增長一個子元素:
class SubEle extends React.Component{
render(){
return <div>Sub content</div>
}
}
class Root extends React.Component{
render(){
return (
<div>
<h2>welcome to study</h2>
<br/>
<SubEle/>
</div>);
}
}
ReactDOM.render(<Root/>,document.getElementById('root'))
React組件的render函數return,只能是一個頂級元素。
Jsx語法是XML,要求全部元素必須閉合,<br/> 不能是<br>
標籤中首字母小寫就是HTML標記,首字母大寫就是組件。
要求嚴格的標記,要求全部標籤必須閉合,br也應該寫成<br />,/前面留一個空格。
單行省略小括號,多行必須使用小括號。
元素有嵌套的,多行,縮進。
Jsx表達式:使用{}括起來,若是大括號內使用了引號,會當作字符串處理。
每個react組件都有一個狀態變量state,是一個JavaScript對象,爲期定義屬性保存值。
狀態變化了,會出發UI從新渲染,使用setstate方法從新修改state的值。
State是組件內部使用的,是私有屬性。
import React from 'react';
import ReactDOM from 'react-dom';
class Root extends React.Component{
state = {
p1: 'abc',
p2:'.com'
};
render(){
this.state.p1 = 'www.abc'
return (
<div>
<div>welcome to {this.state.p1}{this.state.p2}</div>
<br />
</div>
);
}
}
ReactDOM.render(<Root />,document.getElementById('root'))
//this.state.p1 = 'www.abc'
改成下面的,不容許,不容許對更新中的state進行setState
//this.setState({p1:'www.ab'}) //不容許這樣修改,控制檯會報錯,
使用延時函數:setTimeout(裏面是一個函數)
setTimeout(()=>this.setState({p1:'www.abdd'}),5000)
class Root extends React.Component{
state = {
p1: 'abc',
p2:'.com'
};
render(){
//this.state.p1 = 'www.abc'
//this.setState({p1:'www.ab'}) //不容許這樣修改,控制檯會報錯,
setTimeout(()=>this.setState({p1:'www.abdd'}),5000)
return (
<div>
<div>welcome to {this.state.p1}{this.state.p2}</div>
<br />
</div>
);s
}
}
ReactDOM.render(<Root />,document.getElementById('root'))
Div的id是t1,鼠標按下事件就捆綁了一個函數,只要鼠標按下就會觸發調用getEventTrigger函數,瀏覽器就會給其送一個參數event,event是時間對象,當時間觸發的時候,event包含觸發這個時間的對象。
屬性 |
此事件發生在什麼時候 |
Onabort |
圖像的加載被中斷 |
Onblur |
元素失去焦點 |
Onchange |
域的內容被改變 |
Onclick |
當用戶點擊某個對象時候調用的時間句柄 |
Ondbclick |
當用戶雙擊某個對象時候調用的事件句柄 |
Onerror |
在加載文檔或圖像時候發生錯誤 |
Onfocus |
元素得到焦點 |
Onkeydown |
某個鍵盤鍵被按下 |
Onkeypress |
某個鍵盤按鍵被按下並鬆開 |
Onkeyup |
某個按鍵被鬆開 |
Onload |
一張頁面或一幅圖像完成加載 |
Onmousedown |
鼠標按鈕被按下 |
Onmousemove |
鼠標按鍵被移動 |
Onmouseout |
鼠標從某元素移開 |
Onmouseover |
鼠標移到某個元素之上 |
Onmouseup |
鼠標按鍵被鬆開 |
Onreset |
重置按鈕被點擊 |
Onresize |
窗口或框架被從新調整大小 |
Onselect |
文本被選中 |
Onsubmit |
確認按鈕被點擊 |
Onunload |
用戶退出頁面 |
import React from 'react';
import ReactDOM from 'react-dom';
class Toggle extends React.Component{
state = {flag:true};
handleClick(event){
console.log(event.target.id)
console.log(event.target === this);
console.log(this)
console.log(this.state)
this.setState({flag:!this.state.flag})
}
render(){
return <div id="t1" onClick={this.handleClick.bind(this)}>
點擊這句話,會觸發一個事件1。{this.state.flag.toString()}
</div>;
}
}
class Root extends React.Component{
state = {
p1: 'abc',
p2:'.com'
};
render(){
//this.state.p1 = 'www.abc'
//this.setState({p1:'www.ab'}) //不容許這樣修改,控制檯會報錯,
setTimeout(()=>this.setState({p1:'www.abdd'}),5000)
return (
<div>
<div>welcome to {this.state.p1}{this.state.p2}</div>
<br />
<Toggle />
</div>
);
}
}
ReactDOM.render(<Root />,document.getElementById('root'))
Toggle類
有本身的state屬性,當render完成後,網頁上有一個div標籤捆綁了一個click事件的函數,div標籤內有文本內容。
若是用過點擊左鍵,就觸發了click方法關聯的handleClick函數,在這個函數裏將狀態值改變。
狀態值state的改變將引起render重繪。
{this.handleClick.bind(this)},不能外加引號。
This.handleClick.bind(this)必定要綁定this,不然當觸發捆綁的函數時候,this是函數執行的上下文決定的,this已經不是觸發事件的對象了。
Console.log(event.target.id)取回的產生事件的對象的id,不是封裝的組件的對象,因此,console.log(event.target===this)是false,這個this是經過綁定過來的。
React的事件:
使用小駝峯命名。
使用jsx表達式,表達式中要指定事件處理函數。
不能使用return false,若是要阻止事件默認行爲,使用event.preventDefault()
Id是惟一的,堅定不能有重複的。
把react組件當作標籤使用,能夠爲其增長屬性:
組件之間利用state或者傳parent傳遞參數
修改屬性是不能夠的,由於是隻讀的this.props.name.
import React from 'react';
import ReactDOM from 'react-dom';
class Toggle extends React.Component{
state = {flag:true};
handleClick(event){
console.log(event.target.id)
console.log(event.target === this);
console.log(this)
console.log(this.state)
this.setState({flag:!this.state.flag})
}
render(){
return <div id="t1" onClick={this.handleClick.bind(this)}>
點擊這句話,會觸發一個事件1。{this.state.flag.toString()}
{this.props.school}{this.props.age}
<br />
{this.props.parent.state.p1}
{this.props.children}
</div>;
}
}
class Toggle1 extends React.Component{
state = {flag:true};
handleClick(event){
console.log(event.target.id)
console.log(event.target === this);
console.log(this)
console.log(this.state)
this.setState({flag:!this.state.flag})
}
render(){
return <div id="t2" onClick={this.handleClick.bind(this)}>
點擊這句話,會觸發一個事件2。{this.state.flag.toString()}
<br />
{this.props.name}
<hr />
{this.props.age}
{this.props.parent.state.p2}
</div>;
}
}
class Root extends React.Component{
state = {
p1: 'abc',
p2:'.com'
};
render(){
//this.state.p1 = 'www.abc'
//this.setState({p1:'www.ab'}) //不容許這樣修改,控制檯會報錯,
setTimeout(()=>this.setState({p1:'www.abdd'}),5000)
return (
<div>
<div>welcome to {this.state.p1}{this.state.p2}</div>
<br />
<Toggle school='abc' age= '20' parent={this} >
</Toggle>
<Toggle1 name='tom' age= '10' parent={this}/>
</div>
);
}
}
ReactDOM.render(<Root />,document.getElementById('root'))
注意訪問parent送進去的是this,訪問實例自己的屬性的方式是利用this.props.state.p1的值
利用construc(props)。
Super()調用父類的。
只要extends的,必須利用super()調用。Props做爲參數傳入。
import React from 'react';
import ReactDOM from 'react-dom';
class Toggle extends React.Component{
constructor(props){
console.log('Toggle')
super(props)
this.state = {flag:true};
}
handleClick(event){
console.log(event.target.id)
console.log(event.target === this);
console.log(this)
console.log(this.state)
this.setState({flag:!this.state.flag})
}
render(){
return <div id="t1" onClick={this.handleClick.bind(this)}>
點擊這句話,會觸發一個事件1。{this.state.flag.toString()}
{this.props.school}{this.props.age}
<br />
{this.props.parent.state.p1}
{this.props.children}
</div>;
}
}
class Toggle1 extends React.Component{
constructor(props){
console.log('Toggle1')
super(props)
this.state = {flag:true};
}
handleClick(event){
console.log(event.target.id)
console.log(event.target === this);
console.log(this)
console.log(this.state)
this.setState({flag:!this.state.flag})
}
render(){
return <div id="t2" onClick={this.handleClick.bind(this)}>
點擊這句話,會觸發一個事件2。{this.state.flag.toString()}
<br />
{this.props.name}
<hr />
{this.props.age}
{this.props.parent.state.p2}
</div>;
}
}
class Root extends React.Component{
state = {
p1: 'abc',
p2:'.com'
};
render(){
//this.state.p1 = 'www.abc'
//this.setState({p1:'www.ab'}) //不容許這樣修改,控制檯會報錯,
setTimeout(()=>this.setState({p1:'www.abdd'}),5000)
return (
<div>
<div>welcome to {this.state.p1}{this.state.p2}</div>
<br />
<Toggle school='abc' age= '20' parent={this} >
</Toggle>
<Toggle1 name='tom' age= '10' parent={this}/>
</div>
);
}
}
ReactDOM.render(<Root />,document.getElementById('root'))
組件的聲明週期可分爲三個狀態。
Mounting:已插入真實dom。
Updating:正在被從新渲染。
Unmounting:已移除真實dom。
方法以下:
(1)裝載組件觸發:
Componentwillmount在渲染前調用,在客戶端也在服務器端,指揮在裝載前調用一次。
Componentdidmount:在第一次渲染後調用,只要是在客戶端,以後的組件已經生成對應的dom結構,能夠經過this.getdomnode()來進行訪問, 想與其餘的Javascript框架一塊兒使用,在這個方法中調用setTimeout,setinterval或者發送ajax請求等操做,只是在裝載完後調用一次,在render以後。
(2)更新組件觸發,這些方法不會再首次render組件的週期調用。
Componentwillreceiveprops(nextprops)在組件接受到一個新的prop時候被調用,在初始化render時候不會調用。
Shouldcomponentupdae(nextprops,nextstate)返回布爾值,在組件接受到新的Props或者state時候被調用,在初始化或者使用forceupdate時候不被調用。(若是設置爲false,就不容許更新組件。)
Componentwillupdate(nextprops,nextstate)在組件接受到新的props或者state還沒render時候被調用,在初始化不會調用。
Componentdidupdate(prevprops,prevstate)在組件完成後更新後當即調用,在初始化時候不會被調用。
(3)卸載組件觸發
ComponentwillUNmount在組件從dom中移除的時候當即被調用
圖中,constructor構造器是最先執行的函數,觸發更新生命週期的函數,須要更新state或者props。
import React from 'react';
import ReactDOM from 'react-dom';
class Sub extends React.Component{
constructor(props){
console.log('sub con')
super(props)
this.state = {count:0}
}
handleClick(event){
this.setState({count:this.state.count + 1});
}
render(){
console.log('sub render')
return <div id='sub'onClick={this.handleClick.bind(this)}>
Sub's count = {this.state.count}
</ div>
}
componentWillMount(){
//第一次render以前
console.log('sub componentwillmount')
}
componentDidMount(){
//第一次render以後
console.log('sub componentDidMount')
}
componentWillUnmount(){
//清理工做
console.log('sub componentWillUnmount ')
}
}
class Root extends React.Component{
constructor(props){
console.log('root con')
super(props)
this.state = {}
}
render(){
return <div>
<Sub />
</ div>
}
}
ReactDOM.render(<Root />,document.getElementById('root'))
順序是constructor =》 componentwillmount =》 render =》 componentdidmount –state或props改變,render。
import React from 'react';
import ReactDOM from 'react-dom';
import { ENGINE_METHOD_DIGESTS } from 'constants';
class Sub extends React.Component{
constructor(props){
console.log('sub con')
super(props)
this.state = {count:0}
}
handleClick(event){
this.setState({count:this.count + 1});
}
render(){
console.log('sub render')
return <div id='sub'onClick={this.handleClick.bind(this)}>
Sub's count = {this.state.count}
<a style={{height:200+'px',color:'red',backgroundColor:'#f0f0f0'}} >
</ a>
</ div>
}
componentWillMount(){
//第一次render以前
console.log('sub componentwillmount')
}
componentDidMount(){
//第一次render以後
console.log('sub componentDidMount')
}
componentWillUnmount(){
//清理工做
console.log('sub componentWillUnmount ')
}
componentWillReceiveProps(nextProps){
//props變動時候,接受新的props,交給shouldComponentUpdate
//props組件內只讀,只能從外部改變
console.log(this.props)
console.log(nextProps)
console.log('sub componentWillReceiveProps',this.state.count);
}
shouldComponentUpdate(nextProps,nextState){
//是否組件更新,props或state方式改變時候,返回布爾值,true纔會更新
console.log('sub shouldComponentUpdate',this.state.count,nextState)
return true
}
componentWillUpdate(nextProps,nextState){
//贊成更新後,真正更新以前,調用render
console.log('sub componentWillUpdate',this.state.count,nextState)
}
componentDidUpdate(prevProps,prevState){
//贊成更新後,真正更新後,在render以後調用。
console.log('sub componentDidUpdate',this.state.count,prevState)
}
}
class Root extends React.Component{
constructor(props){
console.log('root con')
super(props)
this.state = {}
}
render(){
return <div>
<Sub />
</ div>
}
}
ReactDOM.render(<Root />,document.getElementById('root'))
Componentwillmount第一次裝載,在首次render以前,例如控制state、props。
Componentdidmount第一次裝載結束,在首次render以後,控制state,props。
Componentwillreceiveprops在組件內部,props是隻讀不可變的,這個函數接受到新的props,能夠對props作一些處理,this.props={name:‘root’}這就是偷樑換柱,componentwillreceiveprops觸發,也會走shouldcomponentupdate。
Shouldcomponentupdate判斷是否須要組件更新,是否render,精確的控制渲染,提升性能。
Componentwillupdate除了首次render以外,每次render前執行,componentdidupdate在render以後調用。
componentWillMount(){
//第一次render以前
console.log('sub componentwillmount')
}
componentDidMount(){
//第一次render以後
console.log('sub componentDidMount')
}
componentWillUnmount(){
//清理工做
console.log('sub componentWillUnmount ')
}
componentWillReceiveProps(nextProps){
//props變動時候,接受新的props,交給shouldComponentUpdate
//props組件內只讀,只能從外部改變
console.log(this.props)
console.log(nextProps)
console.log('sub componentWillReceiveProps',this.state.count);
}
shouldComponentUpdate(nextProps,nextState){
//是否組件更新,props或state方式改變時候,返回布爾值,true纔會更新
console.log('sub shouldComponentUpdate',this.state.count,nextState)
return true
}
componentWillUpdate(nextProps,nextState){
//贊成更新後,真正更新以前,調用render
console.log('sub componentWillUpdate',this.state.count,nextState)
}
componentDidUpdate(prevProps,prevState){
//贊成更新後,真正更新後,在render以後調用。
console.log('sub componentDidUpdate',this.state.count,prevState)
}
}
也叫作函數式組件。
許多時候組件簡單不須要state狀態,也不須要聲明周期函數,無條件組件很好的知足了須要,無狀態組件提供了一個參數props,返回一個react元素,無狀態組件函數自己就是render函數。
import React from 'react';
import ReactDOM from 'react-dom';
//let Root = props =><div>{props.shoolname}</div>;
//ReactDOM.render(<Root shoolname='abc' />,document.getElementById('root'))
function Root(props){
return <div> {props.name}</div>
}
ReactDOM.render(<Root name='bcd'/>,document.getElementById('root'))
import React from 'react';
import ReactDOM from 'react-dom';
let wrapper = function (Component){
function _wrapper(props){
return (
<div>
{props.name}
<hr />
<Component />
</ div>
)
}
return _wrapper
}
let Root = props =><div>Root</ div>
let NeeComp = wrapper(Root)
ReactDOM.render(<NeeComp name='abc' />,document.getElementById('root'))
import React from 'react';
import ReactDOM from 'react-dom';
let wrapper = function (Component){
return props=>(
<div>
{props.name}
<hr />
<Component />
</ div>
)
}
let Root = props =><div>Root</ div>
let NeeComp = wrapper(Root)
ReactDOM.render(<NeeComp name='abc' />,document.getElementById('root'))
import React from 'react';
import ReactDOM from 'react-dom';
let wrapper = Component=> props =>(
<div>
{props.name}
<hr />
<Component />
</ div>
)
let Root = props =><div>Root</ div>
let NeeComp = wrapper(Root)
ReactDOM.render(<NeeComp name='abc' />,document.getElementById('root'))
import React from 'react';
import ReactDOM from 'react-dom';
let wrapper = Component=>props=>
(<div>
{props.aname}
<hr />
<Component />
</ div>
)
//let Root = props => <div>Root</ div>
@wrapper
class Root extends React.Component{
render(){
return <div> Root</ div>
}
}
let Newarpper = wrapper(Root)
ReactDOM.render(<Newarpper aname='abc' />,document.getElementById('root'))
import React from 'react';
import ReactDOM from 'react-dom';
let wrapper = Components=>props=>
(<div>
{props.aname}
<hr />
<Components {...props} />
</ div>
)
//let Root = props => <div>Root</ div>
@wrapper
class Root extends React.Component{
render(){
return <div> Root{this.props.aname}</ div>
}
}
//let Newarpper = wrapper(Root)
ReactDOM.render(<Root aname='abc' />,document.getElementById('root'))
Root中也顯示props.name的屬性,使用 <Components {...props} />
增長屬性等。
import React from 'react';
import ReactDOM from 'react-dom';
let wrapper = id => Components=>props=>
(<div id = {id}>
{props.aname}
<hr />
<Components {...props} />
</ div>
)
//let Root = props => <div>Root</ div>
@wrapper('wrapper')
class Root extends React.Component{
render(){
return <div> Root{this.props.aname}</ div>
}
}
//let Newarpper = wrapper(Root)
ReactDOM.render(<Root aname='abc' />,document.getElementById('root'))
函數後面不能加括號調用,由於加括號返回的不是組件,而是render函數須要的內容。
要求返回的是組件,組件函數。