React(四)

快来领取今日份精神食粮
在这里插入图片描述
刚信心满满开始准备写代码时,却是满屏的爆红,搞的我一下午的心情都不好了~

  • 脚手架搭建出错
    在这里插入图片描述
  • 卸载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工具

  1. 先进入到官网

  2. 通过git clone https://github.com/facebook/react-devtools.git下载到本地(或者直接点击下载)

  3. 下载之后进入到react-devtools目录下,用npm安装依赖

​ npm --registry https://registry.npm.taobao.org install

  1. 然后在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影响心情呀

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是一个简单的React实现级联动的例子: ```jsx import React, { useState } from "react"; const options = { "浙江省": { "杭州市": { "西湖区": ["西湖街道", "灵隐街道"], "上城区": ["中山北路街道", "南星街道"] }, "宁波市": { "海曙区": ["中山东路街道", "白云街道"], "江东区": ["庄桥街道", "七塘街道"] } }, "江苏省": { "南京市": { "玄武区": ["梅园新村街道", "红山街道"], "秦淮区": ["夫子庙街道", "集庆门街道"] }, "苏州市": { "姑苏区": ["虎丘街道", "石路街道"], "吴中区": ["香山街道", "越溪街道"] } } }; function Cascader() { const [province, setProvince] = useState("浙江省"); const [city, setCity] = useState("杭州市"); const [district, setDistrict] = useState("西湖区"); const [street, setStreet] = useState("西湖街道"); const handleProvinceChange = (e) => { setProvince(e.target.value); setCity(Object.keys(options[e.target.value])[0]); setDistrict(Object.keys(options[e.target.value][Object.keys(options[e.target.value])[0]])[0]); setStreet(options[e.target.value][Object.keys(options[e.target.value])[0]][Object.keys(options[e.target.value][Object.keys(options[e.target.value])[0]])[0]][0]); }; const handleCityChange = (e) => { setCity(e.target.value); setDistrict(Object.keys(options[province][e.target.value])[0]); setStreet(options[province][e.target.value][Object.keys(options[province][e.target.value])[0]][0]); }; const handleDistrictChange = (e) => { setDistrict(e.target.value); setStreet(options[province][city][e.target.value][0]); }; const handleStreetChange = (e) => { setStreet(e.target.value); }; return ( <div> <select value={province} onChange={handleProvinceChange}> {Object.keys(options).map((option) => ( <option key={option} value={option}> {option} </option> ))} </select> <select value={city} onChange={handleCityChange}> {Object.keys(options[province]).map((option) => ( <option key={option} value={option}> {option} </option> ))} </select> <select value={district} onChange={handleDistrictChange}> {Object.keys(options[province][city]).map((option) => ( <option key={option} value={option}> {option} </option> ))} </select> <select value={street} onChange={handleStreetChange}> {options[province][city][district].map((option) => ( <option key={option} value={option}> {option} </option> ))} </select> </div> ); } export default Cascader; ``` 在这个例子中,我们使用了`useState`来管理个状态:`province`、`city`、`district`和`street`,分别代表省、市、区和街道。我们通过`select`元素来实现级联动,每一级的选项都是根据上一级的选项来动态生成的。 当省份选项发生改变时,我们需要根据选中的省份来动态生成城市选项,同时也需要把城市、区和街道的选项重置为默认值。当城市选项发生改变时,我们需要根据选中的城市来动态生成区选项,并重置街道选项为默认值。当区选项发生改变时,我们需要根据选中的区来动态生成街道选项。当街道选项发生改变时,我们只需要更新`street`状态的值即可。 上述代码只是一个简单的例子,实际情况下可能会更加复杂。但是原理是相同的:通过状态来实现级联动,根据当前选中的选项来动态生成下一级选项。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值