chapter1-React基本语法

# chapter1-React基本语法

  • 今日学习目标
  • 一、React简介
  • 二、React特点
  • 三、创建React脚手架项目
  • 四、hello_world程序编写
  • 五、VSCode中JSX的编写优化
  • 六、ES5与ES6面向对象复习
    • 1、ES5封装与继承
    • 2、ES6封装与继承
  • 七、组件化开发
  • 八、JSX语法糖
  • 九、VSCode中,代码片段扩展的安装
  • 十、事件、state与setState
  • 十一、state的简写
  • 十二、setState是异步的
  • 十三、累加
  • 十四、双向数据绑定
  • 十五、state中数组的修改
  • 十六、【验证】为什么修改state只能通过setState
  • 十七、【验证】key用id好还是index好?
  • 十八、案例:Tab栏
  • 十九、作业

# 今日学习目标

  • 了解React的MVC设计理念
  • 能够使用脚手架创建React项目
  • 掌握JSX语法
  • 掌握组件化开发

# 一、React简介

React 是一个用于构建用户界面的 JavaScript 库,它是 Facebook 的内部项目,用来架设 Instagram 的网站,并于 2013 年 5 月开源。React 主要用于构建UI,很多人认为 React 是 MVC 中的 V(视图)。由于拥有较高的性能,且代码逻辑非常简单,越来越多的人已开始关注和使用它。

中文官网:https://react.docschina.org

# 二、React特点

1、声明式设计

​react是面向数据编程,不需要直接去控制dom,你只要把数据操作好,react自己会去帮你操作dom,可以节省很多操作dom的代码。这就是声明式开发。

2、使用JSX语法

​ JSX 是 JavaScript 语法的扩展。React 开发大部分使用 JSX 语法(在JSX中可以将HTML于JS混写)。

3、灵活

​react所控制的dom就是id为root的dom,页面上的其他dom元素你页可以使用jq等其他框架 。可以和其他库并存。

4、使用虚拟DOM、高效

​虚拟DOM其实质是一个JavaScript对象,当数据和状态发生了变化,都会被自动高效的同步到虚拟DOM中,最后再将仅变化的部分同步到DOM中(不需要整个DOM树重新渲染)。

5、组件化开发

​通过 React 构建组件,使得代码更加容易得到复用和维护,能够很好的应用在大项目的开发中。

6、单向数据流

​react是单向数据流,父组件传递给子组件的数据,子组件能够使用,但是不能直接通过this.props修改。 这样让数据清晰代码容易维护。

# 三、创建React脚手架项目

# 1、构建一个名为 demo 项目

# React不再支持全局安装create-react-app,因此官方建议使用npx来安装
npx create-react-app demo
1
2

注意:项目路径不能有中文,不能有怪异符号,包括“!”也不行!!!!

如图,创建成功:

如果安装过于缓慢,或者有报错,请参考下文:

https://www.jianshu.com/p/91bf816cc1cc

# 2、进入这个文件夹,并且跑起来

cd demo && yarn start
1

项目运行,自动打开谷歌浏览器看见项目页面(第一次项目运行会很慢,要耐心等待)

# 四、hello_world程序编写

1、删除在src目录下所有文件

2、src目录下新建index.js文件作为入口文件

//1、引入React两个核心模块
import React from 'react';
import ReactDOM from 'react-dom';

//2、通过JSX语法将组件/标签渲染到指定标签上
ReactDOM.render(
    <h1>
        hello world!
    </h1>
    , document.getElementById('root'));
1
2
3
4
5
6
7
8
9
10
11

ReactDOM.render(参数1,参数2)

参数1 是JSX语法的标签/组件

参数2 是要把参数1这个标签渲染到的位置

# 五、VSCode中JSX的编写优化

在vscode中的 文件>首选项>设置 中,直接搜索 include Language ,进入 settings.json

找到 "emmet.includeLanguages" 字段,添加:

"emmet.includeLanguages": {
  "javascript": "javascriptreact"
}
1
2
3

搜索 trigger ,找到如图位置,打钩:

设置后就可以通过 标签名+Tab 键快速码出标签

# 六、ES5与ES6面向对象复习

# 1、ES5封装与继承

我们声明一个构造函数:

function Animal(vname){
    this.name = vname;
    this.sayInfo = function(){
        console.log('这是一只'+this.name)
    }
}

var animal = new Animal('动物')
animal.sayInfo();// 这是一只动物
1
2
3
4
5
6
7
8
9

现在我想用一个Dog类来继承这个Animal类,那么就可以:

function Animal(vname){
    this.name = vname;
    this.sayInfo = function(){
        console.log('这是一只'+this.name)
    }
}

function Dog(vname){
  // 在子类型构造函数的内部调用超类型构造函数,通过使用apply()和call()方法可以在新创建的对象上执行构造函数
  Animal.call(this, vname);
}

var dog = new Dog('狗狗');
dog.sayInfo();// 这是一只狗狗
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 2、ES6封装与继承

我们声明一个类:

class Animal {
    // 构造器
    constructor(vname){
        this.name = vname;
    }
    sayInfo(){
        console.log('这是一只'+this.name);
    }
}

let animal = new Animal('动物');
animal.sayInfo();
1
2
3
4
5
6
7
8
9
10
11
12

再定义一个Dog类来继承Animal类:

class Animal {
    // 构造器
    constructor(vname){
        this.name = vname;
    }
    sayInfo(){
        console.log('这是一只'+this.name);
    }
}

class Dog extends Animal {
    constructor(props){
        // 超类,接收父类传递过来的属性
        super(props)
    }
}

let dog = new Dog('狗狗');
dog.sayInfo()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 七、组件化开发

在React的项目中,都是使用组件化开发的模式,所以,我们可以把刚才的hello world的h1定义为一个组件:

定义组件分为3步:

​1、导入React核心模块

​2、定义组件类

​3、导出组件

在src目录下新建App.js文件:

//1、导入React核心模块
import React from 'react'

//2、定义组件类
class Hello extends React.Component{   //类
    render(){     //函数
        return (   //返回值
            <div>
                hello world !!! 我是组件222
            </div>
        )
    }
}

//3、导出组件
export default Hello
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

在需要引入该组件的index.js中,导入,就可以直接使用这个组件了:

//import 组件名 from '文件路径'
import Hello from './App'   //1、导入Hello组件  (首字母必须大写)

ReactDOM.render(
    <Hello />        // 2、使用Hello组件  (首字母必须大写)
    , document.getElementById('root'));

//注意:Hello是组件名,在使用的时候就应该写JSX标签写法,而不能直接写Hello
1
2
3
4
5
6
7
8

!!注意:

1、定义组件的时候,return 后面只能有一个根标签,不能有多个,但这个标签内部可以有其他多个标签

2、使用组件的时候,首字母必须大写

3、如果最外层实在不想放置一层div根目录,可以使用 <></> 空标签代替

# 八、JSX语法糖

React 使用 JSX 来替代常规的 JavaScript。JSX 是一个看起来很像 XML 的 JavaScript 语法扩展,在React中会被babel编译为JavaScript。

# 1、JSX的特点

  • JSX 执行更快,因为它在编译为 JavaScript 代码后进行了优化。
  • 它是类型安全的,在编译过程中就能发现错误。
  • 使用 JSX 编写模板更加简单快速。

# 2、JSX几个注意的格式:

1、React的JSX是使用大写和小写字母来区分本地组件和HTML组件

(如:html就用 div p h1 , 组件就用 MyButton App Home List等 )

2、JSX和html的标签属性的区别

HTML标签属性 JSX 原因
for htmlFor for在JS中为for循环关键字
class className class在JS中为声明类关键字
style 需使用JS对象(使用双花括号--{{}})

组件中:

import React, { Component } from 'react'
var MyImg = require('./assets/01.jpg')

export default class App2 extends Component {
    render() {
        return (
            <>
                <label htmlFor="ipt">label</label>
                <input type="text" id="ipt" className="ipt" style={{background: 'pink', color: 'green'}} />
                <hr/>
                <img src={MyImg} alt=""/>
            </>
        )
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

注意:图片查找路径在src目录,所以引入的时候从src目录触发查找文件

# 3、React的JSX创建出来的是虚拟DOM,而不是HTML

在index.js中:

import React from 'react'
import ReactDOM from 'react-dom'
import App from './App3'

ReactDOM.render(
    <App />,
    document.getElementById('root')
);

const virtualDOM = React.createElement('div')
const realDOM = document.createElement('div')

let virtualNum = 0;
for(var key in virtualDOM){
    virtualNum++;
}

let realNum = 0;
for(var key in realDOM){
    realNum++;
}

console.log('虚拟DOM的属性个数:'+virtualNum)// 7
console.log('真实DOM的属性个数:'+realNum)// 298
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

# 4、JSX变量引用、三目运算符、for循环

在JSX中,想要调用变量,需要在return中直接使用单花括号--**{}**调用

index.js中:

//第四节:JSX中变量引用、三目运算符、for循环的使用
import App3 from './App3'

//2、通过JSX语法将标签/组件渲染到指定标签上
ReactDOM.render(
    <App3 />
    , document.getElementById('root'));
1
2
3
4
5
6
7

App3.js中

import React, { Component } from 'react'

let name = "小明", num1=20, num2=30, arr=[1, 2, 3, 4, 5]

export default class App3 extends Component {
  render() {
    return (
      <div>
        {/* 这是注释的格式 */}
        {/* JSX中引用变量需要加单花括号 */}
        <p>{name}</p>

        {/* 三目运算符的使用 */}
        <p>num1和num2中比较大的是:{num1>num2? num1: num2}</p>
        <p>{gender === 0 ? '男' : (gender === 1 ? '女' : '保密')}</p>

        {/* for循环的使用 */}
        <ul>
          {/* 数组名.map(函数) */}
          {
            //格式1:
            arr.map((v,k)=>(
              <li key={k}>{v}</li>
            ))
          }
          {
            //格式2:可以把下面的大括号和return换成小括号
            arr.map((v,k)=>{
              return <li key={k}>{v}</li>
            })
          }
        </ul>

      </div>
    )
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

总结:在jsx语法中,需要书写js代码的时候,请先加上{ } 再书写js语法

# 九、VSCode中,代码片段扩展的安装

在扩展搜索栏中搜索react,选择下图的扩展进行安装

安装后,通过 rcc+Tab ,得到组件的代码片段, clg+回车 快速得到console.log()代码

# 十、事件、state与setState

App5.js中:

//事件讲解

import React, { Component } from 'react'

//1、实现点击弹框效果(事件基本格式)
export default class App5 extends Component {
    handleClick(){
        alert(132456)
    }

    render() {
        return (
            <div>
                <button onClick={this.handleClick}>按钮</button>
            </div>
        )
    }
}

//2、实现累加的功能 (状态的使用1)
export default class App4 extends Component {
    constructor(props){
        super(props)
        this.state = {
            num: 0
        }
        // 按钮3的函数写法的前提
        this.handleClick = this.handleClick.bind(this);
    }
    handleClick(){
        this.setState({
            num: this.state.num+1
        })
    }
    render() {
        return (
            <div>
                <h2>{ this.state.num }</h2>
                {/* 通过bind来改变this的指向 */}
                {/* <button onClick={this.handleClick.bind(this)}>按钮1</button> */}
                {/* 箭头函数默认没有this,所以this指向数组对象 */}
                {/* <button onClick={()=>this.handleClick()}>按钮2</button> */}
                <button onClick={this.handleClick}>按钮3</button>
            </div>
        )
    }
}

//3、实现双向数据绑定 (状态的使用2)
export default class App5 extends Component {
    constructor(p){
        super(p)
        this.state = {
            name: "你好,世界"
        }
    }
    handleChange(e){
        console.log(e.currentTarget.value)
        console.log(e.target.value)
        this.setState({
            name: e.target.value
        })
    }
    render() {
        return (
            <div>
                <h2>{ this.state.name }</h2>
                <input type="text" value={this.state.name} onChange={this.handleChange.bind(this)} />
            </div>
        )
    }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75

# 十一、state的简写

App6.js中:

import React, { Component } from 'react'

export default class App6 extends Component {
  // 写在construtor中的state也可以简写
    state = {
        username: "张三"
    }
    render() {
        return (
            <div>
                <h1>{this.state.username}</h1>
                <button onClick={this.handleClick.bind(this)}>按钮</button>
            </div>
        )
    }
    handleClick(){
        this.setState({
            username: "李四"
        })
    }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# 十二、setState是异步的

我们可以通过以下代码验证 setState 是异步或是同步:

import React, { Component } from 'react'

export default class App5 extends Component {
    state = {
      msg: "你好世界"
    }
    render() {
        return (
            <div>
                <h2>{this.state.msg}</h2>
                <button onClick={this.handleClick.bind(this)}>改变msg</button>
            </div>
        )
    }
    handleClick() {
        // this.setState是异步还是同步呢?
        this.setState({
            msg: "hello world"  // 修改msg
        })
        console.log(this.state.msg) // 同步则输出“hello world”,异步则输出“你好世界”

        // 验证结果:this.setState是异步的
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

另外 setState 还有回调函数:

this.setState({
  msg: "hello world"
}, ()=>{
  console.log(this.state.msg);    // hello world
})
1
2
3
4
5

如果想要在修改数据后调用该数据,就可以使用回调函数。

# 十三、累加

我们来实现一个累加的效果:

点击按钮则数字加1

import React, { Component } from 'react'

export default class App7 extends Component {
    state = {
        num: 0
    }
    render() {
        return (
            <div style={{textAlign: 'center'}}>
                <h2>{this.state.num}</h2>
                <button onClick={this.addNum.bind(this)}>累加</button>
            </div>
        )
    }
    // 累加
    addNum(){
        // num++ (num = num + 1) num++是会修改num的
        // this.state.num++      this.state.num被修改了
        // 唯一能修改state的方法是setState
        this.setState({
            num: this.state.num+1
        })
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

这里考点在于 ++ 会修改原数据,而在 react 中,修改state中的数据必须通过setState,因此这里不能对 this.state.num 直接进行 ++ 操作。

# 十四、双向数据绑定

React中没有类似vue的 v-model 指令,因此要实现双向数据绑定,只能操作 valueonChange(或onInput)事件

import React, { Component } from 'react'

// 双向数据绑定

export default class App8 extends Component {
    state = {
        msg: "你好世界"
    }
    render() {
        return (
            <div>
                <input type="text" value={this.state.msg} onChange={this.changeFn.bind(this)} />
                <h2>{this.state.msg}</h2>
            </div>
        )
    }
    // input的输入事件
    changeFn(e){
        /*
            currentTarget与target有什么区别?

            当只有一层元素的时候,两者没区别
            当存在两层元素嵌套时,就会有冒泡现象,那么真正指向被你事件触发的元素,是currentTarget
        */
        // console.log(e.currentTarget)
        // console.log(e.target)

        this.setState({
            msg: e.currentTarget.value
        })
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

这里做个补充:

如果input上写的是箭头函数,那么应当这么写,才能获取到事件对象e:

<input type="text" value={this.state.msg} onChange={(e)=>this.changeFn(e)} />
1

# 十五、state中数组的修改

我们对数组进行操作时,大部分数组方法会修改到原数组,因此建议先将数组深拷贝一次,修改后再重新赋值:

import React, { Component } from 'react'

export default class App9 extends Component {
    state = {
        arr: ["张飞", "赵云", "刘备"]
    }
    render() {
        return (
            <div>
                <ul>
                    {
                        this.state.arr.map((item, index)=>{
                            return <li key={index}>{item}</li>
                        })
                    }
                </ul>
                <button onClick={this.addFn.bind(this)}>追加一项到arr的最后</button>
            </div>
        )
    }
    // 追加一项到arr的最后
    // 修改state的方式只能是setState
    // 数组的push方法会修改原数组
    // this.state.arr.push() 会造成直接修改了state中的arr
    // 修改数组,不能直接修改this.state.arr

    addFn(){
        // 如果我声明一个变量,等于this.state.arr,并且让这个变量和this.state.arr完全脱离关系[深拷贝]
        let newArr = JSON.parse(JSON.stringify(this.state.arr));
        // 往newArr中push一项
        newArr.push('关羽');
        // 把最新的newArr赋值给arr
        this.setState({
            arr: newArr
        })
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

# 十六、【验证】为什么修改state只能通过setState

只有setState可以重新触发render函数对页面进行再次渲染,如果直接对state进行修改,那么是无法显示到界面中的,因此想要修改state,只能通过setState。

import React, { Component } from 'react'

// 验证为什么修改state只能通过setState

export default class App10 extends Component {
    state = {
        msg: "你好世界"
    }
    render() {
        return (
            <div>
                <h2>{this.state.msg}</h2>
                <button onClick={this.changeMsg.bind(this)}>修改msg</button>
            </div>
        )
    }
    // 修改msg
    changeMsg(){
        // this.setState({
        //     msg: "hello world"
        // })
        this.state.msg = "hello world";
        console.log('修改后的msg:'+this.state.msg)
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# 十七、【验证】key用id好还是index好?

当然是id好,看代码:

import React, { Component } from 'react'

export default class App11 extends Component {
    state = {
        books: [
            {id: 0, name: '老人与海'},
            {id: 1, name: '西游记'},
            {id: 2, name: '三国演义'}
        ]
    }
    render() {
        return (
            <div>
                <ul>
                    {
                        this.state.books.map((item, index)=>{
                            return (
                                // 失去了唯一标识符的意义
                                <li key={item.id}>
                                    <input type="text" />
                                    <strong>{item.name}</strong>
                                </li>
                            )
                        })
                    }
                </ul>
                <button onClick={this.addItem.bind(this)}>追加一项</button>
            </div>
        )
    }
    addItem(){
        let obj = {id: 3, name: '红楼梦'}
        // 深拷贝
        let newBooks = JSON.parse(JSON.stringify(this.state.books));
        newBooks.unshift(obj)

        this.setState({
            books: newBooks
        })

        // 假如追加的这一项会导致整个数组重排,那怎么办?
        // 如果key使用了index,当数组重排时,就会导致索引对不上
        // 解决方案就是key尽量不适用index作为唯一标识符,尽量使用id
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

# 十八、案例:Tab栏

App7.js中:

import React, { Component } from 'react'
import './com.css';

export default class App7 extends Component {
  state = {
    arr: ["新闻", "体育", "知识"],
    activeNum: 0
  }
render() {
  return (
    <div className="banner">
      <ul>
        {
          this.state.arr.map((item, index) => {
            // this.handleClick.bind(this, 参数)
            return <li key={index} onClick={this.handleClick.bind(this, index)} className={this.state.activeNum==index ? 'active' : ''}>{item}</li>;
          })
        }
      </ul>
      <ol>
        {
          this.state.arr.map((item, index) => {
            return <li key={index} className={this.state.activeNum==index ? 'active' : ''}>{item}</li>;
          })
        }
      </ol>
    </div>
  )
}
handleClick(index){
  // console.log(index)  // 得到索引值
  this.setState({
    activeNum: index
  })
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

com.css中:

*{margin: 0;padding: 0;border: 0;list-style: none;}

.banner{
    width: 500px;
    height: 300px;
    margin: 100px auto;
    border: 1px solid #000;
}

ul{
    height: 60px;
    line-height: 60px;
    display: flex;
    text-align: center;
    justify-content: space-between;
}

ul li{
    height: 60px;
    width: 30%;
    background: #efefef;
}

ul li.active{
    background: darkred;
    color: #fff;
}

ol li{
    height: 240px;
    background: darkred;
    text-align: center;
    line-height: 240px;
    color: #fff;
    display: none;
}

ol li.active{
    display: block;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

# 十九、作业

请使用下列数组:

var arr = [
    {txt: '6月25日峡谷龙舟赛挑战局数异常修复公告', time: '06/25'},
    {txt: '6月25日峡谷龙舟赛挑战局数异常说明', time: '06/25'},
    {txt: '6月25日体验服停机更新公告', time: '06/25'},
    {txt: '6月24日峡谷龙舟赛异常修复公告', time: '06/24'},
    {txt: '6月24日“演员”惩罚名单', time: '06/24'},
    {txt: '6月24日外挂专项打击公告', time: '06/24'}
];
1
2
3
4
5
6
7
8

完成以下效果:

(0)

相关推荐

  • 解读在React中使用JSX语法

    JSX是JavaScript的一种语法扩展,被应用到React体系结构中,它的格式与模板语言类似,但实际上完全在JavaScript内部实现.组成React应用程序的元素最小单元,JSX用于声明Rea ...

  • 前端教程:React之Fragments组件语法片段的使用

    React开发中常见的模式之一是将多个元素返回一个组件,Fragments允许您聚合一个子元素列表,并且不会在DOM中添加额外的节点.会Vue的朋友当然会发现,它看起来和Vue的template非常相 ...

  • 正则表达式 – 语法 | 菜鸟教程

    正则表达式 - 语法 正则表达式(regular expression)描述了一种字符串匹配的模式(pattern),可以用来检查一个串是否含有某种子串.将匹配的子串替换或者从某个串中取出符合某个条件 ...

  • openGauss与PostgreSQL分区策略语法测试

    openGauss与PostgreSQL分区策略语法测试

  • 高中英语学习方法:怎么学好词汇和语法

    语言学习是一个厚积薄发的过程.高中英语怎么学好?小编觉得首先要把基础打好,学习高中英语最重要的基础是词汇和语法,那么,词汇和语法怎么学好呢? 一.词汇积累的作用及方法 词汇是语言的核心. 我们都知道, ...

  • 小学英语中必背的名词单数变复数的语法规则,你都熟记了吗?

    英语中名词可分为可数名词和不可数名词.可数名词在应用时有单数和复数形式,表示一个用单数,表示两个或两个以上用复数.复数名词的构成分为规则变化和不规则变化.让我们来看看具体是怎么变化的吧! 名词单数变复 ...

  • 语法填空的解题技巧和方法汇总,建议收藏!

    语法填空是近年来高考英语推出的一种新题型.在一篇200词左右的语言材料中留出10个空白,要求考生根据上下文填写空白处所需的内容或所提供单词的正确形式,这种题型能全面检测学生在英语词汇.语法,甚至是句法 ...

  • 六张图帮你看懂英语语法!

    六张图帮你看懂英语语法!

  • 【外语】语法填空的解题技巧和方法汇总,建议收藏!

    [高中外语] 此类题可以考查学生对单词形式变化的掌握程度.单词形式变化主要有两种,一是词的形.数.式的变化,一是词的派生变化.在判断出词的变化之后还应该进一步审题,看是否需要使用复合的变化形式,这一点 ...

  • 几个常用函数语法,看过你就不会忘

    IF函数 =IF(判断条件,符合条件时返回啥,不符合条件返回啥) SUMIF函数 =SUMIF(条件区域,指定的条件,求和区域) SUMIFS函数 =SUMIFS(求和区域,条件区域1,指定条件1,条 ...