1.移动App第1天
什么是混合移动App开发【重点】
- 苹果上的软件是如何开发出来的:使用的是 OC、或者使用Swift这门语言
- 安卓平台上的软件又是如何开发出来的:使用安卓相关的语言开发的,Java,安卓的控件进行开发
- 苹果和安卓平台上共有的软件是如何开发出来的:腾讯招两套开发人员【开发组】,手机京东
- 前端移动 App(Application)开发技术,去开发手机端的应用程序;
- 前端的混合移动App开发技术,并没有使用 苹果 或 安卓 官方推荐的 开发平台和开发方式,而是抛弃了 官方提供的方式,使用 前端的独有的技术进行移动App开发体验;
什么是移动App开发:通俗的理解,就是把开发Web网站的技术(HTML+CSS+JS),通过某种方式,移植到移动App开发上进行使用,这种利用Web开发技术进行移动端开发体验的方式,叫做混合移动App开发!
关于移动App开发,需要知道的几个概念:
- 原生开发:它的英文单词是(NativeApp),指的就是使用 IOS、Android 官方提供的工具、开发平台、配套语言进行 手机App开发的方式;
- 混合开发:(HybirdApp)就是使用前端已有的技术,HTML + CSS + JS ,然后再搭配一些相关的打包编译技术,就能够开发出一个手机App,安装到手机中进行使用;
- 什么是App:App是(Application的缩写),意思是:可安装的应用程序;
- App的分类:
- 按照平台来划分:
- PC端:浏览器、代码编辑器、PC端的游戏、听歌的、看视频的、聊天的
- 移动端:手机QQ、手机微信、手机爱奇艺、亡者农药
- 按照功能来划分:
- 游戏:愤怒的小鸡仔、植物大战僵尸、亡者农药…LOL
- 应用:非游戏类的软件,支付宝、陌陌、美团外卖、
- 按照平台来划分:
- App和Web的区别:
- APP概念:App是(Application的缩写),意思是:可安装的应用程序;
- 优点:流畅、稳定、基本上一些App都可以脱网运行,用户体验好; - 缺点:不能跨平台
- Web概念:特指那些基于浏览器的web网站(本质:就是网页)
- 优点:可以跨平台(浏览器天生就是跨平台的) - 缺点:没有App流畅、不稳定,受限于网速和网络
为什么要学混合App开发
从程序员的角度分析:
- 挣钱多(别人不会的你会,别人会的,你精通)
- 对于找工作来说:(React Native)市场需求量大,好找工作,提高我们的行业竞争力
- 能接触到前端流行的技术和框架(各大公司基本都再用React),注意:再React中我们全部都使用ES6语法(class)
- 前端是一个永恒的行业???(只要世界上还有浏览器的存在,必然需要前端,只不过,随着时间的推移,技术更新换代,可能我们对新技术的要求会越来高)
- 屌丝的崛起之路:
只能做页面
->Ajax前后台数据交互
->Jquery、Bootstrap
-> webApp ->三大框架
->可以做手机混合App/桌面应用
->可以做手机原生App
->将来或许可以发射火箭发射卫星发射导弹
->终极目标:统一全宇宙
- (搞前端App开发)能购置一批牛逼的设备【苹果笔记本、IOS测试机、安卓手机(三星的、华为、小米)】
从企业的角度分析:(选择合适自身的移动App开发方式)【重点】
- 节省开发成本
- 从工资上:尽最大的可能,压榨员工的剩余劳动力
- 从时间上:因为 原生的安卓和IOS开发,它们的开发效率并不是很高,因为原生的代码复杂度比较高,因此原生的开发周期比较慢;如果采用移动App开发,那么,我们的开发周期会很短;因为 HTML + CSS + JS 足够简单;(对于前端开发APP来说,有两种方式,其中,比较早的一种,也是比较简单的一种,就是 先开发出一个网站, 然后再把网站运行一行打包的命令,就能得到一个 APP了)
- 市面上常见的App开发方式
- WebApp:基于浏览器实现的,有特定功能的网站,称作WebApp
- 例如:百度脑图、https://m.jd.com/、https://m.taobao.com/#index
- 优点:跨平台
- 缺点:依赖网络,有白屏效果,相对来说,用户体验差;不能调用硬件底层得设备,比如摄像头;
- NativeApp:用android和Object-C等原生语言开发的应用
- 优点:体验好;用户使用起来很流畅;非常适合做游戏【性能高】;可以直接调用硬件底层的API;
- 缺点:不能跨平台
- HybirdApp:利用前端所学的知识去开发移动端App,兼具2者的优势
- 优点:能够跨平台;体验会好一些;也能够调用硬件底层的API
- 缺点:相对于原生体验稍微弱一丢丢;不适合做游戏;适合做非游戏类型的手机App;
- 应用场景:
- 注意: 使用 Java 或者 IOS 写出来的代码和程序,在最终运行的时候,普通的文本代码,都会被编译为 原生的机器码去运行,并不像 JS 这样,解析执行,Java代码是 编译执行的;
- 三种开发方式的原理和对比
企业如何选择合适自己的App开发方式
- 如果这个企业中,曾经使用原生技术开发过一些APP,那么在维护的时候,必然需要使用原生技术来维护
- 如果企业中,需要做一些游戏级别的应用,那么推荐使用原生,因为原生运行效率高,对耗电量处理的很好;
- 如果企业做一些应用级别的非游戏软件,比如 淘宝、京东、美团,就可以使用 混合APP了;
- 在企业中,最主要的是好的点子,如果有了一个好的项目立案,那么最好要立即把这个项目做出来;这时候,使用混合App非常合适,因为开发周期很短,能快速上线,抢先占领市场;【裤衩开发】
企业中项目开发流程
- 需求调研:产品定位、受众群体、市场需求、开发价值;【产出物:需求文档】
- 产品设计:功能模块、流程逻辑;【产出物:设计文档,交互稿】,确定项目的基本功能;
- 项目开发:项目架构、美工、前端、后台、测试【产品的把控】要理解前后端分离的概念
- 运营维护:上线试运行、调Bug、微调功能模块、产品迭代
根据需求搞设计,根据设计做开发
企业技术选型 - 几大主流技术之间的关系
- Angular.js 和 Ionic
- Vue.js 和 Weex
- React.js 和 React-Native
Angular, Vue, React 这三个都是前端框架,我们在进行混合App开发的时候,只是用到了这三个框架的【基础语法】而已;
Ionic, Weex, ReactNatvie 这三个都是打包工具(提供了相关的命令行,只要运行指定的命令,就能够把项目打包成一个手机App出来),能够把我们开发出来的应用,最终打包成一个可安装的手机端程序安装包;同时,这三个东西,也提供了好用的一些小组件,方便我们去构建移动App的用户界面;
前端混合App开发框架
- Html5+、ReactNative、Weex、Ionic
- 认识HTML5+
- h5+是一个产业联盟,它有一些互联网成员,专门在中国推广H5
开发框架之间的区别
- Html5+ 和 Ionic
- ReactNative 和 Weex
使用HBuilder生成安卓应用(在线)
API地址
Hbuilder这个工具,是一个在线打包工具,使用很方便,不需要在本地配置开发环境;直接将做好的网站,通过一些简单的操作,就能在线打包为一个App出来;
- 在项目上右键 -> 发行 -> 发行为原生安装包
好处:本地不用配置开发环境;操作方便,对于程序员来说不关心打包的过程,打包过程对于我们来说是透明的;
缺点:程序员很少能干预打包的过程;源代码被提交到了云端的服务器,存在项目核心代码被泄露的风险;
环境变量的使用
作用:将需要全局使用的工具或者应用程序,配置到Path环境变量中,可以很方便的通过命令行的形式,在任何想要运行这些应用程序的地方,运行它们;
移动App开发环境配置【重点】
安装最新版本的java jdk
- 修改环境变量,新增
JAVA_HOME
的系统环境变量,值为C:\Program Files (x86)\Java\jdk1.8.0_112
,也就是安装JDK的根目录 - 修改系统环境变量
Path
,在Path
之后新增%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin;
- 新建系统环境变量
CLASSPATH
,值为.;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar;
- 保存所有的系统环境变量,同时退出系统环境变量配置窗口,然后运行cmd命令行工具,输入
javac
,如果能出现javac的命令选项,就表示配置成功!
安装Node.js环境
注意:需要安装最新的长期稳定版本,不要实验版本;安装完毕之后的node.js会自动配置到全局系统环境变量中
安装完毕后,可以输入node -v
查看node版本号;
安装C++环境
大多数情况下操作系统自带C++环境,不需要手动安装C++环境;
如果运行报错,则需要手动安装visual studio中的C++环境;
安装Git环境
Git安装完毕后,会自动配置到系统环境变量中;
可以通过运行git --version
来检查是否正确安装和配置了Git的环境变量;
安装Python环境
- 注意:安装Python时候,只能安装2.×的版本,注意勾选安装界面上的
Add Python to path
,这样才能自动将Python安装到系统环境变量中; - 安装完毕之后,可以在命令行中运行
python
,检查是否成功安装了python。
配置安卓环境
- 安装
installer_r24.3.4-windows.exe
,最好手动选择安装到C盘下的android目录 - 打开安装的目录,将
android-25
、android-23
(react-native必须依赖这个)解压后,放到platforms
文件夹下 - 解压
platform-tools
,放到platform-tools
文件夹下 - 【这一步直接忽略即可!】tools文件夹不解压覆盖也行;
解压tools
,放到安装根目录中 - 解压
build-tools_r23.0.1-windows.zip(react-native必须依赖这个)
、build-tools_r23.0.2-windows.zip(weex必须依赖这个)
和build-tools_r23.0.3-windows.zip
,并将解压出来的文件夹,分别改名为版本号23.0.1
、23.0.2
和23.0.3
;在安装目录中新建文件夹build-tools
,并将改名为版本号之后的文件夹,放到新创建出来的build-tools
文件夹下 - 在安装目录中,新建
extras
文件夹,在extras
文件夹下新建android
文件夹;解压m2responsitory
文件夹和support
文件夹,放到新建的extras -> android
文件夹下 - 配置安装环境变量:在系统环境变量中新建
ANDROID_HOME
,值为android SDK Manager的安装路径C:\Users\liulongbin\AppData\Local\Android\android-sdk
,紧接着,在Path中新增;%ANDROID_HOME%\tools;%ANDROID_HOME%\platform-tools;
ReactNative快速打包
- 安装完node后建议设置npm镜像以加速后面的过程(或使用科学上网工具)。注意:**不要使用cnpm!**cnpm安装的模块路径比较奇怪,packager不能正常识别!
npm config set registry https://registry.npm.taobao.org --global
npm config set disturl https://npm.taobao.org/dist --global
- Yarn、React Native的命令行工具(react-native-cli)
- Yarn是Facebook提供的替代npm的工具,可以加速node模块的下载。React Native的命令行工具用于执行创建、初始化、更新项目、运行打包服务(packager)等任务。
npm install -g yarn react-native-cli
- 安装完yarn后同理也要设置镜像源:
yarn config set registry https://registry.npm.taobao.org --global
yarn config set disturl https://npm.taobao.org/dist --global
- 运行
react-native init AwesomeProject
创建React-Native项目 - 运行
cd AwesomeProject
切换到项目根目录中,运行adb devices
来确保有设备连接到了电脑上 - 运行
react-native run-android
打包编译安卓项目,并部署到模拟器或开发机中 - 运行上一条命令之前,要确保有设备连接到了电脑上,可以运行
adb devices
查看当前接入的设备列表,打包好的文件,放到了android\app\build\outputs\apk
目录下 - 入坑指南
问题1:开启悬浮框权限;
问题2:Could not get BatchedBridge, make sure your bundle is packaged correctly
解决方案:在终端中,进入到项目的根目录,执行下面这段命令行:react-native bundle --platform android --dev false --entry-file index.android.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/src/main/res/
运行之前,需要确保android/app/src/main/
目录下有assets
文件夹,如果没有,手动创建之~,再运行上面的命令;
问题3:could not connect to development server
解决方案:晃动手机,唤起设置属性窗口,点击“Dev settings”,再点击Debuug server host 出现设置ip地址窗口,填写Ip地址和端口号8081,例如192.168.1.111:8081
Weex快速打包
- 安装依赖:Weex 官方提供了 weex-toolkit 的脚手架工具来辅助开发和调试。首先,你需要最新稳定版的 Node.js 和 Weex CLi。
- 运行
npm install -g weex-toolkit
安装Weex 官方提供的weex-toolkit
脚手架工具到全局环境中 - 运行
weex create project-name
初始化Weex项目 - 进入到项目的根目录中,打开cmd窗口,运行
weex platform add android
安装android模板,首次安装模板时,等待时间较长,建议fq安装模板 - 打开
android studio
中的安卓模拟器
,或者将启用USB调试的真机
连接到电脑上,运行weex run android
,打包部署weex项目 - 部署完成,查看项目效果
总结重点
- 什么是前端移动App开发
- 市面上常见的App开发方式及优缺点
- 使用Hbuilder在线生成安卓应用
- 学会配置ReactNative开发环境
- 掌握ReactNative打包流程
2.移动App第2天
webpack的发布策略
- 在实际开发中,一般会有两套项目方案:
- 一套是开发期间的项目,包含了测试文件、测试数据、开发工具、测试工具等相关配置,有利于项目的开发和测试,但是这些文件仅用于开发,发布项目时候需要剔除;
- 另一套是部署期间的项目,剔除了那些客户用不到的测试数据测试工具和文件,比较纯净,减少了项目发布后的体积,有利于安装和部署!
- 为了满足我们的发布策略,需要新建一个配置文件,命名为
webpack.publish.config.js
,将webpack.config.js
的配置拷贝过去,剔除一些开发配置项即可:
- 将
devServer
节点删掉:
devServer: {
hot: true,
open: true,
port: 4321
}
- 将
plugins
节点下的热更新插件删掉:
new webpack.HotModuleReplacementPlugin()
- 修改
url-loader
,将图片放入统一的images文件夹之下:
{ test: /\.(png|jpg|gif)$/, use: 'url-loader?limit=43959&name=images/[name].[ext]' }
或者使用img-
前缀加上7位的hash名称
:
{ test: /\.(png|jpg|gif)$/, use: 'url-loader?limit=43959&name=images/img-[hash:7].[ext]' }
- 在
package.json
中的script节点下新增dev
命令,通过--config
指定webpack启动时要读取的配置文件:
"pub": "webpack --config webpack.publish.config.js"
每次重新构建时候删除dist目录
- 运行
cnpm i clean-webpack-plugin --save-dev
- 在头部引入这个插件:
var cleanWebpackPlugin = require('clean-webpack-plugin');
- 在
plugins
节点下使用这个插件:
new cleanWebpackPlugin(['dist'])
分离第三方包改造webpack.publish.config.js
- 改造entry节点如下:
entry: {
app: path.resolve(__dirname, 'src/js/main.js'), // 自己代码的入口
vendors: ['jquery'] // 要分离的第三方包的入口
}
- 在plugins节点下新增插件:
new webpack.optimize.CommonsChunkPlugin({ // 抽离第三方包的插件
name:'vendors', // 指定抽离第三方包的入口名称
filename:'vendors.js' // 抽离出的公共模块的名称
})
html-webpack-plugin
在生成index.html
文件的时候,会自动将抽离的第三方包引入进去!
优化压缩JS
在plugins数组中添加:
new webpack.optimize.UglifyJsPlugin({ // 优化压缩JS
compress:{
warnings:false // 移除警告
}
}),
new webpack.DefinePlugin({ // 设置为产品上线环境,进一步压缩JS代码
'process.env.NODE_ENV': '"production"'
})
优化压缩HTML文件
在plugins
节点下的htmlWebpackPlugin
插件中,添加minify
子节点:
minify:{// 压缩HTML代码
collapseWhitespace:true, // 合并空白字符
removeComments:true, // 移除注释
removeAttributeQuotes:true // 移除属性上的引号
}
其他优化项请参考:html-minifier - github
抽取CSS文件
- 运行
npm install --save-dev extract-text-webpack-plugin
安装抽取CSS文件的插件。 - 在配置文件中导入插件:
const ExtractTextPlugin = require("extract-text-webpack-plugin");
- 修改CSS和Sass的loader如下:
{
test: /\.css$/, use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: ["css-loader"],
publicPath: '../' // 设置图片路径
})
},
{
test: /\.scss$/, use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: ['css-loader', 'sass-loader'],
publicPath: '../' // 设置图片路径
})
}
- 在plugins节点下新增插件:
new ExtractTextPlugin("css/styles.css"), // 抽取CSS文件的插件
压缩抽取出来的CSS文件
- 运行
cnpm i optimize-css-assets-webpack-plugin --save-dev
安装插件到开发依赖。 - 在配置文件头部导入插件:
var OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
- 在plugins节点下新增插件:
new OptimizeCssAssetsPlugin() // 压缩CSS文件的插件
相关文章
3.移动App第3天
ReactJS简介
- React 起源于 Facebook 的内部项目,因为该公司对市场上所有 JavaScript MVC 框架,都不满意,就决定自己写一套,用来架设 Instagram 的网站。做出来以后,发现这套东西很好用,就在2013年5月开源了。
- 由于 React 的设计思想极其独特,属于革命性创新,性能出众,代码逻辑却非常简单。所以,越来越多的人开始关注和使用,认为它可能是将来 Web 开发的主流工具。
- library
- Framework
前端三大主流框架
- Angular.js:出来最早的前端框架,学习曲线比较陡,NG1学起来比较麻烦,NG2开始,进行了一系列的改革,也开始启用组件化了;在NG中,也支持使用TS(TypeScript)进行编程;
- Vue.js:最火的一门前端框架,它是中国人开发的,对我我们来说,文档要友好一些;
- React.js:最流行的一门框架,因为它的设计很优秀;
- windowsPhone 7 7.5 8 10
React与vue.js的对比
组件化方面
- 什么是模块化:从 代码 的角度,去分析问题,把我们编程时候的业务逻辑,分割到不同的模块中来进行开发,这样能够方便代码的重用;
- 什么是组件化:从 UI 的角度,去分析问题,把一个页面,拆分为一些互不相干的小组件,随着我们项目的开发,我们手里的组件会越来越多,最后,我们如果要实现一个页面,可能直接把现有的组件拿过来进行拼接,就能快速得到一个完整的页面, 这样方便了UI元素的重用;组件是元素的集合体;
- 组件化的好处:
- Vue是如何实现组件化的:.vue 组件模板文件,浏览器不识别这样的.vue文件,所以,在运行前,会把 .vue 预先编译成真正的组件;
- template: UI结构
- script: 业务逻辑和数据
- style: UI的样式
- React如何实现组件化:在React中实现组件化的时候,根本没有 像 .vue 这样的模板文件,而是,直接使用JS代码的形式,去创建任何你想要的组件;
- React中的组件,都是直接在 js 文件中定义的;
- React的组件,并没有把一个组件 拆分为 三部分(结构、样式、业务逻辑),而是全部使用JS来实现一个组件的;(也就是说:结构、样式、业务逻辑是混合在JS里面一起编写出来的)
开发团队方面
- React是由FaceBook前端官方团队进行维护和更新的;因此,React的维护开发团队,技术实力比较雄厚;
- Vue:第一版,主要是有作者 尤雨溪 专门进行维护的,当 Vue更新到 2.x 版本后,也有了一个小团队进行相关的维护和开发;
社区方面
- 在社区方面,React由于诞生的较早,所以社区比较强大,一些常见的问题、坑、最优解决方案,文档、博客在社区中都是可以很方便就能找到的;
- Vue是近两年才诞生开源出来的,所以,它的社区相对于React来说,要小巧一些,所以,可能有的一些坑,没人踩过;
移动APP开发体验方面
- Vue,结合 Weex 这门技术,提供了 迁移到 移动端App开发的体验(Weex,目前只是一个 小的玩具, 并没有很成功的 大案例;)
- React,结合 ReactNative,也提供了无缝迁移到 移动App的开发体验(RN用的最多,也是最火最流行的);
为什么要学习React
- 设计很优秀,是基于组件化的,方便我们UI代码的重用;
- 开发团队实力强悍,不必担心短更的情况;
- 社区强大,很多问题都能找到对应的解决方案;
- 提供了无缝转到 ReactNative 上的开发体验,让我们技术能力得到了拓展;增强了我们的核心竞争力
React中几个核心的概念
虚拟DOM(Virtual Document Object Model)
- DOM的本质是什么:就是用JS表示的UI元素
- DOM和虚拟DOM的区别:
- DOM是由浏览器中的JS提供功能,所以我们只能人为的使用 浏览器提供的固定的API来操作DOM对象;
- 虚拟DOM:并不是由浏览器提供的,而是我们程序员手动模拟实现的,类似于浏览器中的DOM,但是有着本质的区别;
- 为什么要实现虚拟DOM:
- 什么是React中的虚拟DOM:
- 虚拟DOM的目的:
Diff算法
- tree diff:新旧DOM树,逐层对比的方式,就叫做 tree diff,每当我们从前到后,把所有层的节点对比完后,必然能够找到那些 需要被更新的元素;
- component diff:在对比每一层的时候,组件之间的对比,叫做 component diff;当对比组件的时候,如果两个组件的类型相同,则暂时认为这个组件不需要被更新,如果组件的类型不同,则立即将旧组件移除,新建一个组件,替换到被移除的位置;
- element diff:在组件中,每个元素之间也要进行对比,那么,元素级别的对比,叫做 element diff;
- key:key这个属性,可以把 页面上的 DOM节点 和 虚拟DOM中的对象,做一层关联关系;
React项目的创建
- 运行
cnpm i react react-dom -S
安装包 - 在项目中导入两个相关的包:
// 1. 在 React 学习中,需要安装 两个包 react react-dom
// 1.1 react 这个包,是专门用来创建React组件、组件生命周期等这些东西的;
// 1.2 react-dom 里面主要封装了和 DOM 操作相关的包,比如,要把 组件渲染到页面上
import React from 'react'
import ReactDOM from 'react-dom'
- 使用JS的创建虚拟DOM节点:
// 2. 在 react 中,如要要创建 DOM 元素了,只能使用 React 提供的 JS API 来创建,不能【直接】像 Vue 中那样,手写 HTML 元素
// React.createElement() 方法,用于创建 虚拟DOM 对象,它接收 3个及以上的参数
// 参数1: 是个字符串类型的参数,表示要创建的元素类型
// 参数2: 是一个属性对象,表示 创建的这个元素上,有哪些属性
// 参数3: 从第三个参数的位置开始,后面可以放好多的虚拟DOM对象,这写参数,表示当前元素的子节点
// <div title="this is a div" id="mydiv">这是一个div</div>
var myH1 = React.createElement('h1', null, '这是一个大大的H1')
var myDiv = React.createElement('div', { title: 'this is a div', id: 'mydiv' }, '这是一个div', myH1)
- 使用 ReactDOM 把元素渲染到页面指定的容器中:
// ReactDOM.render('要渲染的虚拟DOM元素', '要渲染到页面上的哪个位置中')
// 注意: ReactDOM.render() 方法的第二个参数,和vue不一样,不接受 "#app" 这样的字符串,而是需要传递一个 原生的 DOM 对象
ReactDOM.render(myDiv, document.getElementById('app'))
JSX语法
- 如要要使用 JSX 语法,必须先运行
cnpm i babel-preset-react -D
,然后再.babelrc
中添加 语法配置; - JSX语法的本质:还是以 React.createElement 的形式来实现的,并没有直接把 用户写的 HTML代码,渲染到页面上;
- 如果要在 JSX 语法内部,书写 JS 代码了,那么,所有的JS代码,必须写到 {} 内部;
- 当 编译引擎,在编译JSX代码的时候,如果遇到了
<
那么就把它当作 HTML代码去编译,如果遇到了{}
就把 花括号内部的代码当作 普通JS代码去编译; - 在{}内部,可以写任何符合JS规范的代码;
- 在JSX中,如果要为元素添加
class
属性了,那么,必须写成className
,因为class
在ES6中是一个关键字;和class
类似,label标签的for
属性需要替换为htmlFor
. - 在JSX创建DOM的时候,所有的节点,必须有唯一的根元素进行包裹;
- 如果要写注释了,注释必须放到 {} 内部
React中:第一种创建组件的方式
第一种基本组件的创建方式
父组件向子组件传递数据
属性扩散
将组件封装到单独的文件中
React中:第二种创建组件的方式
了解ES6中class关键字的使用
基于class关键字创建组件
- 使用 class 关键字来创建组件
class Person extends React.Component{
// 通过报错提示得知:在class创建的组件中,必须定义一个render函数
render(){
// 在render函数中,必须返回一个null或者符合规范的虚拟DOM元素
return <div>
<h1>这是用 class 关键字创建的组件!</h1>
</div>;
}
}
两种创建组件方式的对比
- 用构造函数创建出来的组件:专业的名字叫做“无状态组件”
- 用class关键字创建出来的组件:专业的名字叫做“有状态组件”
用构造函数创建出来的组件,和用class创建出来的组件,这两种不同的组件之间的本质区别就是:有无state属性!!!
有状态组件和无状态组件之间的本质区别就是:有无state属性!
一个小案例,巩固有状态组件和无状态组件的使用
通过for循环生成多个组件
- 数据:
CommentList = [
{ user: '张三', content: '哈哈,沙发' },
{ user: '张三2', content: '哈哈,板凳' },
{ user: '张三3', content: '哈哈,凉席' },
{ user: '张三4', content: '哈哈,砖头' },
{ user: '张三5', content: '哈哈,楼下山炮' }
]
style样式
总结
理解React中虚拟DOM的概念
理解React中三种Diff算法的概念
使用JS中createElement的方式创建虚拟DOM
使用ReactDOM.render方法
使用JSX语法并理解其本质
掌握创建组件的两种方式
理解有状态组件和无状态组件的本质区别
理解props和state的区别
相关文章
- React数据流和组件间的沟通总结
- 单向数据流和双向绑定各有什么优缺点?
- 怎么更好的理解虚拟DOM?
- React中文文档 - 版本较低
- React 源码剖析系列 - 不可思议的 react diff
- 深入浅出React(四):虚拟DOM Diff算法解析
- 一看就懂的ReactJs入门教程(精华版)
- CSS Modules 用法教程
- 将MarkDown转换为HTML页面
- win7命令行 端口占用 查询进程号 杀进程
4.移动App第4天
组件的生命周期
- 概念:组件从创建、到运行、再到销毁,这期间总是伴随着各种各样的事件,那么,这些事件统称为 组件的生命周期函数;
- 组件生命周期分为三部分:
-
组件创建阶段:生命周期函数,有一个显著的特点:组件一生只执行一次;
-
组件运行阶段:这些函数,也有显著的特点: 一生会根据属性props 和 状态 state 的改变,有选择性的触发0次或多次;
-
组件销毁阶段:这些函数,也有显著的特点:一生只执行一次;
-
vue中的生命周期图
React Native 中组件的生命周期
defaultProps
在组件创建之前,会先初始化默认的props属性,这是全局调用一次,严格地来说,这不是组件的生命周期的一部分。在组件被创建并加载候,首先调用 constructor 构造器中的 this.state = {},来初始化组件的状态。
React生命周期的回调函数总结成表格如下:
组件生命周期的执行顺序:
- Mounting:
- constructor()
- componentWillMount()
- render()
- componentDidMount()
- Updating:
- componentWillReceiveProps(nextProps)
- shouldComponentUpdate(nextProps, nextState)
- componentWillUpdate(nextProps, nextState)
- render()
- componentDidUpdate(prevProps, prevState)
- Unmounting:
- componentWillUnmount()
通过Counter计数器的小案例 - 了解生命周期函数
- 给组件设置默认属性:
- 给属性进行类型校验,需要先运行
cnpm i prop-types --save
组件初始化时生命周期事件总结
- componentWillMount:
- render:
- componentDidMount:
- 注意:在render函数中,不能调用
setState()
方法
通过原生的方式获取元素并绑定事件
React中使用ref属性获取DOM元素引用
使用React中的事件,绑定count自增
组件运行中事件的对比
- shouldComponentUpdate:
- componentWillUpdate:
- render:
- componentDidUpdate:
绑定this并传参的三种方式
- 在事件中绑定this并传参:
<input type="button" value="在事件中绑定this并传参" onClick={this.handleMsg1.bind(this, '🍕', '🍟')} />
// 在事件中绑定this并传参
handleMsg1(arg1, arg2) {
console.log(this);
// 此时this是个null
this.setState({
msg: '在事件中绑定this并传参:' + arg1 + arg2
});
}
- 在构造函数中绑定this并传参:
// 修改构造函数中的代码:
this.handleMsg2 = this.handleMsg2.bind(this, '🚗', '🚚');
<input type="button" value="在构造函数中绑定this并传参" onClick={this.handleMsg2} />
// 在构造函数中绑定this并传参
handleMsg2(arg1, arg2) {
this.setState({
msg: '在构造函数中绑定this并传参:' + arg1 + arg2
});
}
- 用箭头函数绑定this并传参:
<input type="button" value="用箭头函数绑定this并传参" onClick={() => { this.handleMsg3('👩', '👰') }} />
// 用箭头函数绑定this并传参
handleMsg3(arg1, arg2) {
this.setState({
msg: '用箭头函数绑定this并传参:' + arg1 + arg2
});
}
绑定文本框与state中的值
- 在Vue.js中,默认可以通过
v-model
指令,将表单控件和我们的data
上面的属性进行双向数据绑定,数据变化和页面之间的变化是同步的! - 在React.js中,默认没有提供双向数据绑定这一功能,默认的,只能把
state
之上的数据同步到界面的控件上,但是不能默认实现把界面上数据的改变,同步到state
之上,需要程序员手动调用相关的事件,来进行逆向的数据传输! - 绑定文本框和state的值:
{/*只要将value属性,和state上的状态进行绑定,那么,这个表单元素就变成了受控表单元素,这时候,如果没有调用相关的事件,是无法手动修改表单元素中的值的*/}
<input style={{ width: '100%' }} ref="txt" type="text" value={this.state.msg} onChange={this.handleTextChange} />
// 这是文本框内容改变时候的处理函数
handleTextChange = () => {
this.setState({
msg: this.refs.txt.value
});
}
- 注意
setState的一个问题
:
// 保存最新的state状态值,在保存的时候,是异步地进行保存的,所以,如果想要获取最新的,刚刚保存的那个状态,需要通过回掉函数的形式去获取最新state
this.setState({
msg: this.refs.txt.value
// msg: e.target.value
}, function () {
// 获取最新的state状态值
console.log(this.state.msg);
});
发表评论案例
扩展
context特性
记住一串单词组合getChildContextTypes
前3个、后3个、后两个
一个方法、两个静态属性
相关文章
类型校验
Animation Add-Ons
移动端 关于 键盘将input 框 顶上去的解决思路—个人见解
5.移动App第5天-豆瓣电影
Node.js设置跨域
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();
});
Promise规范
-
定义:就是一个异步的代码规范;
-
好处:
-
更好的帮我们解决回调地狱问题
-
能帮我们很好的实现代码的复用
基于Promise规范的fetch API的使用
项目结构搭建和布局
-
运行
npm install antd --save
安装ant design -
导入相关组件:
import { DatePicker } from 'antd';
- 导入样式:
import 'antd/dist/antd.css';
实现ANT组件的按需加载
-
运行
cnpm i babel-plugin-import --save-dev
-
修改
.babelrc
文件:
{
"presets":["es2015", "stage-0", "react"],
"plugins":[
"transform-runtime",
["import", { "libraryName": "antd", "style": "css" }]
]
}
- 然后只需从 antd 引入模块即可,无需单独引入样式。等同于下面手动引入的方式。
使用react-router-dom实现路由跳转
- HashRouter:是一个路由的跟容器,一个应用程序中,一般只需要唯一的一个HashRouter容器即可!将来,所有的Route和Link都要在HashRouter中进行使用
- 注意:HashRouter中,只能有唯一的一个子元素
-
Link:是相当于超链接一般的存在;点击Link,跳转到相应的路由页面!负责进行路由地址的切换!
-
Route:是路由匹配规则,当路由地址发生切换的时候,就会来匹配这些定义好的Route规则,如果有能匹配到的路由规则,那么,就会展示当前路由规则所对应的页面!
-
Route:除了是一个匹配规则之外,还是一个占位符,将来,此Route所匹配到的组件页面,将会展示到Route所在的这个位置!
// 其中path指定了路由匹配规则,component指定了当前规则所对应的组件
<Route path="" component={}></Route>
-
注意:react-router中的路由匹配,是进行模糊匹配的!可以通过
Route
身上的exact
属性,来表示当前的Route
是进行精确匹配的 -
可以使用
Redirect
实现路由重定向
// 导入路由组件
import {Route, Link, Redirect} from 'react-router-dom'
<Redirect to="/movie/in_theaters"></Redirect>
this.prop和Route的关系【重要】
获取到参数之后,从服务器获取电影数据
使用Node服务器转接豆瓣API
渲染电影列表
相关文章
6.React第6天
RN学习说明
- ReactNative是基于React这门框架的语法来进行开发的;
- RN中,提供了 移动端 专用的一些组件,这时候,我们在网页中使用的一些 元素,div, p, img 都不能用了,只能使用RN固有的组件;
- 最终,开发出来的项目,是要运行到手机上的,那么,如何把一个 RN 的项目,完整的发布到手机上去运行呢,这里,需要结合 安卓的 签名打包步骤,并使用 RN 提供的打包命令,进行完整 apk 文件的发布;最终发布出来的就是 Release 版本的项目,可以上传到应用商店;
配置ReactNative基本开发环境
搭建基本的开发环境 - 英文官网
搭建基本的开发环境 - 中文
这两篇文档对比着进行参考,进行相关的安装;
手机的相关配置
- 使用数据线,把手机链接到电脑上;
- 运行
adb devices
的命令,这个命令,是安卓开发环境提供的; - 需要先开启手机的
开发者模式
- 如果开启开发者模式之后,还是看不到设备,则尝试安装
豌豆荚
这样的工具,让这些工具帮助你在电脑上安装手机的驱动;
搭建RN的项目
- 运行
react-native init 项目名称
来初始化一个react native项目;
- 打包运行项目,把打包好的项目部署到手机中!
- 确保手机已经正确的链接到了当前电脑上,同时手机开启了
开发者调试模式
;可以使用adb devices
来查看当前链接到电脑上的手机设备列表! - 当确认手机正确链接到电脑上之后,可以运行
react-native run-android
来打包当前项目,并把打包好的项目以调试的模式安装到手机中! - 打包完成之后的截图
- React Package窗口的作用
- 当第一打包编译项目部署到手机上之后 - 如何设置开发服务器的地址
项目结构介绍以及一些注意事项
使用样式
##修改项目首屏页面
基本组件的使用介绍
- View:
- Text:
- TextInput:
- Image:
- Button:
- ActivityIndicator:
- ScrollView:这是一个列表滚动的组件
- ListView:也是一个列表滚动的组件,但是,这个组件已经过时了,官方推荐使用 FlatList 来代替它
判断组件是否被卸载
if (this._reactInternalInstance){
// 组件没有被卸载
}
配置Tab栏
配置Tab栏的图标
注意:使用图标,需要使用
Android SDK Manager
安装Android SDK Build-tools 26.0.1
并接收其 license;
案例:豆瓣电影列表
- 电影列表数据:
https://api.douban.com/v2/movie/in_theaters
- 电影详细数据:
https://api.douban.com/v2/movie/subject/26309788
安装路由
- 运行
npm i react-native-router-flux --save
- 路由官网:
https://github.com/aksonov/react-native-router-flux
- 路由相关配置:
https://github.com/aksonov/react-native-router-flux/blob/master/docs/API.md
- 路由简单的DEMO:
https://github.com/aksonov/react-native-router-flux/blob/v3/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';
- 其中,在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>
首页轮播图片URL地址:
- 图片地址1:http://www.itcast.cn/images/slidead/BEIJING/2017410109413000.jpg
- 图片地址2:http://www.itcast.cn/images/slidead/BEIJING/2017440109442800.jpg
- 图片地址3:http://www.itcast.cn/images/slidead/BEIJING/2017441409442800.jpg
渲染电影列表数据
渲染电影详情页面
调用摄像头拍照
react-native-image-picker的github官网
react native 之 react-native-image-picke的详细使用图解
- 运行
npm install react-native-image-picker@latest --save
安装到项目运行依赖,此时调试可能会报错,如果报错,需要使用下面的步骤解决:
- 先删除
node_modules
文件夹 - 运行
npm i
- 运行
npm start --reset-cache
- 运行
react-native link
自动注册相关的组件到原生配置中 - 打开项目中的
android
->app
->src
->main
->AndroidManifest.xml
文件,在第8行添加如下配置:
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
- 打开项目中的
android
->app
->src
->main
->java
->com
->当前项目名称文件夹
->MainActivity.java
文件,修改配置如下:package com.native_camera; import com.facebook.react.ReactActivity; // 1. 添加以下两行: import com.imagepicker.permissions.OnImagePickerPermissionsCallback; // <- add this import import com.facebook.react.modules.core.PermissionListener; // <- add this import public class MainActivity extends ReactActivity { // 2. 添加如下一行: private PermissionListener listener; // <- add this attribute /** * Returns the name of the main component registered from JavaScript. * This is used to schedule rendering of the component. */ @Override protected String getMainComponentName() { return "native_camera"; } }
- 在项目中添加如下代码:
// 第1步: import {View, Button, Image} from 'react-native' 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步:
<Image source={{ uri: this.state.imgURL }} style={{ width: 200, height: 200 }}>
// 第4步:
cameraAction = () => {
ImagePicker.showImagePicker(photoOptions, (response) => {
console.log('response' + response);
if (response.didCancel) {
return
}
this.setState({
imgURL: response.uri
});
})
}
```
6. 一定要退出之前调试的App,并重新运行react-native run-android
进行打包部署;这次打包期间会下载一些jar的包,需要耐心等待!
签名打包发布Release版本的apk安装包
- 请参考以下两篇文章:
如何发布一个apk
- 先保证自己正确配置了所有的 RN 环境
- 在 cmd 命令行中,运行这一句话
keytool -genkey -v -keystore my-release-key2.keystore -alias my-key-alias2 -keyalg RSA -keysize 2048 -validity 10000
- 其中:
my-release-key.keystore
表示你一会儿要生成的那个 签名文件的 名称【很重要,包找个小本本记下来】 -alias
后面的东西,也很重要,需要找个小本本记下来,这个名称可以根据自己的需求改动my-key-alias
- 当运行找个命令的时候,需要输入一系列的参数,找个口令的密码,【一定要找个小本本记下来】
- 当生成了签名之后,这个签名,默认保存到了自己的用户目录下
C:\Users\liulongbin\my-release-key2.keystore
- 将你的签名证书copy到 android/app目录下。
- 编辑
android
->gradle.properties
文件,在最后,添加如下代码:
MYAPP_RELEASE_STORE_FILE=your keystore filename
MYAPP_RELEASE_KEY_ALIAS=your keystore alias
MYAPP_RELEASE_STORE_PASSWORD=*****
MYAPP_RELEASE_KEY_PASSWORD=*****
- 编辑 android/app/build.gradle文件添加如下代码:
...
android {
...
defaultConfig { ... }
+ signingConfigs {
+ release {
+ storeFile file(MYAPP_RELEASE_STORE_FILE)
+ storePassword MYAPP_RELEASE_STORE_PASSWORD
+ keyAlias MYAPP_RELEASE_KEY_ALIAS
+ keyPassword MYAPP_RELEASE_KEY_PASSWORD
+ }
+}
buildTypes {
release {
...
+ signingConfig signingConfigs.release
}
}
}
...
- 进入项目根目录下的
android
文件夹,在当前目录打开终端,然后输入./gradlew assembleRelease
开始发布APK的Release版; - 当发行完毕后,进入自己项目的
android\app\build\outputs\apk
目录中,找到app-release.apk
,这就是我们发布完毕之后的完整安装包;就可以上传到各大应用商店供用户使用啦;
注意:请记得妥善地保管好你的密钥库文件,不要上传到版本库或者其它的地方。
相关文章
来源:CSDN
作者:blueboz2
链接:https://blog.csdn.net/blueboz/article/details/104450614