React 组件
文章目录
React书写的一切用户界面都是基于组件的,将界面分割成一些独立的,可复用的部件.
一.声明组件
1.ES5写法:React.createClass()
最老版本的用法,不建议使用,已经废弃了
实际上,createClass() 本质是一个工厂函数
虽然这种方法已经废弃了,但是Facebook出了一个能代替React.createClass() 的替代品,需要使用create-react-class
模块,先安装
$ npm install create-react-class -S
import React from 'react';
var createReactClass = require('create-react-class');
var Greeting = createReactClass({
render: function () {
return <h1>使用create-react-class模块创建react组件</h1>;
}
});
export default Greeting;
2.ES6写法:React.Component
目前官方极为推荐的创建有状态组件的方式
支持
class语法 (状态 属性 生命周期)
[email protected] =>class生命周期写法升级
import React from 'react';
import ReactDOM from 'react-dom';
class Animal extends React.Component {
render() {
return (
<div>Animal组件</div>
)
}
}
ReactDOM.render(
<div>
<Animal></Animal>
</div>,
document.getElementById('root')
);
类定义的组件
- 定义一个类,类名就是组件名
- 这个类需要继承
React.Component
基础组件 - 类中的render函数是必须的,render函数中的return出来的是一段JSX语法,这一段JSX语法就是这个组件的模版的内容
3.函数式组件
无状态函数式写法
不支持状态 属性 生命周期
[email protected]
=> 支持状态 属性 “生命周期” React Hooks
import React from 'react';
import ReactDOM from 'react-dom';
const Cat = () => {
return (
<div>
Cat组件
</div>
);
}
ReactDOM.render(
<div>
<Cat></Cat>
</div>,
document.getElementById('root')
);
函数式的定义组件
- 定义一个函数,然后return出来一段JSX语法,这一段JSX语法就是这个组件的模版的内容
- 函数名称就是组件的名字,[所以首字母需要大写()
PS:组件模版内容,如果需要换行的话,return后面需要写小括号
()括起来,因为原生js,是会返回undefind
2.模版内容只能有一个跟元素
二.组件注意事项
1.组件名首字母大写
组件名,在被引用时 首字母必须大写 编译时会被认为是自定义组件,如果写成了小写,会被认为是原生js的dom节点
2.一个根元素
组件的最外层必须有一个标签包裹,不能有兄弟元素
3.return需要加上小括号
return加上小括号,可以回车,如果内容多了,肯定不会写成一行,原生中return后面没有跟内容,会返回undefind
4.组件是可以嵌套的
组件是可以嵌套的,如父子组件
三.状态(state)
每个React组件都有自己的状态(除了函数式组件外),state只存在于组件自身内部,用来存储自身的数据,相当于Vue中的data选项
1.定义state
在组件内部的构造器中,直接定义
this.state
constructor(props) {
super(props);
this.state = {
data: {
name: 'liuqiao',
age: 18
}
};
}
在ES7中可以直接省略构造器,直接在当前Class
中定义也可以,但是为了规范,建议还是不要省略
// 注意,这里是es7的写法
//不是状态,单纯只是变量
a=10;
//状态
state = {
name: 'liuqiao',
age: 18
}
2.访问state
同样,在需要使用当前状态的地方,通过
this.state
访问状态
render() {
return (
<div>
我的名字叫{this.state.data.name}
</div>
);
}
3.改变state
改变state时,使用React内置的
setState()
方法修改state,每当使用setState时,React会将需要更新的state合并后放入状态队列,触发调和过程,而不是立即更新state.所以,setState是异步的
this.setState({
username:'xiaohong'
});
在需要修改的地方触发此方法即可!另外,如果要修改setState
里面的对象的某一属性,但不会修改其他的属性呢?
this.state = {
username:'xiaoming',
data: {
name: 'liuqiao',
age: 18,
address:'深圳',
like:['爬山','跑步']
}
};
比如我要当前状态中的data对象中的name属性,但是其他属性不修改,我不可能,为了修改一个name属性,把其他的都在setState里都带上吧,那样肯定是不行的,所以我提供了如下方法:
1.方法一
let newData = { ...this.state.data };
newData.name=30;
this.setState({
data: newData
});
采用展开运算符,全部展开,然后只赋值需要修改的属性即可.其实原理呢,就是将原来的对象浅拷贝一个新对象,然后新对象改变属性之后,再浅拷贝回来
2.方法二
let newData = Object.assign(this.state.data, {
['age']: 30
});
this.setState({
data: newData
});
采用Object.assign方法功能,其原理就是此方法的特性可以合并具有相同属性的对象
3.方法三
let data=this.state.data;
data.age=30;
this.setState({
data
});
4.多个改变satae操作情况
culeCount = () => {
this.setState({
count: this.state.count + 1
});
this.setState({
count: this.state.count + 1
});
this.setState({
count: this.state.count + 10
});
// 这里多个setState操作,会被合并,只会执行最后一次的setState,进行了批量更新优化
}
如果遇到某个函数内进行了多个setSatae的情况,会被合并,整合上面的setState,如果有重复的,只会执行最后一次的setState,进行了批量更新优化
5.setState异步
setState()方法接收2个参数,后面参数可以选
this.setState({
myname: 'xiaoming'
}, () => {
//2.再打印
console.log("我是异步的" + this.state.myname);
//
});
//1.先打印
console.log(this.state.myname);
原理:状态更新是异步的,这里的回调函数,会等待状态更新完,并且dom更新完之后,才会被调用,原因是创建虚拟dom,diff算法对比旧的dom节点,和文档碎片,进行最小化重新渲染
6.setState同步
setState在ajax,原生事件,setTimeout是同步的
handleClick2 = () => {
setTimeout(() => {
this.setState({
myname: 'xiaohong'
});
console.log(this.state.myname);
this.setState({
myname: 'xiaofang'
});
console.log(this.state.myname);
}, 0);
}
官网的一句话:setState 并不保证是同步的!所以,得出结论:setState是否同步异步,是得看情况的,当setState在ajax,原生事件,setTimeout是同步的,其他情况是异步的
四.事件绑定
1.匿名箭头函数写法
比较简洁,适合处理代码少,简洁的逻辑
<button onClick={() => {
console.log(this.refs.username.value)
}}>提交(匿名箭头函数写法)</button>
2.自定义函数写法
会存在this指向问题,需要使用bind强制改变this指向 注意,必须使用bind才可以,call和 apply不行
原因是call和apply改变this指向后,会立即执行函数
<button onClick={this.submitLogin.bind(this)}>提交(自定义函数写法)</button>
submitLogin(e) {
//e是事件源
console.log('自定义函数写法',e);
}
3.自定义声明式箭头函数写法
一般推荐这种方式
<button onClick={this.submitOK}>提交(自定义声明式箭头函数写法)</button>
submitOK=()=>{
console.log('外部自定义函数', this.refs.username.value);
}
4.改编第一种写法,推崇这种
原理是使用箭头函数做中转,就不会有this指向问题了
<button onClick={(e)=>this.submitLogin('liuqiao','123')}>改编第一种 箭头函数做中转</button>
submitLogin(username,pwd,e) {
//e是事件源
console.log('外部自定义函数', username,pwd,e);
}