爲何要學習webpack,對一些語法糖高級語法進行解析降檔css
可以說出Webpack的做用html
可以說出webpack打包時loader加載的原理前端
可以使用開發時候的webpack配置文件vue
掌握webpack-dev-server的使用java
掌握html-webpack-plugin的使用react
瞭解什麼是webpack的發佈策略android
瞭解常見插件的使用webpack
key
值,這樣能提升咱們虛擬DOM的對比效率! cnpm i react react-dom --save
安裝react依賴包// react這個模塊,是專門用來建立虛擬DOM元素,或者建立React組件,包括組件的生命週期等一系列和虛擬DOM相關的東西,都在這個模塊中進行定義 import React from 'react' // react-dom這個模塊,是幫咱們進行DOM操做的模塊,好比說:將建立好的虛擬DOM元素,掛在到頁面指定的容器中,就是經過這個模塊進行實現的 import ReactDOM from 'react-dom'
React.createElement
來建立虛擬DOM: // React.createElement方法中,參數列表的含義: // 第一個參數:用字符串,指定要建立的元素的類型 // 第二個參數:用對象,指定要建立的元素的相關屬性 // 第三個參數:any,指定要建立的元素的子節點 // 從第三個參數開始,都是當前建立元素的子節點!!!// 建立一個div元素,這是屬性,同時設置兩個子節點 var divObj = React.createElement('div', {id:'div1', title:'this is a div'}, '彬哥好帥啊,崔剛老師更帥!', h1Obj);
ReactDOM.render
渲染虛擬DOM:ReactDOM.render(divObj , document.getElementById('app'));
在JSX語法中,出現 {} 的時候,就表示說,咱們要在 {} 內部,寫JS語法了!git
只要是符合JS語法規範的,均可以向 {} 書寫!程序員
在JSX語法中,若是想給元素添加類樣式,須要用 className 來代替 class ,由於 class 是ES6中的關鍵字!
與 className 相似,label的 for 屬性也是一個JS關鍵字,須要用 htmlFor 來代替!
使用JSX語法必需要配置webpack的loader,使用babel-loader去解析JSX語法
安裝babel-loader的命令中須要新增一個babel-preset-react
整個安裝命令:
.babelrc文件
{ "presets":["es2015","stage-0","react"], "plugins":["transform-runtime"] }
function Hello(){ return <div> {/*這是一個註釋,你確定看不到我,由於我是註釋*/} <br/> 這是一個Hello組件 </div>; }
<Hello name="zs" age={20} gender="男"></Hello>
<Hello name="zs" age={20} gender="男"></Hello>
props
來接收:(想要在頁面上顯示props屬性,須要安裝一個chrome插件,React Developer Tools)function Hello(props){ return <div> 這是一個Hello組件----- {props.name} ---- {props.age} ---- {props.gender} </div>; }
// 注意:必須導入react模塊,不然會報錯 import React from 'react' function Hello2(){ return <div> 這是一個Hello2組件 </div>; } export default Hello2
class Person extends React.Component{ // 經過報錯提示得知:在class建立的組件中,必須定義一個render函數 render(){ // 在render函數中,必須返回一個null或者符合規範的虛擬DOM元素 return <div> <h1>這是用 class 關鍵字建立的組件!</h1> </div>; } }
用構造函數建立出來的組件,和用class建立出來的組件,這兩種不一樣的組件之間的本質區別就是:有無state屬性!!! 有狀態組件和無狀態組件之間的本質區別就是:有無state屬性!
CommentList = [ { user: '張三', content: '哈哈,沙發' }, { user: '張三2', content: '哈哈,板凳' }, { user: '張三3', content: '哈哈,涼蓆' }, { user: '張三4', content: '哈哈,磚頭' }, { user: '張三5', content: '哈哈,樓下山炮' } ]
理解React中虛擬DOM的概念 理解React中三種Diff算法的概念 使用JS中createElement的方式建立虛擬DOM 使用ReactDOM.render方法 使用JSX語法並理解其本質 掌握建立組件的兩種方式 理解有狀態組件和無狀態組件的本質區別 理解props和state的區別
虛擬DOM和Diff算法:提升組件的渲染效率
建立虛擬DOM的兩種方式:
兩種組件建立的方式:
使用style添加樣式:
屬性擴散:
組件從建立、到加載到頁面上運行,再到頁面關閉組件被銷燬,這期間老是伴隨着各類各樣的事件,那麼這些事件,統稱爲組件生命週期!
在組件建立以前,會先調用 getDefaultProps(),這是全局調用一次,嚴格地來講,這不是組件的生命週期的一部分。在組件被建立並加載候,首先調用 getInitialState(),來初始化組件的狀態。
React生命週期的回調函數總結成表格以下:
組件生命週期的執行順序:
constructor()
componentWillMount()
render()
componentDidMount()
componentWillReceiveProps(nextProps)
shouldComponentUpdate(nextProps, nextState)
componentWillUpdate(nextProps, nextState)
render()
componentDidUpdate(prevProps, prevState)
// getDefaultProps方法在es6中已經棄用 // 使用下面的方式進行props的初始化 static defaultProps = { count: 0 }
// 用來進行屬性校驗,PropsTypes裏面提供了不少的數據類型,可是頁面上照常顯示,只是在開發過程當中給出了錯誤提示 // 1. npm i prop-types --save // 2. import PropTypes from 'prop-types' static propTypes = { count: PropTypes.number }
setState()
方法:// 在render方法中,可使用setState方法,可是setState方法會觸發組件從新渲染,從新調用render方法死循環 // this.setState({ // count: 1 // })
// 使用原生的方式設置點擊事件 // document.getElementById('btn').onclick = () => {· // this.setState({ // count: this.state.count + 1 // }) // }
onClick
事件:<input type="button" value="日本又死人了,柯南要破案了" onClick={ this.onclick } />
onclick = ()=> { console.log('點擊事件'); // 若是不用箭頭函數的方式,這裏獲取的this是null // 不是原生js點擊事件裏面獲取的對象 console.log(this); this.setState({ count: this.state.count + 1 }) }
ref
屬性:<div ref='div1'>小五郎脖子上紮了{this.state.count}針</div>
this.refs
來獲取對應的引用:console.log('shouldComponentUpdate---' + this.refs.div1.innerHTML);
// 組件是否應該已經新 // 這個方法有返回值,必須是bool類型的值 // 若是是false說明要阻斷組件的更新 // 若是是true 組件更新 // 裏面使用this.state方式獲取的state對象是更新以前的 // 若是要使用最新的,使用參數的形式進行獲取 shouldComponentUpdate(nextProps, nextState) { console.log('shouldComponentUpdate---' + this.refs.div1.innerHTML); // console.log(this.state.count + ' ------------- ' + nextState.count); // if(nextState.count % 2 === 0){ // return true; // } return true; }
<input type="button" value="在事件中綁定this並傳參" onClick={ this.click.bind(this, 'aa', 'bb') }/>
constructor(){ super(); this.state = { msg:'' } // 先使用bind方法將this和參數綁定上去,再將綁定以後的方法對象賦值到了click1上 this.click1 = this.click1.bind(this, 'bb', 'cc'); } <input type="button" value="在構造函數中綁定this並傳參" onClick={ this.click1 }/>
<input type="button" value="使用箭頭函數中綁定this並傳參" onClick={ ()=>{ this.click2('cc', 'dd') } }/>
v-model
指令,將表單控件和咱們的data
上面的屬性進行雙向數據綁定,數據變化和頁面之間的變化是同步的!state
之上的數據同步到界面的控件上,可是不能默認實現把界面上數據的改變,同步到state
之上,須要程序員手動調用相關的事件,來進行逆向的數據傳輸!<input ref="text" type="text" value={ this.state.msg } onChange={ this.changeText }/> changeText=(e)=>{ // console.log(e.target.value); // setState方法執行更新state的時候,是一個異步的操做,不可以直接獲取到最新的state值 // setState方法容許咱們傳入一個回調函數,在回調函數中可以獲取到最新的state this.setState({ msg: e.target.value }, function(){ console.log(this.state.msg); }) console.log(this.state.msg); }
setState的一個問題
:setState是異步的// setState方法執行更新state的時候,是一個異步的操做,不可以直接獲取到最新的state值 // setState方法容許咱們傳入一個回調函數,在回調函數中可以獲取到最新的state this.setState({ msg: e.target.value }, function(){ console.log(this.state.msg); }) console.log(this.state.msg);
用於父組件向子組件傳遞數據
使用步驟:
在父組件中調用getChildContext方法獲取子組件上下文並返回數據:
// 給全部的子組件去共享數據使用context getChildContext(){ return { color: this.state.color } }
在父組件中使用childContextTypes對數據進行校驗:
// 給子組件經過Context共享數據,必需要進行類型驗證 // 使用下面的方式: 驗證須要安裝 prop-types static childContextTypes = { color: PropTypes.string }
在子組件中使用contextTypes對數據進行校驗:
// 子組件想要接收父組件經過COntext傳遞的數據,還要進行類型驗證 static contextTypes = { color: PropTypes.string }
瞭解組件生命週期的三個階段
掌握defaultProps和propTypes的使用
掌握React提供的事件綁定機制
掌握ref的形式獲取元素
瞭解綁定this並傳參的三種方式
掌握表單控件配合onChange事件使用
父組件向子組件傳值
瞭解子組件向父組件傳值
app.use('*', function (req, res, next) { // 設置請求頭爲容許跨域 res.header("Access-Control-Allow-Origin", "*"); // 設置服務器支持的全部頭信息字段 res.header("Access-Control-Allow-Headers", "Content-Type,Content-Length, Authorization, Accept,X-Requested-With"); // 設置服務器支持的全部跨域請求的方法 res.header("Access-Control-Allow-Methods", "POST,GET"); // next()方法表示進入下一個路由 next(); });
頁面的結構: Ant Design
點擊導航切換顯示內容: 使用路由
數據來源:豆瓣電影的API
獲取數據:Ajax fetch
點擊返回返回上一個頁面
// 其中path指定了路由匹配規則,component指定了當前規則所對應的組件 <Route path="" component={}></Route>
Route
身上的exact
屬性,來表示當前的Route
是進行精確匹配的Redirect
實現路由重定向// 導入路由組件 import {Route, Link, Redirect} from 'react-router-dom' <Redirect to="/movie/in_theaters"></Redirect>
複習:
搭建基本的開發環境 - 英文官網<br/> 搭建基本的開發環境 - 中文 這兩篇文檔對比着進行參考,進行相關的安裝;
react-native init 項目名稱
來初始化一個react native項目;開發者調試模式
;可使用adb devices
來查看當前連接到電腦上的手機設備列表!react-native run-android
來打包當前項目,並把打包好的項目以調試的模式安裝到手機中!require(相對路徑)
:<Image source={require('./images/1.jpg')}></Image>
<Image source={{uri:'http://www.itcast.cn/images/slidead/BEIJING/2017332909331100.jpg'}} style={{width:200, height:200}}></Image>
// 使用方式: // 1. 建立一個ListView的數據源對象,配置對象是一個固定寫法, 做用是爲了實現ListView組件的高效更新 // 未來,這個數據源對象,會交給ListView去展現,目前,剛建立完畢的數據源,是個空數據源 const ds = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2 }); this.state = { // 調用數據源對象的cloneWithRows方法,將數據交給數據源去保存 userList: ds.cloneWithRows(['柯南', '毛利', '嬴政', '里斯', '毛多多', '柯南', '毛利', '嬴政', '里斯', '毛多多', '柯南', '毛利', '嬴政', '里斯', '毛多多']) } <ListView dataSource={this.state.userList} renderRow={(rowData) => <Text>{rowData}</Text>} />
https://api.douban.com/v2/movie/in_theaters
https://api.douban.com/v2/movie/subject/26309788
npm i react-native-router-flux@3.38.0 --save
https://github.com/aksonov/react-native-router-flux
https://github.com/aksonov/react-native-router-flux/blob/master/docs/API_CONFIGURATION.md
https://github.com/aksonov/react-native-router-flux/blob/master/docs/MINI_TUTORIAL.md
https://github.com/leecade/react-native-swiper?utm_source=tuicool&utm_medium=referral
npm i react-native-swiper --save
安裝輪播圖組件import Swiper from 'react-native-swiper';
showsPagination={false}
是用來控制頁碼的;showsButtons={false}
是用來控制左右箭頭顯示與隱藏;height={160}
是用來控制輪播圖區域的高度的!var styles = StyleSheet.create({ wrapper: {}, slide1: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#9DD6EB', }, slide2: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#97CAE5', }, slide3: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#92BBD9', }, image:{ width:'100%', height:'100%' } })
<Swiper style={styles.wrapper} showsButtons={true} height={160} autoplay={true}> <View style={styles.slide1}> <Image source={{uri:'http://www.itcast.cn/images/slidead/BEIJING/2017410109413000.jpg'}} style={styles.image}></Image> </View> <View style={styles.slide2}> <Image source={{uri:'http://www.itcast.cn/images/slidead/BEIJING/2017440109442800.jpg'}} style={styles.image}></Image> </View> <View style={styles.slide3}> <Image source={{uri:'http://www.itcast.cn/images/slidead/BEIJING/2017441409442800.jpg'}} style={styles.image}></Image> </View> </Swiper>
react-native-image-picker的github官網
安裝插件
npm install react-native-image-picker@latest --save
修改android/build.gradle文件
buildscript { ... dependencies { classpath 'com.android.tools.build:gradle:2.2.+' // <- USE 2.2.+ version } ... } ...
修改android/gradle/wrapper/gradle-wrapper.properties文件
distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip
修改android/app/build.gradle
dependencies { compile project(':react-native-image-picker') }
修改AndroidManifest.xml
<uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
修改MainApplication.java
import com.imagepicker.ImagePickerPackage; // <-- add this import public class MainApplication extends Application implements ReactApplication { @Override protected List<ReactPackage> getPackages() { return Arrays.<ReactPackage>asList( new MainReactPackage(), new ImagePickerPackage() // <-- add this line // OR if you want to customize dialog style new ImagePickerPackage(R.style.my_dialog_style) ); } }
在咱們本身的組件中添加以下代碼:
// 第1步: import ImagePicker from 'react-native-image-picker' var photoOptions = { //底部彈出框選項 title: '請選擇', cancelButtonTitle: '取消', takePhotoButtonTitle: '拍照', chooseFromLibraryButtonTitle: '選擇相冊', quality: 0.75, allowsEditing: true, noData: false, storageOptions: { skipBackup: true, path: 'images' } } // 第2步: constructor(props) { super(props); this.state = { imgURL: '' } } // 第3步: <Button title="拍照" onPress={this.cameraAction}></Button> <Image source={{ uri: this.state.imgURL }} style={{ width: 200, height: 200 }}></Image> // 第4步: cameraAction = () => { ImagePicker.showImagePicker(photoOptions, (response) => { console.log('response' + response); this.setState({ imgURL: response.uri }); if (response.didCancel) { return } }) }
必定要退出以前調試的App,並從新運行react-native run-android
進行打包部署;此次打包期間會下載一些jar的包,須要耐心等待!