【18】react1 基本知识+todolist案例+github搜索案例

bootcdn.cn网址,常用的js库

用于构建用户界面的javascript库

  • 特点
  1. 采用组件化模式,声明式编码,提高开发效率和组件复用率
  2. 在React Native中可以使用React语法进行移动端开发
  3. 使用虚拟Dom和优秀的Diffing算法,尽量减少与真实Dom的交互

babel用途:1.ES6转ES5 2.jsx转js

hello,react

<body>
	<!-- 准备好一个“容器” -->
	<div id="test"></div>

	<!-- 引入react核心库 -->
	<script type="text/javascript" src="../js/react.development.js"></script>
	<!-- 引入react-dom,用于支持react操作DOM -->
	<script type="text/javascript" src="../js/react-dom.development.js"></script>
	<!-- 引入babel,用于将jsx转为js -->
	<script type="text/javascript" src="../js/babel.min.js"></script>

	<script type="text/babel" > /* 此处一定要写babel */
		//1.创建虚拟DOM
		const VDOM = <h1>Hello,React</h1> /* 此处一定不要写引号,因为不是字符串 */
		//2.渲染虚拟DOM到页面
		ReactDOM.render(VDOM,document.getElementById('test'))
	</script>
</body>

虚拟dom和真实dom

关于虚拟DOM:
1.本质是Object类型的对象(一般对象)
2.虚拟DOM比较“轻”,真实DOM比较“重”,因为虚拟DOM是React内部在用,无需真实DOM上那么多的属性。
3.虚拟DOM最终会被React转化为真实DOM,呈现在页面上。

jsx语法规则

1.定义虚拟DOM时,不要写引号。
2.标签中混入JS表达式时要用{}。
3.样式的类名指定不要用class,要用className。
4.内联样式,要用style={{key:value}}的形式去写。
5.只有一个根标签
6.标签必须闭合<input type="text"/>
7.标签首字母
(1).若小写字母开头,则将该标签转为html中同名元素,若html中无该标签对应的同名元素,则报错。
(2).若大写字母开头,react就去渲染对应的组件,若组件没有定义,则报错。

区分【js语句(代码)】与【js表达式】

一定注意区分:【js语句(代码)】与【js表达式】
1.表达式:一个表达式会产生一个值,可以放在任何一个需要值的地方
下面这些都是表达式:
(1). a
(2). a+b
(3). demo(1)
(4). arr.map()
(5). function test () {}
2.语句(代码):
下面这些都是语句(代码):
(1).if(){}
(2).for(){}
(3).switch(){case:xxxx}

模块与组件、模块化与组件化的理解

模块

1.理解:向外提供特定功能的js程序, 一般就是一个js文件
2.为什么要拆成模块:随着业务逻辑增加,代码越来越多且复杂。
3.作用:复用js, 简化js的编写, 提高js运行效率

组件

1.理解:用来实现局部功能效果的代码和资源的集合(html/css/js/image等等)
2.为什么要用组件: 一个界面的功能更复杂
3.作用:复用编码, 简化项目编码, 提高运行效率

模块化

当应用的js都以模块来编写的, 这个应用就是一个模块化的应用

组件化

当应用是以多组件的方式实现, 这个应用就是一个组件化的应用

5 创建组件

5.1 函数式

执行了ReactDOM.render(…之后,发生了什么?
1.React解析组件标签,找到了MyComponent组件。
2.发现组件是使用函数定义的,随后调用该函数,将返回的虚拟DOM转为真实DOM,随后呈现在页面中。

5.2 类

执行了ReactDOM.render(…之后,发生了什么?
1.React解析组件标签,找到了MyComponent组件。
2.发现组件是使用类定义的,随后new出来该类的实例,并通过该实例调用到原型上的render方法。
3.将render返回的虚拟DOM转为真实DOM,随后呈现在页面中。

MyComponent的实例对象 <=> MyComponent组件实例对象。

类的相关知识复习

总结:
1.类中的构造器不是必须要写的,要对实例进行一些初始化的操作,如添加指定属性时才写。
2.如果A类继承了B类,且A类中写了构造器,那么A类构造器中的super是必须要调用的。
3.类中所定义的方法,都放在了类的原型对象上,供实例去使用。

组件实例的三大属性

1.state

状态驱动页面显示
严重注意:状态必须通过setState进行更新,且更新是一种合并,不是替换。

this.setState({isHot:!isHot})
//1.创建组件
		class Weather extends React.Component{
			
			//构造器调用几次? ———— 1次
			constructor(props){
				console.log('constructor');
				super(props)
				//初始化状态
				this.state = {isHot:false,wind:'微风'}
				//解决changeWeather中this指向问题
				this.changeWeather = this.changeWeather.bind(this)
			}

			//render调用几次? ———— 1+n次 1是初始化的那次 n是状态更新的次数
			render(){
				console.log('render');
				//读取状态
				const {isHot,wind} = this.state
				return <h1 onClick={this.changeWeather}>今天天气很{isHot ? '炎热' : '凉爽'}{wind}</h1>
			}

			//changeWeather调用几次? ———— 点几次调几次
			changeWeather(){
				//changeWeather放在哪里? ———— Weather的原型对象上,供实例使用
				//由于changeWeather是作为onClick的回调,所以不是通过实例调用的,是直接调用
				//类中的方法默认开启了局部的严格模式,所以changeWeather中的this为undefined
				
				console.log('changeWeather');
				//获取原来的isHot值
				const isHot = this.state.isHot
				//严重注意:状态必须通过setState进行更新,且更新是一种合并,不是替换。
				this.setState({isHot:!isHot})
				console.log(this);

				//严重注意:状态(state)不可直接更改,下面这行就是直接更改!!!
				//this.state.isHot = !isHot //这是错误的写法
			}
		}
		//2.渲染组件到页面
		ReactDOM.render(<Weather/>,document.getElementById('test'))

简单写法

//1.创建组件
		class Weather extends React.Component{
			//初始化状态
			state = {isHot:false,wind:'微风'}

			render(){
				const {isHot,wind} = this.state
				return <h1 onClick={this.changeWeather}>今天天气很{isHot ? '炎热' : '凉爽'}{wind}</h1>
			}

			//自定义方法————要用赋值语句的形式+箭头函数
			changeWeather = ()=>{
				const isHot = this.state.isHot
				this.setState({isHot:!isHot})
			}
		}
		//2.渲染组件到页面
		ReactDOM.render(<Weather/>,document.getElementById('test'))

2.props

构造器是否接收props,是否传递给super,取决于:是否希望在构造器中通过this访问props

3.refs

React.createRef调用后可以返回一个容器,该容器可以存储被ref所标识的节点,该容器是“专人专用”的

react生命周期

1 初始化阶段: 由ReactDOM.render()触发—初次渲染

  1. constructor()
  2. componentWillMount()
  3. render()
  4. componentDidMount() =====> 常用 一般在这个钩子中做一些初始化的事,例如:开启定时器、发送网络请求、订阅消息

2 更新阶段: 由组件内部this.setSate()或父组件render触发

  1. shouldComponentUpdate()
  2. componentWillUpdate()
  3. render() =====> 必须使用的一个
  4. componentDidUpdate()

3 卸载组件: 由ReactDOM.unmountComponentAtNode()触发

  1. componentWillUnmount() =====> 常用
    一般在这个钩子中做一些收尾的事,例如:关闭定时器、取消订阅消息

react脚手架

index.js
//引入react核心库
import React from 'react'
//引入ReactDOM
import ReactDOM from 'react-dom'
//引入App组件
import App from './App'

//渲染App到页面
ReactDOM.render(<App/>,document.getElementById('root'))

实践中的注意事项

  1. defaultChecked和checked的不同:defaultChecked只管第一次打开的时候的选择与否
  2. 自组件给父组件传数据,父给子传递一个函数,子在合适的时候调用函数(this.props)【子组件改变父组件】
  3. uuid 生成独一无二的id
  4. window.confirm()弹窗选择确认与否
  5. 数组的方法map遍历,返回每个值;filter过滤,条件不满足的被过滤掉;reduce条件统计求和
  6. defaultChecked、defaultValue 只在初始渲染时由状态控制,之后更新不再跟状态有关系,而checked、value在全过程中都受状态控制
  7. class需要被批量替换为className

todoList案例相关知识点

	1.拆分组件、实现静态组件,注意:className、style的写法
	2.动态初始化列表,如何确定将数据放在哪个组件的state中?
				——某个组件使用:放在其自身的state中
				——某些组件使用:放在他们共同的父组件state中(官方称此操作为:状态提升)
	3.关于父子之间通信:
			1.【父组件】给【子组件】传递数据:通过props传递
			2.【子组件】给【父组件】传递数据:通过props传递,要求父提前给子传递一个函数
	4.注意defaultChecked 和 checked的区别,类似的还有:defaultValue 和 value
	5.状态在哪里,操作状态的方法就在哪里

ajax请求

跨域问题:可以发出请求,返回不了数据
解决:
1.修改package.json文件,添加"proxy":"http://localhost:5000",在APP.js中直接申请当前端口3000
2.多个代理 写setupProxy.js文件

const { createProxyMiddleware } = require('http-proxy-middleware')
module.exports = function(app){
    app.use(
        createProxyMiddleware('/api1',{
            target:'http://localhost:5000',
            changeOrigin:true,
            pathRewrite:{'^/api1':''}
        }),
        createProxyMiddleware('/api2',{
            target:'http://localhost:5001',
            changeOrigin:true,
            pathRewrite:{'^/api2':''}
        })
    )
}

!一定要注意 不然无法打开localhost:3000

node里面使用的是CJS语法
连续结构赋值
const obj={a:{b:{c:1}}}
const {a:{b:{c}}}=obj 解构出c
const {a:{b:{c:data}}}=obj 解构出c并重命名为data

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值