写这篇文章的目的是好好沉淀一下自己所学的东西。
React基础
Hello World
在这里默认已经有React开发环境,就直接开始了。
下面这是一段最简单的react代码,效果是在页面上渲染出Hello,World!
ReactDOM.render(
<h1>Hello, world!</h1>,
document.getElementById('root')
);
这段代码是将h1 标签及内容渲染到页面上,在HTML文件中需要有一个id 为root 的节点用于渲染React元素。
通常情况下使用 React 构建的应用只有单一的根 DOM 节点。
想要将一个 React 元素渲染到根 DOM 节点中,只需把它们一起传入 ReactDOM.render() 。
可以理解为,将你要渲染的东西交给React,然后它会帮你把那些东西放在你在页面指定的位置;
像这段代码还能写成下面这样:
const element = <h1>Hello, world</h1>;
ReactDOM.render(element, document.getElementById('root'));
这里的第一行是JSX语法,一种JavaScript的拓展语法,能够将HTML元素写在JS中,与React通常搭配使用,在下一节中将会对JSX进行一个介绍。
JSX
JSX 是 JavaScript 的语法扩展,JSX 使得我们可以以类似于 HTML 的形式去使用 JS。简单来说就是使用JSX将我们所期望的网页结构编写出来,然后React再根据JSX自动生成JS代码。
像上面那段代码能像这样写:
const name = 'World'
const element = <h1>Hello, {name}</h1>;
ReactDOM.render(element, document.getElementById('root'));
在编译之后,JSX 表达式会被转为普通 JavaScript 函数调用,并且对其取值后得到 JavaScript 对象。
也就是说,你可以在 if 语句和 for 循环的代码块中使用 JSX,将 JSX 赋值给变量,把 JSX 当作参数传入,以及从函数中返回 JSX;但是不能在JSX中书写if 语句和 for 循环.
可以使用{}插入js表达式,就像上面的{name} ,这就是读取name的值并一同赋值给element。
组件
React中组件分为函数组件和class组件, 组件名称必须以大写字母开头
类式组件和函数式组件
这是一个类式组件:
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
类式组件是一个继承于React.Component 的一个类;默认接收带有数据的 “props”,props具有只读属性,不可进行修改。
这是一个函数式组件:
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
上述两个组件在 React 里是等效的。
本文皆使用函数式组件加Hooks;
渲染组件
之前我们遇到的 React 元素都只是 DOM 标签:
const element = <div />;
但是React 元素也可以是用户自定义的组件:
const element = <Welcome name="Sara" />;
当 React 元素为用户自定义组件时,它会将 JSX 所接收的属性(attributes)以及子组件(children)转换为单个对象传递给组件,这个对象被称之为 “props”。
例如,这段代码会在页面上渲染 “Hello, Sara”:
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
const element = <Welcome name="Sara" />;
ReactDOM.render(
element,
document.getElementById('root')
);
在这个例子中
- 我们调用
ReactDOM.render() 函数,并传入 <Welcome name="Sara" /> 作为参数。 - React 调用
Welcome 组件,并将 {name: 'Sara'} 作为 props 传入。 Welcome 组件将 <h1>Hello, Sara</h1> 元素作为返回值。- React DOM 将 DOM 高效地更新为
<h1>Hello, Sara</h1> 。
条件渲染
上文有说在JSX中是不能使用if…else…语句的,那我们该如何使用分支结构呢。
现要求根据isLoading的值判断是否加载Loading动画。
通常在React使用如下方法:
let isLoading = ture;
isLoading&&<div>Loading...</div>
isLoading? <div>Loading...</div> : <div>Hello</div>
列表的渲染
有这样一组数据要渲染在页面中:
students = ['张三','李四','王五']
在React中,通常使用数组的map方法进行列表渲染,即:
<ul>
{students.map(item=>{
return <li>item</li>
})}
</ul>
const items = students.map(item=><li>item</li>)
<ul>
{items}
</ul>
但是像这样写的话,打开控制台时你一定会看到一行红色的内容,它大概内容是:Warning: Each child in a list should have a unique “key” prop.
意思是列表中的每一个元素都需要有一个属性 key 并且它的值是唯一的,因为在React在使用diffing算法进行虚拟DOM对比的时候需要根据key的索引,若是没有key的话可能会出现某些不该出现的错误。
创建React项目
一般使用Create-React-App进行项目的初始化创建,这方面可以查阅其他资料;
Props
上文已经提到过了Props,这里再稍微讲一下;
Props用于父子组件间的通信,由父组件通过属性的方式将值传给子组件
在组件内部可以通过props.xxx来访问外部传递进的属性,从而达到动态设置的目的。需要注意的是,标签体也可以设置为props的一个属性,叫做children,可以通过props.children来获取标签体的内容。
还有一点一定要记住,props中的属性是只读属性是无法修改的!
State
State可以被认为是一个变量,但是它的定义方式不太一样,我们以函数组件为例来介绍state的使用方式
在使用state之前能够调用ReactDOM.render() 对元素进行渲染。而State作为组件的状态,能够在状态修改时自动重新渲染组件,从而完成界面的更新。
下面是一个计数器的例子,这里用的时Hooks写法
import {useState} from 'react'
function Count(){
const [count,setCount] = useState(0);
return(
<div>
<h1>{count}</h1>
<button onClick={()=>{setCount(count+1)}}>点我加1</button>
</div>
)
}
当每次点击按钮时,count会自动加1,同时React检测到State发生改变,于是重新渲染组件;这时点击按钮在页面上就能看见数字递增;
事件处理
React 元素的事件处理和 DOM 元素的很相似,但是有一点语法上的不同:
- React 事件的命名采用小驼峰式(camelCase),而不是纯小写。
- 使用 JSX 语法时你需要传入一个函数作为事件处理函数,而不是一个字符串。
例如,传统的 HTML:
<button onclick="add()">
点我加1
</button>
在 React 中略微不同:
<button onClick={add}>
点我加1
</button>
上面的计数器例子也能像这样写:
import {useState} from 'react'
function Count(){
const [count,setCount] = useState(0);
const add = ()=>{
setCount(count+1)
}
return(
<div>
<h1>{count}</h1>
<button onClick={add}}>点我加1</button>
</div>
)
}
需要注意的是,在事件中传的是一个函数,而不是一个函数的调用。
要是传的是函数的调用的话,那么在JSX解析过程中就会执行该函数,从而出现奇怪的bug。
事件对象
React事件也会产生事件对象,在事件的响应函数中可以定义第一个参数来获取事件对象:
const clickHandler = (e)=> {
console.log(e);
alert('你点我干嘛');
};
这个事件对象是由React所创建的事件对象,和原生的事件对象类似,但使用它我们不需要担心兼容的问题。使用事件对象可以完成像原生DOM中事件对象的各种操作,比如取消默认行为和取消事件的冒泡:
const clickHandler = (e)=> {
e.preventDefault();
e.stopPropagation();
};
= (e)=> {
console.log(e);
alert('你点我干嘛');
};
这个事件对象是由React所创建的事件对象,和原生的事件对象类似,但使用它我们不需要担心兼容的问题。使用事件对象可以完成像原生DOM中事件对象的各种操作,比如取消默认行为和取消事件的冒泡:
const clickHandler = (e)=> {
e.preventDefault();
e.stopPropagation();
};
|