最近跟着教程,简单了解了一下react
1.安装node,npm
npx create-react-app my-app
cd my-app
npm start
快捷 imrc , cc
public:是放公共文件的
src放自己编写的文件
index.js: 入口文件。
serviceWorker.js: 这个是用于写移动端开发的,PWA必须用到这个文件,有了这个文件,就相当于有了离线浏览的功能。
React,ReactDOM是必要的
App就是我们传说中的react组件了(组件化开发)
调用ReactDOM.render()方法把你的组件挂载到dom节点上
ReactDOM.render(组件,dom节点)
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
ReactDOM.render(<App />,document.getElementById('root'))
react的组件是写成类的样子
类里有个render()方法写html结构
在示例中这种类似 XML 的写法被称为 JSX。
import React, { Component } from 'react'
//相当于 import React from 'react'
//const Component = React.Component 解构赋值
class App extends Component {
render () {
return (
Hello React!
)
}
}
export default App;
npm start 就可以看到页面了
JSX就是Javascript和XML结合的一种格式。
上述app.js组件里 render() return的就是jsx
可以理解为js和html混用
当遇到<
,JSX就当作HTML解析,遇到{
就当JavaScript解析.
ReactDOM.render(
<div>
<h1>{
i == 1 ? 'True!' : 'False'}</h1>
</div>
,
document.getElementById('example')
);
jsx不能使用if else,但可以使用三目运算符
jsx推荐使用内联样式,在指定元素数字后自动添加px
注释写在{/* 注释 */}中 ,vscode快捷键ctrl+/
var myStyle = {
fontSize: 100,
color: '#FF0000'
};
ReactDOM.render(
菜鸟教程
{/* 注释 */}
,
document.getElementById('example')
);
JSX 允许在模板中插入数组,数组会自动展开所有成员:
var arr = [
菜鸟教程
,
学的不仅是技术,更是梦想!
,
];
ReactDOM.render(
{arr},
document.getElementById('example')
);
a.在组件里引入css文件
import '地址'
b.使用时class替换成className
3.将字符串以html进行解析
class Xiaojiejie extends Component{
constructor(props){
super(props)
this.state = {
content:'标题'
}
}
render(){
return(
)
}
}
export default Xiaojiejie
在显示时,将内容写入__html对象中
第一{}代表jsx语法开始,第二个是代表dangerouslySetInnerHTML接收的是一个对象键值对
dangerouslySetInnerHTML={
{__html:this.state.content}}
label标签的for 和 input 的id 一般共同使用,是对应关系
但是在jsx里for要用htmlFor代替
<div>
<label htmlFor="jspang">加入服务:</label>
<input id="jspang" value={
this.state.inputValue} onChange={
this.inputChange.bind(this)} />
</div>
注意: a.需要用bind改变this指向 b.在react里用this.setState(变量:改变值)改变变量
react里面禁止直接操作state!!
import React,{
Component} from 'react'
class Xiaojiejie extends Component{
constructor(props){
super(props)
this.state = {
inputValue: '',
list:['111','222']
}
}
render(){
return(
<div>
<div><input value = {
this.state.inputValue} onChange={
this.inputChange.bind(this)} /><button onClick={
this.addList.bind(this)}>增加服务</button></div>
<ul>
{
this.state.list.map((item,index)=>{
return (
<li key={
item+index}
onClick = {
this.deleteItem.bind(this,index)}
>{
item}</li>
)
})
}
</ul>
</div>
)
}
inputChange(e){
//如果不绑定this,this是undefined,绑定后指向的是这个类的s(?)
this.setState({
inputValue:e.target.value
})
}
addList(){
this.setState({
list:[...this.state.list,this.state.inputValue]
})
}
deleteItem(index){
let list = this.state.list
list.splice(index,1)
this.setState({
list:list
})
//不要直接修改state的数据,后续性能优化会有问题
//this.state.list.splice(index,1)
}
}
export default Xiaojiejie
我们需要最外用一个div进行包裹
如果不想用div可以用Fragment代替
但是要引入
import React,{
Compnent,Fragment} from 'react'
我们想将上述例子的每一项li作为组件拆出来
新建组件xiaojiejieitem.js
import React, {
Component } from 'react';
class XiaojiejieItem extends Component {
state = {
}
render() {
return ( <div>选项1</div> );
}
}
export default XiaojiejieItem;
在Xiaojiejie的组件里导入并使用
class Xiaojiejie extends Component{
...
render(){
return(
<div>
<div><input value = {
this.state.inputValue} onChange={
this.inputChange.bind(this)} /><button onClick={
this.addList.bind(this)}>增加服务</button></div>
<ul>
{
this.state.list.map((item,index)=>{
return (
<div>
<XiaojiejieItem key={
index+item}></XiaojiejieItem>
</div>
)
})
}
</ul>
<div dangerouslySetInnerHTML={
{
__html:this.state.content}}></div>
</div>
)
}
}
Xiaojiejie.js
<XiaojiejieItem content={
item}></XiaojiejieItem>
XiaojiejieItem.js
import React, {
Component } from 'react'; //imrc
class XiaojiejieItem extends Component {
//cc
render() {
return (
<div>{
this.props.content}</div>
);
}
}
export default XiaojiejieItem;
子组件不能直接操作父组件的数据,只能通过父组件的方法进行修改
想实现点击选项删除该选项
父组件需要传递 1.index 2.删除的方法(传递的方法也要绑this)
Xiaojiejie.js
<XiaojiejieItem
key={
index+item}
content={
item}
index={
index}
deleteItem={
this.deleteItem.bind(this)} />
子组件新写一个方法调用传递的方法进行响应
import React, {
Component } from 'react';
class XiaojiejieItem extends Component {
constructor(props){
super(props)
//在constructor里绑定性能更好
this.handleClick = this.handleClick.bind(this)
}
render() {
return (
<div onClick={
this.handleClick}>{
this.props.content}</div> );
}
handleClick(){
this.props.deleteItem(this.props.index)
}
}
export default XiaojiejieItem;
XiaojiejieItem.js
1.导入 2.使用
import PropTypes from 'prop-types'
class XiaojiejieItem extends Component{
..}
XiaojiejieItem.propTypes = {
content: PropTypes.string,
index: PropTypes.number,
deleteItem: PropTypes.func
}
...
这样如果传值类型不对就会报错
isRequired
关键字了,它表示必须进行传递,如果不传递就报错。
content: PropTypes.string.isRequired
defalutProps
就可以实现默认值的功能
XiaojiejieItem.defaultProps = {
content:'1111'
}
ref是用来绑定dom的
如下用ref绑定了input,在方法里用this.input 调用
{this.input=input}}
//关键代码------------end
/>
inputChange(){
this.setState({
inputValue:this.input.value
})
}
首先要知道this.setState()这个函数是异步的,在这个函数和后面使用ref操作dom,就会this.setState()还没执行完,后面的操作就执行了
但是this.setState()的第二个函数是一个回调函数,我们可以把ref的操作放在这里
例子: 用ref绑定了ul, addList方法中使用
<ul ref={
(ul)=>{
this.ul = ul}}>
{
this.state.list.map((item,index)=>{
return (
<XiaojiejieItem
key={
index+item}
content={
item}
index={
index}
deleteItem={
this.deleteItem.bind(this)} />
)
})
}
</ul>
addList(){
this.setState({
list:[...this.state.list,this.state.inputValue],
inputValue: '',
},()=>{
console.log('对的'+ this.ul.querySelectorAll('div').length)
})
console.log('错的'+ this.ul.querySelectorAll('div').length)
}
Initialization
:初始化阶段。Mounting
: 挂在阶段。Updation
: 更新阶段。Unmounting
: 销毁阶段Mounting阶段叫挂载阶段,伴随着整个虚拟DOM的生成,它里边有三个小的生命周期函数,分别是:
componentWillMount
: 在组件即将被挂载到页面的时刻执行。
render
: 页面state或props发生变化时执行。
componentDidMount
: 组件挂载完成时被执行。
在这个周期请求数据
componentWillMount(){
console.log('componentWillMount----组件将要挂载到页面的时刻')
}
componentDidMount(){
console.log('componentDidMount----组件挂载完成的时刻执行')
}
render(){
console.log('render---组件挂载中.......')
}
componentWillMount
和componentDidMount
这两个生命周期函数,只在页面刷新时执行一次,而render
函数是只要有state和props变化就会执行
Updation
阶段Updation
阶段,也就是组件发生改变的更新阶段,这是React生命周期中比较复杂的一部分,它有两个基本部分组成,一个是props
属性改变,一个是state
状态改变。
1.shouldComponentUpdate函数
shouldComponentUpdate
函数会在组件更新之前,自动被执行。要求返回一个布尔类型的结果,必须有返回值。返回值true/false。就是返回true,就同意组件更新;返回false,就反对组件更新。
shouldComponentUpdate(){
console.log('shouldComponentUpdate---组件发生改变前执行')
return true
}
解决子组件频繁无用渲染render
的性能问题
shouldComponentUpdate有两个参数:
在子组件中加入
shouldComponentUpdate (nextProps, nextState) {
if (nextProps.content !== this.props.content) {
return true
} else {
return false
}
}
2.componentWillUpdate函数
componentWillUpdate
在shouldComponenUpdate
之后被执行,组件更新之前执行。
//shouldComponentUpdate返回true才会被执行。
componentWillUpdate(){
console.log('componentWillUpdate---组件更新前,shouldComponentUpdate函数之后执行')
}
3.componentDidUpdate
componentDidUpdate
在组件更新之后执行,它是组件更新的最后一个环节。
componentDidUpdate(){
console.log('componentDidUpdate----组件更新之后执行')
}
几个函数的执行顺序
1-shouldComponentUpdate---组件发生改变前执行
2-componentWillUpdate---组件更新前,shouldComponentUpdate函数之后执行
3-render----开始挂载渲染
4-componentDidUpdate----组件更新之后执行
4.compoenentWillReceiveProps
子组件接收到父组件传递过来的参数,父组件render函数重新被执行,这个生命周期就会被执行。
componentWillUnmount函数
组件从页面中删除的时候执行
用react做一个css的动画
主要是再熟悉一下react吧。。
点击按钮实现元素的出现和隐藏
import React, { Component } from 'react';
class Sunwukong extends Component {
render () {
return (
孙悟空
);
}
constructor(props) {
super(props)
this.state = {
isShow: true
}
this.toToggle = this.toToggle.bind(this)
}
toToggle () {
this.setState({
isShow: this.state.isShow ? false : true
})
}
}
export default Sunwukong;
在主组件引入的css文件写
.show{
opacity: 1 ;
transition: all 1.5s ease-in;
}
.hide{
opacity: 0 ;
transition: all 1.5s ease-in;
}
子组件不能直接操作父组件的数据,只能通过父组件的方法进行修改
可以理解父组件将值传递给子组件时,子组件不能直接修改,所有数据是单向的