React以及生态圈 React生态圈中技术: ReactJS ReactNative ReactVR(React360) Redux… ReactRouter ReactNavigation AntDesign 。。。 概述: slogan:learn once,write anywhere(只需要学习一次react中的核心概念,就可以使用reactjs写网页,使用reactnative写nativeapp,使用react360来实现虚拟现实的app)
1、reactjs(才用react实现网页编程) 1.1 3w1h what? reactjs是facebook,一个编写ui界面的js库 when? reactjs就是为了实现DOM操作非常频繁的应用场景(VDOM:virtual DOM 虚拟DOM) why? 组件化的开发方式 引入了VDOM 单向数据流 。。。 how? 搭建环境 方式1:cli npx create-react-app my-app cd my-app npm start
方式2:引入对应的js文件 找到C:\xampp\htdocs\codes\forStu\react\reactjs文件\ 的目录; 拷贝三个js文件到 C:\xampp\htdocs\codes\reactjs\js react.js ... 编程方式 1.2 第一个demo 知识点1:方法 ReactDOM.render(a,b) //方法:将a渲染到b这个地方去 知识点2:jsx 知识点3:babel 1.3 核心概念 ①jsx语法 jsx只是js语法的一个扩展:①允许在js中直接写标签 < ②在jsx中通过花括号来执行一些表达式 { babel:编译器 支持将jsx、es6转换为浏览器能识别的js 注意: 不可以直接渲染多个标签(放在一个容器) 每一个标签有开始和结束标记(比如<input/>) 优缺点: 更方便的封装视图 提高效率 jsx需要通过babel来转换(class->className for-》htmlFor...) jsx将数据和视图揉在一起 ②component 组件:是可被反复使用的,带有特定功能的视图 回顾: vue: vue.component('',{ components:{} }) angular: @Component() export class Demo01Component{} React: 创建: var Test = React.createClass({ render:function(){ return *** } }) 调用: <Test></Test> 注意事项: 组件类的名字必须得是全驼峰 在组件的render方法来渲染内容时,不要直接换行 如果要渲染多个元素,放在一个顶层容器 练习:demo04_lianxi.html (:- 15:30) 需求: 准备3个组件:MyInput MyList MyPage MyInput:input button(add) MyList: ul li*3 MyPage = MyInput+MyList 最终将MyPage作为根组件 渲染到id为example的容器 ③props 回顾: vue: <son myValue='100'></son> props:['myValue'] //this.myValue Angular: <son myValue='100'></son> import {Input} from '@angular/core' @Input() myValue=""//this.myValue React: 知识点1: 使用props来完成父--》子的通信 <Son myValue='100'></Son> this.props.myValue 知识点2: 背景知识: // 任何一个组件类的实例 都有一个props对象;一个props对象的keyValue的个数 取决于组件调用时的属性的个数,其实有一个例外:this.props.children(当前组件作为标签来调用时,开、闭标签内部的一些子标签的集合) // this.props.children类型是不确定的,如果有一个子标签,它是对象;如果有0个子标签,就是undefined;如果有2个或者以上的子标签,就是一个数组 获取所有的子标签来做操作 React.Children.map( this.props.children, (value)=>{return value} ) 知识点3: 事件绑定:<any onEvent={this.handleEvent}></any> 共识:一个组件在被调用的时候,通过属性传值,这个值还可以是一个方法 步骤1:父组件准备一个有参数的方法 rcvMsg(msg){} 步骤2:将有参数的方法传给子组件 <Son func={this.rcvMsg}></Son> 步骤3:子组件内部 可以调用通过属性传来的这个有参数的方法,将传递的数据传递给父组件 this.props.func(123) 练习: demo07_lianxi.html 需求:(:- 16:55) 完成组件的创建MyList、MyItem //list={[1,2,3]} MyList作为根组件来调用,调用的时候传递一个数组过去;接收到数组,动态的创建多个MyItem(同时将数组中值传递给MyItem) MyItem显示一个h1,显示传来的数据 ④ref reference 引用 基础语法: 步骤1: <input ref="myInput"/> 步骤2: this.refs.myInput 目的:为了让父组件可以通过ref快速的找到子组件的实例,调用子组件内部所定义的属性和方法 练习:(:- 10:50) demo10_lianxi.html 页面: 准备一个组件MyList,该组件显示input/button(add)/ul 功能: 点击button,通过ref获取input的值,添加到数组list,遍历list在ul中创建多个li ⑤state state中的数据是由绑定效果的 state的基本操作: 初始化 getIntialState:function(){ return {count:0} } 读 this.state.count 写 this.setState({count:1}) this.setState({count:1},()=>{}) 总结: jsx是基础语法 component是构成复杂视图的基础内容props实现组件间的通信 ref实现在父组件中操作子组件的 state可以实现绑定的效果,数据的管理 1.4 进阶知识 1.4.1 生命周期的钩子函数 组件从创建到消亡的过程,如果需要在一个特定的阶段去执行一个操作,借助于lifecycle hook来指定行为。 mount: 初始化 componentWillMount componentDidMount(推荐:执行初始化工作) update:数据发生变化 componentWillUpdate componentDidUpdate componentWillReceiveProps unmount:清理 componentWillUnmount 注意事项: ①不可以在willMount通过ref定位元素或者子组件做操作 ②在update相关的钩子函数中,在数据变化时 执行一些逻辑操作,同时记得避免出现死循环 ③当组件内部的state、传给该组件的prop对应的值发生变化,都会执行componentWillUpdate/DidUpdate ④通过props传给子组件的值,子组件只能读,不可以修改 ⑤什么时候在子组件中,会因为prop变化而执行update相关的钩子函数? 父组件准备一个状态,将状态通过属性传递给子组件;当父组件中操作这个状态的时候,子组件通过属性所获取到的值也跟着变化了 ⑥componentWillReceiveProps只有在通过属性传来的值变化的时候 才会执行 (在此钩子函数中 比如将prop传来的值存储在state以方便组件内部的数据操作) 练习:(:-15:30) demo13_lianxi.html ①准备一个组件 组件渲染一个h1 ②在组件挂载完毕之后,修改h1的透明度 0~0.1~0.2...~1 0~0.1~0.2 <any style={{opacity:this.state.**}}></any> 1.4.2 循环 <div> { this.state.myList.map(()=>{ return <li></li> }) } </div> jsx中写注释: {/* it is a comment */} 1.4.3 条件判断 <div> { this.state.isLogin && <p>欢迎会员回来</p> } </div> 1.4.4 特殊的表单 如果表单元素指定了value/selected/checked属性,那么用户直接操作,结果是不对的,受到react控制,称之为受控的表单元素 解决受控问题核心思路: 借助于状态的绑定特性 处理过程: 就是状态的3个基本操作(初始化、读、写) 1.4.5 事件处理函数自定义传值 <button onClick={()=>this.handleClick(30)}> </button> 1.5 综合练习 demo18_lianxi.html 准备以下组件:MyList MyInput 模板内容: MyInput: input + btn MyList:MyInput + ul 功能: 点击MyInput中的按钮,获取输入框的值,传递给MyList; MyList接收到值之后,保存在state(这应该是一个数组),遍历state在ul动态的创建多个li 新需求:在li中除了显示值之外,添加一个delete的按钮;点击delete,将li从ul中移除2、reactnative 使用核心概念,调用ui组件来完成移动端app的开发
es6模块注意的细节: ①导入和引入的方式 方案1: export default class Demo01 import Demo01 方案2: export class Demo01 import {Demo01} 调试技巧: 如何开启热更新: 摇一摇--》enable hot reloading 如何手工更新:摇一摇--》reload 如何在rn中查看console对应的日志信息: 摇一摇 --> Debug js remotely 2.1 概述 rn的竞品: weex/native script reactNative: Build native mobile apps using JavaScript and React rn是由facebook,才用react中的核心概念结合rn中所封装的组件 来完成NativeApp的编写 how? 编程方式: 使用react中所提供的概念(jsx/component/state/props/ref), 来调用rn中所封装的各种组件来构建app的页面 搭建环境: 步骤1:准备pc端的可以编码的模板项目 ①将C:\xampp\htdocs\codes\forStu\react\rn_myapp.zip拷贝到C:\xampp\htdocs\codes\rn目录; ②将rn_myapp.zip解压缩到了rn_myapp文件夹 ③通过vscode打开C:\xampp\htdocs\codes\rn\rn_myapp文件夹 ④启动内置终端,执行npm start ⑤通过浏览器来访问localhost:8081端口 步骤2:准备手机(模拟器)进行效果的预览 打开模拟器(夜神、蓝叠、网易mumu、腾讯手游助手。。。) 确认模拟器有没有预置我们安装好的app:myapp 如果没有预置myapp这个可以运行android系统的包, 将C:\xampp\htdocs\codes\rn\rn_myapp\android\app\build\outputs\apk\app-debug.apk拖拽安装到模拟器 启动myapp的android app: 情况1:闪退--》卸载重新安装 情况2: 出现了红色错误窗口(提示并没有配置要连接的开发服务器地址和端口) 设置要连接的ip和port? ①按下模拟器的"摇一摇"/"菜单键"来启动开发者菜单 ②按下dev settings,启动一个菜单 ③按下debug server host & port for device;弹出一个输入框 在输入框中输入ip地址和端口 172.163.100.134:8081 查看电脑的ip地址? cmd-->ipconfig 172.163.100.134 ④关闭应用程序,重新打开 2.2 基础 2.2.1 组件 创建: export default class Demo01 extends Component{} 调用: import Demo01 from '***' <Demo01></Demo01> 注意事项: ①不允许在组件中编写html元素 ②所有的类的名称要符合全驼峰 ③所有的类,要先引入再调用 练习:(:- 15:25) ①完成一个组件的创建和调用 demo02_lianxi.js Demo02Component ②组件渲染的内容 两个Text(放在View,仿照根组件中View的用户) 2.2.2 state 两个知识点 ①state中的数据 是有绑定效果 ②3个基础操作 初始化:放在构造函数中 constructor(){ super(); this.state = {} } 读: this.state.** 写: this.setState() 2.2.3 fetch fetch是负责和服务器端做交互的 fetch(url) .then( (response)=>response.json() ) .then((result)=>{ //result就是服务器端返回我们关心的数据 }) 如果需要进行post请求的处理: var config={ method:"POST", headers:{ "Content-Type":"application/x-www-form-urlencoded" }, body:"uname=dingding&upwd=123456" } fetch(url,config).then().then() 2.2.4 style rn中几乎所有的核心组件都支持style属性的 <Text style={{color:'red'}}></Text> 怎么封装和复用样式? import {StyleSheet} from 'react-native' const myStyles = StyleSheet.create({ myView:{width:200,height:200}, myText:{color:'red'} }) <View style={myStyles.myView}></View> <View style={[myStyles.myView,myStyles.myText]}></View> 准备工作: ①npm start 启动项目的开发服务器 ②启动xampp集成的mysql的数据库服务器 ③启动xz_api的app.js所对应的web服务器 ④打开模拟器 启动myapp 综合练习: demo06_lianxi.js Demo06Component ①组件挂载完毕之后,请求http://172.163.***.***:8080/product/list; fetch ②保存服务器端返回的数据中的data, 保存在状态list this.setState ③组件要渲染的内容 在View中循环的创建多个Text,Text中显示商品的title(Text字体颜色为蓝色) 2.3 常用组件 Text/View/Image/TextInput/Switch/FlatList/.... 自定义布局 2.3.1 Text 目的:展示一段文本内容 使用步骤: import {Text} from 'react-native' <Text>111</Text> 2.3.2 View 目的:准备一个容器 使用步骤: import {View} from 'react-native' <View> .... </View> 2.3.3 FlatList 目的:实现一个高性能的列表组件 使用步骤: import {FlatList} from 'react-native' showItem(info){ //info.item是遍历数组时临时变量 //info.index是下标 return <Text></Text> } <FlatList data={} renderItem={this.showItem}></FlatList> 注意: 如何解决key的warning问题? 从data所指向的数组着手,给数组中每一个对象添加一个key的属性,值要具有唯一性 2.3.4 Button、 目的:实现一个按钮 使用步骤: import {Button} from 'react-native' handlePress=()=>{} <Button title="刷新" onPress={this.handlePress}></Button> 练习: ①完成demo09_lianxi.js中Demo09Component组件类的封装和调用 ②模板内容: View Button FlatList(列表项:Text Button) ③功能 点击Button,准备一个数组[100,200,300,400,500]; 将数组保存在状态中;将状态的数据给FlatList去用; FlatList列表项中的Text显示数组中临时变量, 点击Button时alert弹窗显示下标 2.3.5 TextInput 目的:获取用户输入的信息 步骤: import {TextInput} from 'react-native' //ChangeText事件的事件处理函数是有参数的,这个参数是当前输入框的值 <TextInput placeholder="" onChangeText={} secureTextEntry={true}></TextInput> 2.3.6 Switch 目的:实现一个滑动开关 注意:Switch默认是一个受控组件,需要根据状态的绑定特性来解决受控问题 步骤: import {Switch} from 'react-native' <Switch onValueChange=""></Switch> 2.3.7 Image 目的:展示图片 使用步骤: import {Image} from 'react-native' //情况1:加载的本地资源图片 <Image source={require('../assets/img/3.jpg')}></Image> //情况2:加载网络资源图片 <Image source={{uri:""}} style={{width:200,height:200}}></Image> 2.3.8 TouchableOpacity 目的:放在此容器中的元素 在按下的时候 是会有一个透明度变化的效果 使用步骤: import {TouchableOpacity} from 'react-native' <TouchableOpacity> ... </TouchableOpacity> 2.3.9 ScrollView 目的:实现一个支持滚动的容器 步骤: import {ScrollView} from 'react-native' <ScrollView> .... </ScrollView> 2.3.10 ActivityIndicator 目的:实现一个加载中的loading 使用步骤: import {ActivityIndicator} from 'react-native' <ActivityIndicator size="large" color='green'></ActivityIndicator> 综合练习:(:- 17:30) ①在demo15_lianxi.js文件中 封装一个组件Demo15Component ②组件的模板内容 View TextInput Button(add) FlatList (列表项:Text,希望Text支持点按的ui变化效果-->TouchableOpacity) ③点击add按钮,将TextInput的值保存在一个数组,数组显示FlatList; Text在点按时 通过alert来显示下标 在点完add之后,清空一下输入框的值 this.state = {list:[],myValue:""} <Button onPress <TouchableOpacity onPress <TextInput onChangeText onPress onChangeText onValueChange 2.3.11 布局 ReactNative支持c3中flexbox 主轴默认是column alignItems/justifyContent/flexDirection 2.4 路由(ReactNavigation) express/vue/angular/ionic 路由的本质:建立一种映射关系 rn这项技术官方并没有提供路由:可以使用非常受欢迎的reactNativigation开源项目来完成rn的路由的功能 ①基础概念 ReactNavigation是用在rn中的一个路由的开源项目 how? yarn add react-navigation # or with npm # npm install --save react-navigation 基础用法: 步骤1:创建几个组件 步骤2:引入react-navigation这个包里边的配置路由的工具,进行路由配置 import {createStackNavigator} from 'react-navigation' var myNavigation = createStackNavigator({ login:{ screen:LoginComponent }, }) 步骤3:调用路由 AppRegistry.registerComponent( "myapp", ()=>myNavigation ) 注意: 在设置路由的时候,第一个keyValue就是默认要访问的组件 练习: 完成demo17_register.js文件的创建,并在此文件中,封装一个Demo17Register的组件类; 希望路由中默认展示Demo17Register 稍等.... ②跳转 //vue:this.$router.push //angular: this.myRouter.navigateByUrl() //ionic:this.navCtrl.push() this.props.navigation.push('detail') ③传参 步骤1:跳转的同时 发送数据 this.props.navigation.push('detail',{id:1,title:'123'}) 步骤2:接收数据 this.props.navigation.getParam('id') 基础语法+网络+内部数据+路由总结:在React以及生态圈中学到的知识点 ①react 5大核心概念 jsx(语法基础) component(视图的封装和复用) props(组件间通信) state(管理组件内部的数据) ref(在父组件中主动的获取子组件的数据) ②rn中基础 fetch 实现与远程服务器端的通信 fetch(url).then((response)=>response.json()).then((result)=>{}) style <Text style={{color:‘red’}}> StyleSheet 样式的封装和服用 StyleSheet.create() flexbox 自定义布局 ③rn中各种组件 View/Text/TextInput/Button/Image… (div/p/input/button/img) ④路由ReactNavigation 跳转和传参
综合练习:(:- 14:55) ①完成两个文件 demo19_cart.js --> CartComponent demo19_submit.js-->SubmitComponent ②配置路由 两个路由地址:cart(默认)/submit ③demo19_cart.js 初始化一个状态list(对象数组,每一个对象包含title/price/count) 视图:FlatList(列表项显示title)+Button(点击跳转到submit) (:- 15:35) ④点击cart中的Button时跳转到submit,同时将商品的总价格,发送过去 ⑤submit接收传来的价格,显示在Text .... 2.5 实现一个基于RN的项目 使用ionic来实现一个webApp/hybridApp vue+mintui/mui/vux 实现一个webApp 实现一个NativeApp: weex/native script/react native 目标: ①熟练使用react的核心概念 jsx/props/state/... ②熟练使用rn中所封装的各种组件 View/Text/TextInput/Image/.. ③具备编写NativeApp的能力 View-->android.View/uiView