快来领取今日份精神食粮
刚信心满满开始准备写代码时,却是满屏的爆红,搞的我一下午的心情都不好了~
- 脚手架搭建出错
- 卸载yarn之后,又出现node版本低~
- node升级后,npm又出现bug
最终解决方案:
卸载nvm,重新安装node。因为node10版本之后,npm不会随之更新。
不想当炮灰的,建议大家下载稳定版。
下载之后,就是傻瓜式安装。安装成功后,利用黑窗口进行检测。
一.性能优化
react组件更新的时机:只要setState()被调用了,就会引起组件更新。不论数据改前改后是否一样,或者修改的数据是否在页面上呈现,都会进行更新组件。但是vue中,数据必须在模板使用,并且数据发生变化才能引起组件的重新渲染。所以,在React里,只有做性能优化,才可以把这种无效的渲染阻止掉。
1)、shouldComponentUpdate()钩子函数
shouldComponentUpdate(nextProps, nextState){
console.log("this.state",this.state);//当前状态
console.log("nextState",nextState);//新的状态
return false;//不再渲染。
}
我们可以在这个钩子函数里利用return false,来跳过组件更新。
2)、PureComponent
React15.3中新加了一个 PureComponent 类,只要把继承类从 Component 换成 PureComponent 即可
-
PureComponent 默认提供了一个具有浅比较的shouldComponentUpdate方法。只是比较数据是否有变化,并不会判断数据是否在页面上展示;
-
当props或者state改变时,PureComponent将对props和state进行浅比较;
-
不能再重写shouldComponentUpdate;
-
PureComponent只是解决了数据不变化的情况下不做再次的渲染,而不能解决是否在页面上使用。
Component和PureComponent的区别:
①组件继承自 Component 时,只要setState()被调用了,就会引起组件更新。
②不论数据改前改后的是否一样,或者修改的数据是否在页面上呈现,都会进行更新组件。③PureComponent只能保证数据不变化的情况下不做再次的渲染。
class MyCom extends React.PureComponent{
constructor(){
super();
this.state={
username:"张三疯",
age:12,
wife:{
name:"宝宝的宝宝"
}
}
}
componentWillUpdate(){
console.log("componentWillUpdate");
}
componentDidUpdate(){
console.log("componentDidUpdate");
}
fn(){
//1、 不会引起组件的更新,因为,值没有变
// this.setState({
// username:this.state.username
// });
//2、 会引起组件的更新,因为,值变了
// this.setState({
// username:"dddd"
// });
//3、 会引起组件的更新,因为,值变了(即使age么有在页面上显示,也会引起更新)
// this.setState({
// age:this.state.age+1
// })
//4、不会引起组件的更新,因为,PureComponent里只做了浅比较
let obj = this.state.wife;
obj.name="宝宝";
this.setState({
wife:obj
});
}
render(){
console.log("render");
return (
<div>
<input type="text" value={this.state.username} /><br/>
<input type="button" value="测试" onClick={()=>this.fn()} />
</div>
)
}
}
二.脚手架
2.1facebook的官方脚手架
1)、安装 create-react-app
npm install create-react-app -g | yarn global add create-react-app
2)、用脚手架创建 react项目
create-react-app 项目名称
如:create-react-app reactapp01
注意:项目名称不能有大写字母。
3)、 启动项目:
npm start | yarn start
4)、目录解析:
4.1)第一级目录
node_modules:是项目依赖的模块
src:是程序员写代码的地方,src是source的缩写,表示源代码。
public: 静态资源。
4.2)展开目录:
- Public:
index.html:是html网页,是个容器。这个文件千万不敢删除,也不能改名。
只有Public目录下 的文件才会被index.html文件引用,这是静态资源,index.html不会引用src目录下的文件
manifest.json: 生成一个网页的桌面快捷方式时,会以这个文件中的内容作为图标和文字的显示内容
- src:
src目录是源代码,webpack只会打包这个目录下的文件,所以,把需要打包的文件都放在这个目录下。
Index.js:是主js文件,千万不敢删除,也不能改名
Index.css:是index.js引入的css文件(也是模块,webpack会把css也打包成模块) 千万不敢删除,也不能改名
App.js:是一个组件示例(模块),在 index.js里会引入这个组件。我们自己需要写组件时,只需要复制App.js文件即可。
App.css:是App.js文件引入的css文件(也是模块,webpack会打包)。
Logo.svg:是图片
registerServiceWorker.js:支持离线访问,所以用起来和原生app的体验很接近,只有打包生成线上版本的react项目时,registerServiceWorker.js才会有效。服务器必须采用https协议
5)、打包
npm run build | yarn build
6)、如果要解构出配置文件:
npm run eject | yarn eject 解构出所有的配置文件 可选
7)、如果需要调试,安装react-dev-tools工具
-
先进入到官网
-
通过git clone https://github.com/facebook/react-devtools.git下载到本地(或者直接点击下载)
-
下载之后进入到react-devtools目录下,用npm安装依赖
npm --registry https://registry.npm.taobao.org install
- 然后在npm run build:extension:chrome
环境配置
1、把配置解构
npm run eject | yarn eject
报git错误时:
git add . -> git commit -m 'init' -> yarn eject
报缺少babel 包: 安装一下
2、修改端口
//修改script/start.js
const DEFAULT_PORT = parseInt(process.env.PORT, 10) || 3001;
3、去除eslint 警告
//config/webpack.config.js
//注释关于eslint的导入和rules规则
资源限制
-
本地资源导入(import) 不可以导入src之外的包
-
相对 指向src,绝对路径 指向了 public目录 <img src={"/img/1.jpg"} />
-
前景图片, 相对 和 绝对路径 都指向了 public目录
在脚手架里做项目的步骤:
1)、创建目录
在src目录下创建以下文件夹:
-
assets :静态资源文件夹
-
components:组件文件夹
/components/a组件/ a.js 和 a.css
-
pages:页面文件夹
-
styles:样式文件夹
2)、图片文件夹
1.在public里放图片。
把图片放到public文件夹中 直接使用图片名使用(使用绝对路径(img src="/img/image.jpg" />)),这样的图片不会打包。
2.使用require引用,require(‘图片的相对路径’),Require中只能使用字符串不能使用变量,这样的图片会打包。如:
<img src={require("…/…/assets/img/banner04.jpg").default} />
反向代理:
https://create-react-app.dev/docs/proxying-api-requests-in-development/
1、安装模块(http-proxy-middleware):
npm install http-proxy-middleware --save-dev
yarn add http-proxy-middleware -D
2、在项目源代码的根目录创建文件: src/setupProxy.js
const { createProxyMiddleware } = require('http-proxy-middleware');
module.exports = function(app) {
console.log("proxy");
app.use(
'/api',
createProxyMiddleware({
target: 'http://xmb8nf.natappfree.cc',
changeOrigin: true,
// 重写接口路由
pathRewrite: {
'^/api': ''
}
})
);
};
3、重启服务器
yarn start
2.2第三方脚手架
yeomen/dva/umi
2.3组件传值
2.3.1.父子组件通信方式
(1) Props传递数据与Props传递方法
父组件—>子组件传递数据,用props传递数据
eg:App组件=》Son组件传值
-
App组件
-
Son组件
子组件—>父组件传递数据,用props传递方法
父组件利用props传递方法给子组件,子组件回调这个方法的同时,将数据传递进去,使得父组件的相关方法得到回调,这个时候就可以把数据从子组件传递给父组件了。
- 父组件App
function App() {
// 子朝父传
function fn(str){
console.log("str",str);
}
return (
<div className="App">
<h5>App组件</h5>
<Son
fn={fn}/>
</div>
);
}
export default App;
- 子组件Son
class Son extends React.Component {
chuan = () => {
this.props.fn("我是儿子");
};
render() {
return (
<div>
<input type="button" value="传给父" onClick={this.chuan} />
</div>
);
}
}
export default Son;
终于懂得了其中的道理,好开森呀~要不觉得传来传去的,都不知道在干啥子
(2) ref 标记
组件间通信除了props外还有onRef方法,不过React官方文档建议不要过度依赖ref。
思路:当在子组件中调用onRef函数时,正在调用从父组件传递的函数。this.props.onRef(this)这里的参数指向子组件本身,父组件接收该引用作为第一个参数:onRef = {ref =>(this.child = ref)}然后它使用this.child保存引用。之后,可以在父组件内访问整个子组件实例,并且可以调用子组件函数。
2.3.2.非父子组件通信方式
(1)订阅发布(pubsub模块)
- 订阅: token=pubsub.subscribe(‘消息名’,回调函数(‘消息名’,数据))
- 发布: pubsub.publish(‘消息名’,数据)
- 清除指定订阅:pubsub.unsubscribe(token|‘消息名’);
- 清除所有:pubsub.unsubscribeAll()
eg:Son组件给Son1组件传值(兄弟组件)
首先写一个工具类
在App组件中使用这两个组件
(2)状态提升
使用 react 经常会遇到几个组件需要共用状态(数据)的情况。这种情况下,我们最好将这部分共享的状态提升至他们最近的父组件当中进行管理。
即:把原本属于子组件的state,放在父组件里进行管理。
https://www.reactjscn.com/docs/lifting-state-up.html
父组件:src/components/Parent.js
import React from "react";
import Son1 from "./Son1";
import Son2 from "./Son2";
export default class Parent extends React.Component {
constructor(props){
super(props);
this.state = {val:'默认值'};
}
tempFn(val){
console.log("tempFn");
console.log("val",val);
this.setState({
val:val
})
}
render = () => (
<div >
父组件
<hr/>
<Son1 onMyClick={(val)=>this.tempFn(val)} />
<Son2 val={this.state.val} />
</div>
)
}
Son1组件
src/components/Son1.js
export default class Son1 extends React.Component {
constructor(props){
super(props);
this.state = {
name:"我是son1"
};
}
chuan(){
this.props.onMyClick(this.state.name);
}
render = () => (
<div >
son1组件
<input type="button" value="son1传给parent" onClick={()=>{this.chuan()}} />
<hr/>
</div>
)
}
Son2组件
src/components/Son2.js
export default class Son2 extends React.Component {
constructor(props){
super(props);
this.state = {};
}
render = () => (
<div >
<p>son2组件</p>
<p>val:{this.props.val}</p>
<hr/>
</div>
)
}
这份blog很不满意~bug影响心情呀