React阶段 - 使用 create-react-app 构建项目

自动化构建项目

通过前面 script 的方式虽然也能完成 React.js 的开发(上一篇的文章中的方式)
但是,却存在这很大的问题,模块化怎么实现

create-react-app

Create React App 基于 Node.js 编写的命令行工具,通过它可以快速生成 React.js 项目
内置了 Babel、Webpack 等工具帮助我们实现 ES6+ 解析、模块化解析打包
通过它,我们可以使用 模块化 以及 ES6+ 等更新的一些特性
同时它还内置 ESLint 语法检测工具、Jest 单元测试工具
还有一个基于 Node.js 的 WebServer 帮助我们更好的在本地预览应用(热更新)
下载执行后即可搭建项目

安装与使用

  • 下载安装
    理论上 npmyarnnpx 都可以
    npm 的方式 npm i -g create-react-app
    yarn 的方式 yarn global add create-react-app
  • 创建项目
    npm 方式create-react-app 项目名称
    npx 方式(npx存在)npx create-react-app 项目名称
  • 创建之后的文件摆放
    React阶段 - 使用 create-react-app 构建项目_第1张图片
  • 启动项目npm start
    启动一个内置的本地 WebServer,根目录映射到 ‘./public’ 目录,默认端口:3000
    会直接启动浏览器,将项目在浏览器上运行,实现热更新
  • 打包项目npm run build
    将项目整体打包,然后可以上传到远端

组件

类式组件

需要继承React,{Component}组件
组件内部需要有render()方法,render()方法内部的标签必须return返回
需要export default导出

import React,{Component} from "react";
class FriendList extends Component{
    // 函数放置位置
    render() {
        return (
        	// 放置页面渲染的标签
            <div className="friend-list"> </div>
        );
    }
}
export default FriendList;

引入静态资源
直接引入即可,不需要手动使用
import "./FriendList.css"

嵌套循环
create-react-app的实例中是要求用到key
直接在一个整体中嵌套某些情况下会显得代码臃肿,可阅读性下降
所以这里直接抽取出来处理

  • 数据结构
    React阶段 - 使用 create-react-app 构建项目_第2张图片
  • 第一层处理(实际上的作用就是拆分数据,传递给下一层)
    将对象的属性名遍历Object.keys(data)返回处理为一个数组(仅仅是为了借用处理后的length值)
    将对象的属性名:item属性值:data[item]传递给子组件
    同时处理key这里绑定index只是为了避免页面警告,实际使用时key有讲究的
	return (
        <div className="friend-list">
			{
				Object.keys(data).map((item,index)=>{
					return (
						<FriendGroup 
							name = {item}
                            key={index}
                            value = {data[item]} 
						/>
					)
				})
			}
		</div>
	);
  • 第二层处理(真正意义上的渲染页面)
    接收数据结构赋值let {title,list} = this.props.value;
    使用数据,渲染页面
    render(){
        console.log(this.props)
        let {title,list} = this.props.value;
        return (
            <div className="friend-group"> 
                <dt>{title}</dt>
                {
                    list.map((item,index)=>{
                        return (<dd key={index}>{item.name}</dd>)
                    })
                }
            </div>
        )
    }
state

类似于vue组件中的data属性
state 的主要作用是用于组件保存、控制、修改自己的可变状态
在组件内部进行初始化,也可以在组件内部进行修改,但是组件外部不能修改

静态写法
  • 代码展示
	class App extends Component {
	    state={
        	nub:23,
        	name:"Mr_Qin",
        	say:"hello"
    	}
    	render(){
        	let {nub} = this.state; 
        	console.log(this.state)
        	return (<div>
            	<p> {this.state.nub} </p>
        	</div>)
    	}
	}
  • 页面效果
    可以通过this.state去获取数据
    React阶段 - 使用 create-react-app 构建项目_第3张图片
constructor 写法

类组件中,定义constructor,一定要接受props,调用super(props)

	class App extends Component {
    	constructor(props){
        	super(props)
        	this.state={
            	nub:0
        	}
    	}
     	fn=()=>{
        	this.setState({
            	nub:this.state.nub + 1
        	})
    	}
    	render(){
    		// 通过this调用箭头函数 
        	let {nub} = this.state; 
        	return (<div>
            	<p> {this.state.nub} </p>
        	</div>)
    	}
	}
设置修改state中的属性

需要通过this.setState()去设置,直接通过this.state.属性=属性值是不能操作的

  • 方法1:内部直接修改赋值
	class App extends Component {
	    state={
        	nub:23,
        	name:"Mr_Qin",
        	say:"hello"
    	}
    	render(){
    		// this 指向当前组件
        	let {nub} = this.state; 
        	return (<div>
            	<p> {this.state.nub} </p>
            	<button
                	onClick={()=>{
                    	// 只去查找对相应的属性 不是整体覆盖
                    	this.setState({
                        	nub:nub+1,
                        	sex:"男"
                    	})
                	}}
            	>add one year</button>
        	</div>)
    	}
	}
  • 方法2:通过调用函数实现
	class App extends Component {
	    state={
        	nub:23,
        	name:"Mr_Qin",
        	say:"hello"
    	}
     	fn=()=>{
        	this.setState({
            	nub:this.state.nub + 1
        	})
    	}
    	render(){
    		// 通过 this调用箭头函数(普通函数 this会跑偏) 
        	let {nub} = this.state; 
        	return (<div>
            	<p> {this.state.nub} </p>
            	<button
                	onClick={this.fn}
            	>add one year</button>
        	</div>)
    	}
	}
注意:this.setState()修改属性时,只去查找对相应的属性 不是整体覆盖

函数式组件

组件的第1个参数是 props 用来接收父级传递的信息
组件中的 return(必写) 定义该组件要渲染的内容
没有生命周期,没有 this 没有 state
在 16.7 (测试版)之前,函数组件一直当做纯渲染组件 来使用

	import React from 'react';

  	function Child(props){ // props ⇒ 接收父组件的数据
    	return <h3>{props.info}</h3>
  	}

	function App(){
  		// this ⇒ undefind
    	console.log(this)
    	return (
      	<div>
        	来啊 快活啊
        	// 子组件
        	<Child info="诶嘿" />
      	</div>)
  	}

	export default App;

React阶段 - 使用 create-react-app 构建项目_第4张图片

useState

与类式组件中的state功能相近,用于数据管理
使用前需要引入依赖 import {useState} from 'react';

使用说明

let [属性名,修改方法] = useState(属性名的初始值)

  function Child(props){
  	console.log(props.data)
    return (
    	<div> 
			<h3>{props.data.name}</h3>
			<h3>{props.data.age}</h3>
		</ div>
    )
  }
  
  function App(){
    let [data,setData] = useState({
      name:"浩克",
      age:24
    })
    return (
      <div>
      	<Child data={data} />
        <button 
          onClick={()=>{
            // 会覆盖之前的数据
            setData({
              name:"疯狂的麦咭"
            })
          }}
        >变身</button>
      </div>)
  }
注意:使用useStae修改数据,会直接覆盖原先的值

React阶段 - 使用 create-react-app 构建项目_第5张图片

组件通信

父传子

组件传参 | 接收
传参
在组件调用的位置属性名=属性值传递

	...
	return (
		<FriendGroup 
			name = {item}
			key={index}
			value = {data[item]} 
		/>
	)

接收
创建组件的文件中this.props去调用拿到数据

	class FriendGroup extends Component{
    	render(){
        	console.log(this.props)
        	// 这里去接收传递的数据
        	let {title,list} = this.props.value;
        	return (
            	<div className="friend-group"> 
                	<dt>{title}</dt>
            	</div>
        	)
    	}
	}
子传父

类似于制作一个函数传递给子组件,然后允许子组件调用函数,将结果返回,父组件拿到结果后处理
React阶段 - 使用 create-react-app 构建项目_第6张图片
传参
在组件调用的位置属性名=属性值传递

	...
	return (
		<FriendGroup 
			name = {item}
            key={index}
            value = {data[item]}
            isOpen= {isOpen}
			changeOpen={this.changeOpen}  
		/>
	)

接收
创建组件的文件中this.props去调用拿到数据

	class FriendGroup extends Component{
    	render(){
        	// 这里去接收传递的数据
        	let {name,isOpen,changeOpen} = this.props;
        	let {title,list} = this.props.value;
        	return (
            	<div className="friend-group"> 
                	<dt
                    	onClick={()=>{
                        	changeOpen(name)
                    	}} 
                	>{title}</dt>
            	</div>
        	)
    	}
	}
跨组件传参

就像是在组件外部设置了一个仓库,在仓库中 获取 / 存放
定义仓库
文件名为context.js内部代码是固定的

	import {createContext} from "react"

	let context = createContext();
	let {Consumer,Provider}= context;

	export default context
	export {Consumer,Provider}

传参
Provider 是一个标签的存在,传递的数据可以放在标签上
包裹了父组件

	import {Provider} from "./context"
	// Provider 是一个标签的存在,传递的数据可以放在标签上
	class App extends Component {
    render(){
        return (
        	<Provider value={
            	{info:"测试数据"}
        	}>
            	<div>
                	<FriendList />
            	</div>
        	</Provider>)
    	}
	}
	export default App;

接收
Consumer也是标签的存在,标签内部可以拿到数据
在子组件的子组件中使用跨组件了

	import {Consumer} from "./context"
	class FriendGroup extends Component{
    	render(){
        	// 这里去接收传递的数据
        	let {name,isOpen,changeOpen} = this.props;
        	let {title,list} = this.props.value;
        	return (
            	<div className="friend-group"> 
                	<dt
                    	onClick={()=>{
                        	changeOpen(name)
                    	}} 
                	>{title}</dt>
                	<dd>
                    	<Consumer>{(val)=>{return val.info}}</Consumer>
                	</dd>
            	</div>
        	)
    	}
	}

页面效果
React阶段 - 使用 create-react-app 构建项目_第7张图片

你可能感兴趣的:(React)