react是一个js库,与vue齐名。
vue重心在增强了html,react重心在增强的js。
react的语法更贴近js,所以需要学好js才能学好react。
在这里先开个头,之后去系统学习js。
npm i react react-dom
这个函数接受3个及以上参数,返回一个react元素.
- 第一个参数是要创建的标签名。
- 第二个参数是标签的属性。
- 第三个及以后的参数是元素的子节点。
这个函数接受一个DOM元素,将其转化为一个React元素并返回。
const title = React.createElement(
'h1',
{title : 'h1' , id : 'hello'},
"hello react!!!",
React.createElement('span' , null , '我是span')
);
const root = ReactDOM.createRoot(document.querySelector('#root'));
root.render(title);
通过指令来创建react项目,与vue不同,完全没有配置的余地,倒是也省事。
npx好慢呀,有没有cnpx呢??
npx create-react-app <name>
npx是npm下的一个包,高版本的node会直接内置。
npx可以在不安装脚手架的情况下使用脚手架。
jsx全称JavaScript XML,是react提出的js增强语法,也提出了jsx的文件类型,可以直接在js文件中书写jsx代码。
在脚手架中配置有babel,而babel中有jsx的处理程序,所以可以放心使用。
jsx可以更加清楚地描述页面的结构,看起来就像html代码一样。
react元素采用驼峰命名法。
react元素的一些属性名与html元素不同
- class -> className
- for -> htmlFor
- tabindex -> tabIndex
react元素如果没有子节点可以写成单标签
推荐使用小括号来包裹jsx的标签
不像vue中有各种各样的指令,react只有一种插值表达式。
与vue 的插值表达式基本相同,但是它是一对大括号而不是两对。
jsx的使用有一些注意点:
jsx的条件渲染有多种方式,但都是通过原生js
通过控制条件来返回不同的jsx块
const dogAreYou = () => {
if(flag){
return (<div>我是neko 的 狗</div>);
}
return (<div>拿来的野猫呀</div>)
};
const is = flag ? (<div>我是neko 的 狗</div>) : (<div>拿来的野猫呀</div>)
与运算符利用的是短路,与上面两种不太一样,他只能控制一个块是否渲染。
flag && return (<div>我是neko 的 狗</div>);
react要求使用map来遍历数组实现列表渲染。
const girls = [
{id: 1 , name: 'neko'},
{id: 2 , name: '蜜莓'},
{id: 3 , name: '砂糖'}
]
const list = (
<ul>
{girls.map(item => <li key={item.id}> {item.name} </li>)}
</ul>
)
在上面的代码中我给每个li都绑定了key值。
原因和注意点与vue中相同,与diff算法有关。
简单写一下,行内的样式要用大驼峰。
const list = (
<ul>
{girls.map(item => <li key={item.id} style={{
backgroundColor : 'pink',
listStyle : 'none'}}
>
{item.name}
</li>)}
</ul>
)
这么写挺乱的,可以把样式单独提出来。
const listStyle = {backgroundColor : 'pink' , listStyle : 'none'};
const list = (
<ul>
{girls.map(item => <li key={item.id} style={listStyle}> {item.name} </li>)}
</ul>
)
通过为元素绑定类名,然后引入单独的css文件。
虽然说推荐这种写法,但目前我更喜欢上面这种,一个文件能解决的问题为什么要再加一个独立的文件,管理起来不麻烦吗????
开头就说了,组件是react最重要的部分。
跟vue的组件思想一样,但vue开创了单独的vue文件,react则是通过函数和类,实现了组件。
函数组件就是用函数的方式来写。
Click = function () {
function say() {
alert("点到了")
}
return (<button onClick={say}>点我</button>)
}
函数组件的约定:(必须遵守)
通过js的类来实现组件
写法如下:
class Click extends React.Component{
say(){
alert("点到了");
}
render() {
return (<button onClick={this.say}>点我</button>)
}
}
类组件的约定:
讲组件单独抽离到一个文件中可以实现复用。
按照下面的步骤定义组件文件。
- 引入react
- 定义组件
- 导出组件
与原生js 的事件绑定方法相同。
只不过事件名都前缀on并且改为大驼峰命名法。
(<button onClick={say}>点我</button>)
与原生的js相同,在事件函数定义是接受的参数就是事件对象。
不同的是react做了处理,变为合成事件对象,不用再考虑浏览器的兼容问题。
状态就是组件的数据,跟vue中的data一样。
只有类组件有状态,因此叫做状态组件,函数组件又被称为无状态组件。
所有函数组件和类组件的作用有所不同,函数组件定义死的页面,类组件用来定义需要更新的组件。
react中的state 就是 vue中的data。
初始化state要依靠类中的constructor构造器函数。
constructor() {
super();
this.state = {
number: 1
}
}
也可以使用简写,将state抽出来,不影响构造器函数使用
tate = {
number: 10
}
// constructor 不写也没问题
constructor() {
super();
}
要获取state中的值使用this.state 的方式
<h1>当前数字:{this.state.number}</h1>
要修改state中的值,使用setState函数,不能直接修改(突然觉得vue好方便)。
this.setState({
number: this.state.number + 1
//setState接受一个对象,然后将他和原来的state合并。
})
setState的分离进单独的函数之后会出现this的指向问题,有三种解决方案。
<button onClick={() => (this.add)}>+1</button>
constructor() {
super();
this.add = this.add.bind(this);
}
add = () => {
// console.log('事件处理程序中的this',this);
this.setState({
number: this.state.number + 1
})}
将表单中的value值和state中的数据绑定,
表单值受到react控制的表单组件称为受控组件。
要做到双向数据绑定,没有像vue中那样的指令,需要自己手写。
state = {
txt: '',
}
<input type="text" value="this.state.txt" onChange={
(e) => this.setState({txt: e.target.value})}>
state = {
girl: '蜜莓',
}
<section value={this.state.city} onChange={(e) => {
this.setState({girl : e.target.value})
}}>
<option value='mm'>蜜莓</option>
<option value='st'>砂糖</option>
<option value='neko'>neko</option>
</section>
state = {
is: flase,
}
<input type="checkbox" checked="this.state.is" onChange={
(e) => this.setState({is: e.target.checked})}>
state = {
txt: '',
}
<input
type="text"
name='txt'
value="this.state.txt"
onChange={
(e) => {
const value = e.target.type === 'checkbox'
? e.target.checked
: e.target.value;
const name = e.target.name;
this.setState({[name]: value});
}}>
不推荐这种方式,react不希望我们来操作DOM。
constructor(){
super();
this.Ref = React.createRef();
}
<input type='text' ref={this.Ref}>
this.Ref.current.value