react学习

文章目录

  • 搭建react环境
    • 插件Simple React Snippets
    • 目录介绍
  • 组件引入
    • 1.在index.js文件引入
    • 2.编写App.js组件
  • JSX
    • 1.语法
    • 2.引入css文件用classname
    • 3.label标签
  • 一个例子
    • 1.写一个组件Xiaojiejie.js
      • 1.在constructor里定义data
      • 2.事件绑定
    • 2.在index.js引入并且使用
  • 组件拆分
  • 传值
    • 不同组件的通信
      • 父子组件传值
        • 父组件传值给子组件依靠属性传递
    • PropType对接收传递值的类型进行规定
  • ref的使用
    • 使用
  • 生命周期
    • Mounting阶段
    • `Updation`阶段
    • **unmount阶段**
  • 一个例子
  • 理论:单项数据流

最近跟着教程,简单了解了一下react

搭建react环境

1.安装node,npm

npx create-react-app my-app
cd my-app
npm start

插件Simple React Snippets

快捷 imrc , cc

目录介绍

public:是放公共文件的

  • mainifest.json:移动端配置文件,这个会在以后的课程中详细讲解。

src放自己编写的文件

  • index.js: 入口文件。

  • serviceWorker.js: 这个是用于写移动端开发的,PWA必须用到这个文件,有了这个文件,就相当于有了离线浏览的功能。


组件引入

1.在index.js文件引入

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'))

2.编写App.js组件

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

JSX就是Javascript和XML结合的一种格式。

上述app.js组件里 render() return的就是jsx

可以理解为js和html混用

1.语法

当遇到<,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') );

2.引入css文件用classname

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}}

3.label标签

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>

一个例子

1.写一个组件Xiaojiejie.js

1.在constructor里定义data

2.事件绑定

注意: 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'

2.在index.js引入并且使用

组件拆分

我们想将上述例子的每一项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;

PropType对接收传递值的类型进行规定

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的使用

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)
    } 

生命周期

  1. Initialization:初始化阶段。
  2. Mounting: 挂在阶段。
  3. Updation: 更新阶段。
  4. Unmounting: 销毁阶段

Mounting阶段

Mounting阶段叫挂载阶段,伴随着整个虚拟DOM的生成,它里边有三个小的生命周期函数,分别是:

  1. componentWillMount : 在组件即将被挂载到页面的时刻执行。

  2. render : 页面state或props发生变化时执行。

  3. componentDidMount : 组件挂载完成时被执行。

    在这个周期请求数据

componentWillMount(){
    console.log('componentWillMount----组件将要挂载到页面的时刻')
}
componentDidMount(){
    console.log('componentDidMount----组件挂载完成的时刻执行')
}
render(){
    console.log('render---组件挂载中.......')
}

componentWillMountcomponentDidMount这两个生命周期函数,只在页面刷新时执行一次,而render函数是只要有state和props变化就会执行

Updation阶段

Updation阶段,也就是组件发生改变的更新阶段,这是React生命周期中比较复杂的一部分,它有两个基本部分组成,一个是props属性改变,一个是state状态改变。

1.shouldComponentUpdate函数

shouldComponentUpdate函数会在组件更新之前,自动被执行。要求返回一个布尔类型的结果,必须有返回值。返回值true/false。就是返回true,就同意组件更新;返回false,就反对组件更新。

shouldComponentUpdate(){
    console.log('shouldComponentUpdate---组件发生改变前执行')
    return true
}

解决子组件频繁无用渲染render 的性能问题

shouldComponentUpdate有两个参数:

  • nextProps:变化后的属性;
  • nextState:变化后的状态;

在子组件中加入

shouldComponentUpdate (nextProps, nextState) {
     
        if (nextProps.content !== this.props.content) {
     
            return true
        } else {
     
            return false
        }
    }

2.componentWillUpdate函数

componentWillUpdateshouldComponenUpdate之后被执行,组件更新之前执行。

//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函数重新被执行,这个生命周期就会被执行。

unmount阶段

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;
}

理论:单项数据流

子组件不能直接操作父组件的数据,只能通过父组件的方法进行修改

可以理解父组件将值传递给子组件时,子组件不能直接修改,所有数据是单向的

你可能感兴趣的:(react)