react所有的生命周期函数,render函数一定要有。
此次项目是基于react的单页应用,所以需要用到脚手架工具create-react-app来快速搭建一个开发环境。
npm install -g create-react-app
create-react-app my-app
cd my-app
npm run start
这样,就可以自动在浏览打开一个端口号为3000的服务,显示欢迎页面。
本次项目是组件化开发的。页面的话主要分为主页面,列表页,详情页。公有部分,在每个页面中都有,所以,在项目目录中单独开辟一个空间。在app/components目录下开发公共部分。页面在app/pages目录下进行开发。
● 组件之间的跳转需要用到路由,这里用的是前端路由(react-router),而app.js是入口文件,所以这里将路由写在app.js中,引入路 由,引入react。配置路由项(默认路由,子路由,嵌套路由,动态路由),每个路径对应不同的组件,所以需要引入不同的组件。
● 公共部分的某些数据需要动态获取,所以需要现在本地模拟数据(mock),然后用fiddler正向代理。具体步骤具体分析。在组件中需要发送一个ajax请求,获取数据,将获取到的数据放到state中,进行页面中数据的更新。state是在构造函数constructor中定义的,修改的话,是用setState修改的,而且是异步的。在页面中将获取到的数据,进行遍历,循环输出在页面中,有链接的带上链接。
● 主页面的内容基本上是固定的,为了防止每次回到页面都发送ajax请求,所以将首页的数据存到store中,这里用到的是react-redux。所以需要在app.js中引入’react-redux‘中的provider,将store分发给各个组件。在主页面的组件中引入’react-redux‘中的connect,让组件与store进行连接。
○ 组件中的数据,想放到store中,需要先ajax动态获取,然后再创建action,调用dispatch()方法,将action传给reducer,reducer中返回新的数据,在组件中接收到数据,循环显示在页面中。
○ 轮播图(swipper) 全局引用swiper.css,在swiper组件中引入swiper.js。render函数中返回页面渲染的内容。
○ echarts 在node环境中安装echarts,在组件中引入echarts模块,初始化一个echarts实例。在官网中查找自己需要用到的图表,将options引入过来,添上数据,调用setOption(),在页面上展示信息。
○ 下拉刷新 引入iscroll-probe.js文件,对应Dom需要固定的高度。利用iscroll中自带方法监听scroll和scroll事件,以此来作为判断条件,进行数据重新加载。选择js文件的时候有坑。
○ canvas 调用canvas中的各种方法进行绘图。
● 每个id对应着不同的内容,所以详情页的内容可以通过id 动态获取。同样也是将ajax获取到的数据放到store,与主页面中数据的操作类似。
○ 右侧固定 当页面滚动时,让右侧固定一个地方。这里用到了window来监听滚动条的变化,当组件销毁时需要解绑,不然会报错。this指向问题是一个坑。
○ 音频,视频播放 需要用到HTML5中添加的audio和video标签,以及js中定义的一些方法,属性和事件。
● 列表页,主要展示了某一类型的数据信息。通过id获取后台数据,将数据展示在页面中。具体的一些操作与主页面也是类似的。
至此,整个项目的开发过程算是完成了。但是需要与后端进行联调,并将项目打包上线。联调涉及到跨域的问题,我们需要在package.json中配置反向代理(因为webpack已经配置好了反向代理,这里只需简单配置即可)。
1.执行yarn reject命令,手动配置webpack项,将css样式也进行模块化开发,共有的样式可以不按模块分配。将开发环境与生产环境都进行修改。
2.执行yarn build将项目打包,打包后的文件在build目录下,将目录下的文件复制到后端项目的public目录下,这时,重新开启一个后端服务器,就可以看见页面了。
provider:接收一个参数store,使store能够在每一个组件中被连接;
connect:在子组件中被调用,他的第二个括号里面接受的是子组件:
(1) 第一个括号里面接收两个参数:(mapStateToProps, mapdispatchToProps)
mapstateToProps:把store里面的数据按照规则映射到props里。
mapdispatchToProps:把这里的函数里的一些函数映射props里。经过这样一个操作,子组件变成了一个ui组件,而connect返回了最终的容器组件。
(2) 最后一个括号之所以写子组件的名字,是因为让子组件和store做链接;
provider:把store传递给每一个组件。在根组件中外层嵌套一个Provider,这样每一个子组件可以获取到store。
在input.js中绑定keyup事件。引入connect和store做连接,把handlekeyup映射到props里,调用dispatch,映射到props中,list组件变成了一个ui组件,通过connect方法返回一个容器组件。
redux建议我们把所有的数据都存放在store里( 容易管理 ),不管数据共享还是不共享。
父组件引入Item子组件,然后通过属性的方法向子组件传值:
子组件通过 this.props.value 接收到父组件传递过来的值:
在react中子组件向父组件传递参数不能用事件的方式。要通过调用父组件传递过来的方法。
父组件向子组件传递方法:
子组件通过调用父组件传过来的方法:
react中的数据都存放在state中,当state发生改变的时候或者当props发生改变的时候,render函数就会重新执行。
(1) react中的事件绑定:(是通过事件委托的方式绑定事件的)表面上是绑定在该元素上,通过编译转化为es5的代码,通过事件代理的方式把事件统一绑定在根元素上。这样可以达到性能优化的目的。事件代理,动态增加的元素,不用再绑定事件。
(2) 函数作用域的绑定要放在constructor里面写,这样的话,每一个传递给子组件的方法的引用是固定的,子组件就不会因为这个方法而重新渲染页面,提高性能。
每一次执行render函数的时候,bind也会返回一个新的方法,每次执行都会返回一个全新的函数。当调用bind(this)的时候,调用旧的函数结合作用域,返回一个新的函数,两次执行render函数,执行的两个函数是不相等的。子组件接收proxy,会重新渲染页面,会消耗性能,使子组件做无谓的渲染。
当数据发生改变的时候,父组件中的render函数会重新执行,绑定的方法会传给子组件,子组件接收到方法,发现跟之前的方法是一样的,然后就不重新渲染页面了,减少一次页面渲染的次数,提高新能。
reactDOM.render()反复执行,会重新渲染页面。
propsType的作用:
(1) 用来帮助对接收的属性值进行校验,约束传递数据的内容类型,校验父组件传递给子组件的值的类型;
(2) 设置父组件传递过来属性的默认值。
propsType的使用:
react中的组件都是一个class。
判断页面是前端渲染的还是后端拍出来的:查看源代码,源代码中没有的内容,就是前端渲染的,源代码中有的内容就是后端拍出来的。
状态:组件自己的数据都放在list.state中。
es5中建立组件:
es6建立组件:
和页面展示毫无关系的数据,不放在state里面。state里面只存放和页面有关的数据。否则数据一改变,render函数会重新执行,页面会重新渲染,降低性能。
改变state,必须调用setState()方法,才能改变state中的数据。
在react发送请求:
(1) axios发送请求:(和在vue中使用的方法一样)在netwok中type值为:xhr。【https://github.com/axios/axios】
// 先下载axios
yarn add axios
// 然后引入axios
import axios from ''axios"
发送的请求写在componentDidMount()生命周期函数里面。
(2) 使用fetch发送请求:【https://github.com/github/fetch】在netwok中type值为:fetch。
// 先下载
npm install whatwg-fetch --save yarn add whatwg-fetch
// 引入
import 'whatwg-fetch'
到react项目目录中执行命令: yarn eject
然后在该目录下面会增加一个config文件夹,在该文件夹下 :
webpack.config.dev.js:webpack本地打包的配置文件。在该文件下搜索css找到:
然后引入css样式:import style from './style.css';className要修改为:
问题:
(1) 当在config中设置module:true时,该组件中的样式就形成了一个局部样式,只能供该组件的元素使用。然后设置的swiper就出了问题。
解决办法:
在config中设置时,在webpack.config.dev.js文件中搜索css,在module中找到css配置文件的那一部分,粘贴一份,将css改为mcss,并在mcss中的css-loader下的options中添加一个module:true。作用是当发现是mcss文件时,将其变成一个局部的样式,当找到css样式时,就是全局样式。module:true的作用就是将组件中的样式变为局部样式。只在该组件内使用。
1. webpack 按需加载:【https://www.cnblogs.com/libin-1/p/6537936.html】
2. vue-router 按需加载:【http://blog.csdn.net/xiejiashu/article/details/78018234?locationNum=10&fps=1】
为了让页面更快的加载完成,第一时间提供给用户。也为了帮助客户端节省流量资源,我们可以启动vue-router
访问首页的时候按需加载:
(1) 图片按需加载:
将图片的真实资源地址存放在标签自定义的属性里面,如data-src,那么src属性就用一张透明的图片占用(1k左右),当触发动作时,交换属性,就可以达到按需加载。常见的交互效果是图片滚动按需加载。
(2) 内容按需加载:
(1) 利用textarea标签将你需要加载的html结构全放在标签里面,这样页面解析的时候会忽略他们。当触发的时候,将textarea的value赋值给父元素的innerHTML,就达到了按需加载。
(2) script标签的type="text/html"也可以,常常用作当js代码片段模板处理,如弹出框。
(3) 调用程序生成的ajax接口,通过触发动作往页面中添加内容。如瀑布流,点击加载更多,链接,通过滚动触发,请求ajax接口,加载更多图片资源。.