欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

前端笔记之React(一)初识React&组件&JSX语法

程序员文章站 2022-05-03 12:03:14
一、React项目起步配置 官网:https://reactjs.org/ 文档:https://reactjs.org/docs/hello-world.html 中文:http://react.css88.com/ 2013年被开源,2014年在中国彻底火爆。 React是CMD架构,现阶段需要 ......

一、react项目起步配置

官网:

文档:

中文:

2013年被开源,2014年在中国彻底火爆。

 

reactcmd架构,现阶段需要webpack打包

npm install -g webpack@4.9.1

必须安装以下三个依赖:

npm install --save-dev babel-core babel-loader babel-preset-env

 

react采用jsx语法,jsx语法是什么?

就是全球唯一标准的javascriptxhtml结合开发最优雅的语法。

浏览器不识别jsx语法,所以需要babeljsx语法翻译,babel要装一个新的preset

npm install --save-dev babel-preset-react

 

安装完依赖,修改webpack.congif.js文件中的preset配置:

const path = require('path');
module.exports = {
    entry: "./www/app/main",
    output : {
        path: path.resolve(__dirname, "www/dist"),
        filename : "bundle.js",
    },
    watch:true,
    mode : "development",
    module: {
        rules: [
            {
                test: /\.js?$/, 
                include: [path.resolve(__dirname, "www/app")],
                exclude: [path.resolve(__dirname, "node_modules")], 
                loader : "babel-loader",
                options: { presets: ["env","react"] }, //要翻译的语法 
            }
        ]
    }
}

还要安装reactreact-dom包:

npm install --save react react-dom

 react是核心库

 react-dom提供了与dom操作的功能库

注意:项目文件夹名字千万不要叫react,很坑。

 

index.html上放“挂载点”的盒子:

<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <title>document</title>
</head>
<body>
    <div id="app"></div>
</body>
<script type="text/javascript" src="dist/bundle.js"></script>
</html>

 

app/main.js

import react from "react";
import reactdom from "react-dom";

reactdom.render(
    <div>
        <h1>你好,我是react,来自facebook公司</h1>
    </div>,
    document.getelementbyid('app')
);

运行webpack,直接打开页面:

前端笔记之React(一)初识React&组件&JSX语法

 react是所有react项目的入口

 react-dom负责react element添加到html页面的挂载点上

 

react-dom 这个包提供了你的app最高等级的api,提供了元素的挂载和上树的方法

render() 接收两个参数,第一个参数是react元素,第二个参数是挂载点,用来让react元素进行挂载。

 

vue在写实例,而react在写类(构造函数)。


二、组件

组件叫component”,就是htmlcssjs行为的一个封装。

vue中的组件是一个.vue文件(其实是普通的json对象),react中,组件是一个类(构造函数)。

2.1类式组件

创建app.js文件,这是一个组件,必须按照要求写标准壳,这个壳我们叫rcc壳“react class component”,react的类式组件:

import react from "react";
// 默认暴露一个构造函数(类组件)
export default class app extends react.component{
    constructor(){
        super();
    }
    render(){
        return <div>
            <h1>我是app组件!</h1>
        </div>
    }
}

 

注意:

1)这个文件的默认暴露就是一个类,这个类的类名必须和文件名相同。
2)文件名和类名的首字母必须大写!react中组件的合法名字首字母必须是大写字母。
3)这个类必须继承自react.component类,也就是说,rcc壳必须是extends react.component的写法。
4)这个类必须有构造器constructor,构造器里面必须调用超类的构造器,super();
5)这个类必须有render函数,render函数中必须return一个jsx对象。而且这个jsx对象必须被唯一的标签包裹。

 

在main.js主文件中引入组件,然后用自定义标签:

import react from "react";
import reactdom from "react-dom";
// 引入组件
import app from "./app.js";

reactdom.render(
    <div>
        <app></app>
        <h1>你好,我是react,来自facebook公司</h1>
    </div>,
    document.getelementbyid("app")
);

注意:

引入的组件必须路径以./开头

组件要使用,就将这个组件的名字(类名、文件名)进行标签化即可

原理就是这个app类在被实例化。

因为类的名字是大写字母,所以所有的自定义组件标签名字一定是大写字母开头的

react中,所有以大写字母开头的都是组件,而不是标签。

 

reactdom.render(jsx,根的挂载点)

reactdom只能出现一次,但是非常厉害,可以和html结合

 前端笔记之React(一)初识React&组件&JSX语法

jsx,现在一律在js文件夹中开发,并不是传统放html开发

htmlcssjs都被构建到bundle.js文件夹中。

 

安装以下插件,输入rcc即可快速生成一个组件的语法:

 前端笔记之React(一)初识React&组件&JSX语法


2.2组件可以多层嵌套

main.js文件中引入app.js组件,app组件里面的render函数还可以引入其他组件。

components/child.js

import react from "react";
export default class child extends react.component {
    constructor() {
        super();
    }
    render() {
        return <div>
            <h1>我是child子组件!</h1>
        </div>
    }
}

 

app父组件中引入:

import react from "react";
import child from "./components/child";
// 默认暴露一个构造函数(类组件)
export default class app extends react.component {
    constructor() {
        super();
    }
    render() {
        return <div>
            <h1>我是app组件!</h1>
            <child></child>
            <child></child>
            <child></child>
        </div>
    }
}

简单的说:在react中做一个组件:

第一步:创建一个类并暴露

第二步:引入这个类,然后用这个类的类名当做组件的标签(实例化)


2.3函数式组件

一个函数,如果是大写字母开头,并且return一个react element就是一个组件。

比如app.js组件中,创建一个child1的函数,这个函数直接返回jsx语法的react element,此时这个函数就是组件,这个函数直接成为自定义标签,就可以用了。

import react from "react";
import child from "./components/child";
// 默认暴露一个构造函数(类组件)

//定义一个自定义的函数组件
const child1 = ()=> <div>
    <h1>我是child1函数式组件!</h1>
</div>

export default class app extends react.component {
    constructor() {
        super();
    }
    render() {
        return <div>
            <h1>我是app组件!</h1>
            <child></child>
            <child1></child1>
        </div>
    }
}

注意:

1render是一个函数,所以函数里面当然可以定义另一个函数。我们用const来定义一个箭头函数,这个箭头函数的名字,必须首字母大写。react中所有标签名字是首字母大写的,将被判定为我们自己的组件。

2)这个函数里面return了一个jsx对象,注意,不要加引号。初学者会有很多不适。

3)这个组件也是通过“标签”的形式来上树的!

4)函数式组件比类组件差很多功能很多,后面会说。

5)至于什么时候用什么组件、圆括号中能不能传入参数,后面会说。

 

函数式组件有个缺点,没有state,没有生命周期。


三、jsx语法

所有对react不适应,都是jsx语法造成的,jsx语法淡化了jshtml之间的“边界”。

 

3.1标签必须合理嵌套

错误的:

import react from "react";
import reactdom from "react-dom";
// 引入组件
import app from "./app.js"
reactdom.render(
    <app></app>
    <app></app>
    <app></app>
  ,
  document.getelementbyid('app')
);

 

有多个组件,必须有一个标签包裹所有组件:

import react from "react";
import reactdom from "react-dom";
// 引入组件
import app from "./app.js"
reactdom.render(
  <div>
     <app></app>
     <app></app>
     <app></app>
  </div>
  ,
  document.getelementbyid('app')
);

 

比如table不能直接嵌套tr,必须要有tbody

import react from "react";
export default class app extends react.component {
    constructor() {
        super();
    }
    render() {
        return <div>
            <table>
                <tbody>
                    <tr>
                        <td>1</td>
                        <td>2</td>
                    </tr>
                </tbody>
            </table>
        </div>
    }
}

 

比如这样也是错误的:

 <p><div>111</div></p>

前端笔记之React(一)初识React&组件&JSX语法


3.2 return不能换行

return后面直接跟着div,不能换行

 前端笔记之React(一)初识React&组件&JSX语法

 

如果想换行,必须加圆括号包裹。

import react from "react";
export default class app extends react.component {
    constructor() {
        super();
    }
    render() {
        return (
            <div>
                <h1>我是app组件</h1>
            </div>
        )
    }
}

3.3标签必须严格封闭

因为jsx语法被babel-loader翻译(babel-perset-react),所以标签必须严格封闭,否则翻译会报错。

错误的:
<br>
<hr>

正确的:
<br/>
<hr/>

错误的:
<input type="text">

正确的:
<input type="text" />

3.4所有的类名必须用classname表示

因为jsclass是关键字,所以类名必须用classname

错误的

<div class="box"></div>

前端笔记之React(一)初识React&组件&JSX语法

正确的:

 <div classname="box"></div>

 

for要用htmlfor代替:

错误的:
 <label for=""></label>
正确的:
 <label htmlfor=""></label>

3.5插值基础(重点)

可以在jsx内部,用单个“{}”大括号进行一些js表达式的插入,我们叫做插值。

{} 只能出现在react element中,简化了连字符串工作。

import react from "react";
export default class app extends react.component {
    constructor() {
        super();
    }
    render() {
        const year = 10000;
        const pingfang = (n)=>{
            return n * n
        }
        const arr = [1000,2000,3000,4000]
        return <div>
            <h1>{5000 * 2}年</h1>
            <h1>{year}年</h1>
            <h1>{pingfang(100)}年</h1>
            <h1>{arr.reduce((a,b)=>a + b)}年</h1>
            <h1>{parseint(math.random() * 100)}年</h1>
            <h1>{3 > 8 ? 10000 : 1}年</h1>
        </div>
    }
}

 

不能出现的语法:

不能定义变量:

<h1>{var a = 100}</h1>

不能定义函数:

<h1>{function name(){}}</h1>

应该在return之前定义:

render() {
    const pingfang = (n)=> n * n
    return (
        <div>
            <h1>我爱你{pingfang(100)}年</h1>
        </div>
    )
}

 

不能出现for循环、if语句、whiledo语句:

<h1>{for(var i = 0;i < 100;i++){}}</h1>

jsx不能出现对象(json)。

render() {
    const obj = {"a":100,"b":200}
    return (
        <div>
            <h1>{obj}</h1>
        </div>
    )
}

此时会报错,如果要在页面显示json,应该:

render() {
    const obj = {"a":100,"b":200}
    return (
        <div>
            <h1>{json.stringify(obj)}</h1>
        </div>
    )
}

3.6插值高级

jsx表达式不能出现引号中,比如有一个变量

render() {
    const picurl = "baby1.jpg"
    return <div>
        <img src="images/{picurl}.jpg" />
    </div>
}

 

正确的应该先写在外层的{}

render() {
    const picurl = "baby1";
    const tip = '这是黄晓明老婆';
    const url = 'http://www.baidu.com/'
    return <div>
        <img src={"images/" + picurl + ".jpg"} />
        <img src={`images/${picurl}.jpg`} title={tip} />
        <a href={url}>去百度</a>
    </div>
}

 

内嵌样式要求这样的语法插值:

style后面直接跟着{{}},没有引号,{{}}中是json,所有的属性名都是驼峰命名法:

<div style={{"width":"100px","height":"100px","backgroundcolor":"red"}}></div>

react的程序,可以进行合理的换行

<div style={{
    "width":"100px",
    "height":"100px",
    "backgroundcolor":"red"
}}>
</div>

3.7 jsx中数组内容会被自动展开(重点)

此时你心里可能有一万个*,这是什么鬼,数组怎么能不加引号呢?因为是jsx语法规定。

import react from "react";
export default class app extends react.component {
    constructor() {
        super();
    }
    render() {
        const arr = [
            <li key="0">牛奶</li>,
            <li key="1">咖啡</li>,
            <li key="2">奶茶</li>,
            <li key="3">可乐</li>
        ]
        return <div>
             <ul>
                 {arr}
             </ul>
        </div>
    }
}

只要你在{}放一个数组,此时这个数组不用循环了,就会自动被展开。

所有的数组元素,必须加上key属性,否则报错

 前端笔记之React(一)初识React&组件&JSX语法

注意:

数组有4项,每项都是jsx元素,不需要加引号

每项必须要有不同的key属性,这是react要求的

数组直接{arr}就可以了,也不需要写循环遍历语句。

 

数据和dom怎么进行模板的循环:

arr数组中,没有任何的标签,只是数据:此时就要在{}中用map来映射一个新的数组

import react from "react";
export default class app extends react.component {
    constructor() {
        super();
    }
    render() {
        const arr = ["牛奶","咖啡","奶茶","可乐"]
        return <div>
             <ul>
                 {arr.map((item,index)=>{
                    return <li key={index}>{item}</li>
                 })}
             </ul>
        </div>
    }
}

映射出一个表格:

import react from "react";
export default class app extends react.component {
    constructor() {
        super();
    }
    render() {
        const arr = [
            {"id":1,"name":"小明","age":12,"sex":"男"},
            {"id":2,"name":"小红","age":13,"sex":"女"},
            {"id":3,"name":"小刚","age":14,"sex":"男"},
            {"id":4,"name":"小白","age":15,"sex":"男"}
        ]
        return <div>
             <table>
                 <tbody>
                    {
                        arr.map(item=>{
                            return <tr key={item.id}>
                                <td>{item.id}</td>
                                <td>{item.name}</td>
                                <td>{item.age}</td>
                                <td>{item.sex}</td>
                            </tr>
                        })
                    }
                 </tbody>
             </table>
        </div>
    }
}

3.8九九乘法表

学习的是二维数组的展开

我们先有一个套路,准备一个外层的数组,然后外层的循环中push内部数组:

import react from "react";
export default class app extends react.component {
    //构造函数
    constructor() {
        super();
    }
    render() {
        var arr = [];
        for(var i = 1;i <= 9;i++){
            var temp = []
            for(var j = 1; j <= i; j++) {
                temp.push(<td key={j}> {i} * {j} = {i*j} </td>)
            }
            arr.push(<tr key={i}>{temp}</tr>)
        }
        return (
            <div>
                 <table>
                    <tbody>
                        {arr}
                    </tbody>
                 </table>
            </div>
        )
    }
};

3.9日历

日历的原理,决定一个日历的画风,有三要素:

 这个月第一天是星期几;

 这个月有几天;

 上个月有几天;

 

要知道2018年5月5日是星期几:
new date(2018,5-1,5).getday()

要知道2018年5月有几天:
new date(2018,5,0).getdate()

 

本月有几天,等价于下个月前一天是几号,所以下个月的0号,就是本月的最后一天。

 

 

给日历加农历:

npm install --save solarlunar
import react from "react";
import solarlunar from 'solarlunar';
export default class app extends react.component {
    //构造函数
    constructor() {
        super();
    }
    render() {
        var year = 2018;
        var month = 8; //是人类的月份,而不是计算机的
        //本月第一天是星期几
        var themonthfirstday = new date(year,month - 1,1).getday();
        //本月共几天
        var themonthdays = new date(year,month,0).getdate();
        //上个月共几天
        var prevmonthdays = new date(year,month-1,0).getdate();

        var arr = [];
        
        //上个月的尾巴,本月第一天星期几就有几天上个月的尾巴
        while (themonthfirstday--){
            arr.unshift(prevmonthdays--)
        }

        // 本月放进数组
        var count = 1;
        while(themonthdays--){
            arr.push(count++);
        }
        // 下个月的前有多少天,要补齐42天
        var nextcount = 1;
        while ( arr.length != 42){
            arr.push(nextcount++);
        }
        console.log(arr)
        //接下来要用这个一维数组集合jsx语法,展开为二维数组
        const showtable = ()=>{
            var domarr = [];
            for(var i = 0; i < arr.length / 7; i++){
                domarr.push(
                    <tr key={i}>
                        {
                            arr.slice(i * 7, i * 7 + 7).map(item=>{
                                var n = solarlunar.solar2lunar(year, month, item);
                                return <td key={item}>
                                    {item}
                                    <br/>
                                    {n.term || n.daycn}
                                </td>
                            })
                        }
                    </tr>      
                )
            }
            return domarr;
        }

        return (
            <div>
                 <table>
                     <thead>
                         <tr>
                             <th>日</th>
                             <th>一</th>
                             <th>二</th>
                             <th>三</th>
                             <th>四</th>
                             <th>五</th>
                             <th>六</th>
                         </tr>
                     </thead>
                     <tbody>
                        {showtable()}
                     </tbody>
                 </table>
            </div>
        )
    }
};