为何要学习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的包,须要耐心等待!