React基础学习

React基础

📣 📣 📣 📢📢📢

☀️☀️点开就是缘分认识一下,我是小冷。是一个兴趣驱动自学练习两年半的的Java工程师。

📒 一位十分喜欢将知识分享出来的Java博主⭐️⭐️⭐️,擅长使用Java技术开发web项目和工具

📒 文章内容丰富:覆盖大部分java必学技术栈,前端,计算机基础,容器等方面的文章

📒 如果你也对Java感兴趣,关注小冷吧,一起探索Java技术的生态与进步,一起讨论Java技术的使用与学习

✏️高质量技术专栏专栏链接: 微服务数据结构netty单点登录SSMSpringCloudAlibaba
😝公众号😝想全栈的小冷 ,分享一些技术上的文章,以及解决问题的经验

当前专栏React系列

React核心价值与前置知识

核心价值

  • 组件化(易开发易维护)

  • 数据驱动视图 :定义好数据和ui的显示规则 即UI=f(state)

    • 只关注业务数据修改,不在操作DOM 增加开发效率

使用vite创建Recat项目

开发规范

使用 prettier & eslint 规范开发

  • eslint 检查语法语义
  • prettier 检查代码风格
shell 复制代码
#eslint :
npm install eslint@typescript-eslint/parser @typescript-eslint/eslint-plugin --save-dev

#prettier:
npm install prettier eslint-config-prettier eslint-plugin-prettier --save-dev

vite和 webpack的区别

webpack是一个非常流行的前端打包工具 比较经典 Create-React-App 是使用webpack作为打包工具的

vite 既是构建工具 又是打包工具

vite的特点:

  1. Vite打包项目 在启动和代码更新时更快
  2. vite使用了 es Module 语法(仅开发环境)

React JSX语法

内容 :

  1. JSX语法
  2. 组件和props
  3. 实战: 列表页

JSX特点:

  1. JSX是js的扩展 写在js代码里面 组件的ui结构
  2. 语法和html很相似
  3. 不只是React独有

标签

  • 首字母大小写的区别 , 大写字母是自定义组件
  • 标签必须闭合 如<input>在jsx是非法的
  • 每段JSX中只有一个根节点

属性

和html基本相似

  • class要改为 className
  • style要使用js对象 不能是string 而且key需要使用驼峰写法

如下

在JSX中插入js变量

  • 使用{}可以插入JS变量 函数 表达式
  • 可以插入文本 属性
  • 可以用于注释

代码案例

条件判断

​ 常见的if else 可以通过{}的方式实现,但是在JSX中代码一多就显得不够实用了 以下三种方法可以解决:

  • 使用&&
  • 使用三元表达式
  • 使用函数来判断

比如这样:反之如果flag等于false 就不会出现hello

效果:

三元运算符:flag为判断条件 来控制标签的显示

效果:

函数:

jsx 复制代码
function isShowHello(){
  if (flag)return <p>show hello</p>
  return <p>defaultHello</p>
}

效果 :

循环

  • 使用map来循环
  • 每一个循环项(item)都要有key
  • key需要具有唯一性

实现

jsx 复制代码
const list = [
  {username:'zhangsan', name:"张三"},
  {username:'shuangyue', name:"双月"},
  {username:'lisi', name:"李四"},
]

     {/*循环*/}
        <div>
          {list.map(user=>{
            const {username,name} = user
           return <li key={username}>{name}</li>
          })}
        </div>

效果:

PS : 不建议使用 index 如 :

因为我们的key 需要具有唯一性

小结实战 列表页

开发一个列表页

调整一下显示的jsx

保证这个代码结构简洁 ,然后就可以开始开发了

jsx 复制代码
import React from 'react';
import './App1.css';

function App() {
    const questionList = [
        {id: 'q1', title: '问卷1', isPublished: true},
        {id: 'q2', title: '问卷2', isPublished: true},
        {id: 'q3', title: '问卷3', isPublished: true},
        {id: 'q4', title: '问卷4', isPublished: false}
    ]

    function edit(id) {
        console.log('edit', id);
    }

    return (<div>
        <h1>列表详情页</h1>
        <div>
            {questionList.map(question => {
                const {id, title, isPublished} = question;
                return <div key={id} className="list-item">
                    &nbsp;
                    <strong>{title}</strong>
                    &nbsp;
                    {isPublished ? <span style={{color: "green"}}>已发布</span> : <span>未发布</span>}
                    &nbsp;
                    <button onClick={() => edit(id)}>编辑问卷</button>
                </div>
            })}
        </div>
    </div>)

}

export default App;

css

css 复制代码
.list-item {
    border: 1px solid #ccc;
    padding: 10px;
    margin-bottom: 16px;
    display: flex;
    justify-content: center;
}

效果

组件

react 一切皆是组件

  • 组件拥有一个ui片段
  • 拥有独立的逻辑和显示
  • 可大可小 可以嵌套

组件拆分的价值和意义

  • 组件嵌套来组织的 ui 结构 和 html 一样没有学习成本
  • 良好的拆分组件利于代码维护和多人协同开发
  • 封装公共组件或者直接使用第三方组件复用代码

好的组件化 逻辑是清晰的 更能提升开发效率并且更加的美观易读

我们可以将组件理解成一个一个的函数

使用我们之前的列表页代码 拆分成组件 list1

然后用improt的方式 引入到listdemo中

这样我们的总框架就没有那么多的代码冗余 需要修改对应的代码 只需要寻找对应的组件文件即可

属性 props

  • 组件可以嵌套 有层级关系
  • 父组件可以向子组件传递数据
  • props是只读对象

props 其实就是实现差异化组件信息传递的一种手段

实践

将之前循环内显示数据的div拆出来抽象成组件:QuestCard.tsx 。 CSS还是和之前的内容一样

使用 ts主要是方便传入泛型

QuestCard.tsx

tsx 复制代码
import React, {FC} from "react";
import './QuestCard.css'

type proptype = {
    id: string,
    title: string,
    isPublished: boolean
}
export const QuestCard: FC<proptype> = (props) => {
    const {id, title, isPublished} = props;

    function edit(id) {
        console.log('edit', id);
    }

    return (
        <div key={id} className="list-item">
            &nbsp;
            <strong>{title}</strong>
            &nbsp;
            {isPublished ? <span style={{color: "green"}}>已发布</span> : <span>未发布</span>}
            &nbsp;
            <button onClick={() => edit(id)}>编辑问卷</button>
        </div>)
}

改造list1.jsx 这样就将显示问卷卡片抽取出来为一个独立的组件了

jsx 复制代码
import React from "react";
import './list1.css';
import {QuestCard} from "./QuestCard";

export const List1 = () => {
    const questionList = [
        {id: 'q1', title: '问卷1', isPublished: true},
        {id: 'q2', title: '问卷2', isPublished: true},
        {id: 'q3', title: '问卷3', isPublished: true},
        {id: 'q4', title: '问卷4', isPublished: false}
    ]


    return (
        <div>
            <h1>列表详情页</h1>
            <div>
                {questionList.map(question => {
                    const {id, title, isPublished} = question;
                    return <QuestCard key={id} id={id} title={title} isPublished={isPublished}/>
                })}
            </div>
        </div>)

}

小结:

  • 如何定义和使用组件
  • props-父组件给子组件传递数据
  • 重构列表页 抽象出QuestionCard

效果

children

场景: 当我们把内容签到在子组件标签中时,父组件会自动的在名为 children的prop中接受内容

子组件传递父组件

顾名思义 其实就是子组件给父组件传递信息

tsx 复制代码
function Son({onGetSonMsg}) {
//     son 中的数据
    const sonMsg = 'this is son msg';
    return <div>this is son
        <button onClick={() => onGetSonMsg(sonMsg)}>sendMsg</button>
    </div>
}

function AppDemo() {
    const [msg, setMsg] = useState('')
    const getMsg = (msg) => {
        console.log(msg)
        // msg = '我是信息'  这么改是无效的
        setMsg(msg)
    }
    return <div>
        this is APP Son send msg =>{msg}
        <Son onGetSonMsg={getMsg}/>
    </div>
}
兄弟组件传递

使用状态提升实现兄弟组件通信

  • 其实就是有共同父组件的两个子组件传递信息
  • a 传递给父组件 然后由父组件 传递给 b

代码

tsx 复制代码
import {useState} from "react";

function A({onGetAName}) {
    const name = "a name"
    return <div>this is A
        <button onClick={() => onGetAName(name)}>send</button>
    </div>
}

function B({pushAName}) {
    return <div>this is B
        {pushAName}
    </div>
}

function AppDemo() {
    const [aName, setAName] = useState('');
    const getAName = (name) => {
        console.log(name)
        setAName(name)
    }
    return <div>
        this is app
        <A onGetAName={getAName}/>
        <B pushAName={aName}/>
    </div>
}


export default AppDemo;
function A({onGetAName}) {
    const name = "a name"
    return <div>this is A
        <button onClick={() => onGetAName(name)}>send</button>
    </div>
}

function B({pushAName}) {
    return <div>this is B
        {pushAName}
    </div>
}

function AppDemo() {
    const [aName, setAName] = useState('');
    const getAName = (name) => {
        console.log(name)
        setAName(name)
    }
    return <div>
        this is app
        <A onGetAName={getAName}/>
        <B pushAName={aName}/>
    </div>
}

效果

HOOKS

useState

这是React 中的一个hook 函数 它允许我们向组件添加一个状态变脸,从而控制组件的渲染结果

tsx 复制代码
 const [msg, setMsg] = useState('')
  1. useState是一个函数 返回值是一个数组
  2. 数组中的第一个参数是状态变量,第二个参数是set函数用于修改状态
  3. useState的参数将作为状态变量的初始值

修改规则

在React 中 状态被认为是只读的 我们应该替换而不是修改 直接修改状态不会得到视图的更新

tsx 复制代码
    const [msg, setMsg] = useState('')
    const getMsg = (msg) => {
        console.log(msg)
        // msg = '我是信息'  这么改是无效的
        setMsg(msg)
    }
    
    //如果是对象作为参数
      const [msg, setMsg] = useState({id:'122ds'})
    const getMsg = (msg) => {
        console.log(msg)
        // msg = '我是信息'  这么改是无效的
        setMsg({
            ...msg,
        	id:'123'})
    }

useContext 组件通信

  1. 使用createContext 方法创建一个上下文对象 ctx=
  2. 在顶层组件 app 中 通过 ctx.Provider提供数据
  3. 在底层组件 通过 useContext钩子函数获取消费数据

案例 :

我们需要将app的消息传递到b

TSX 复制代码
const MsgContext = createContext()

function A() {
    return <div>this is A
        <B/>
    </div>
}

function B() {
    const msg = useContext(MsgContext)
    return <div>this is B from APP:{msg}
    </div>
}

function AppDemo() {
    const msg = "this is app msg"
    return (<div>
        <MsgContext.Provider value={msg}>
            this is app
            <A/>
        </MsgContext.Provider>
    </div>)
}

useEffect

这是React中的一个 hook 函数 ,用于在React 中创建不是由事件引起而是由渲染本身引起的操作,比如发送 AJAX请求 更改DOM等

基础使用

需求: 在组件渲染完毕后,从服务器获得列表数据展示

语法:

TSX 复制代码
useEffect(()=>{},[])
  1. 参数1是一个函数,可以把它叫做副作用函数,函数内部可以放置要执行的操作
  2. 参数2是一个数组 ,数组里放置依赖项,不同依赖项会影响第一个参数的执行,当该参数是一个空数组的时候,副作用函数只会在组件渲染完毕后执行一次
tsx 复制代码
import {useEffect, useState} from "react";

const URL = 'http://geek.itheima.net/v1_0/channels'

function AppDemo() {
    const [list, setList] = useState([]);
    useEffect(() => {
        async function getList() {
            const res = await fetch(URL)
            const jsonRes = await res.json()
            console.log(jsonRes)
            setList(jsonRes.data.channels)
        }

        getList()
        console.log("list", list)
    }, []);
    return (<div>
        this is app
        <ul>
            {list.map(item => <li key={item.id}>{item.name}</li>)}
        </ul>
    </div>)
}


export default AppDemo;

效果

依赖项参数

TSX 复制代码
function AppDemo() {
    /*1. 没有依赖项*/
    const [count, setCount] = useState(0);
    // useEffect(() => {
    //     console.log("副作用函数执行了")
    // });
    /*2 传入空数组依赖*/
    // useEffect(() => {
    //     console.log("副作用函数执行了")
    // }, []);
    useEffect(() => {
        console.log("副作用函数执行了")
    }, [count]);
    return <div>this is app
        <button onClick={() => setCount(count + 1)}>+{count}</button>
    </div>
}

清除副作用

useEffect中编写的由渲染本身引起的对接组件外部的操作,社区也经常把它叫做副作用操作,我们想在组件卸载时把这个定时器清理掉,这个过程就是清理副作用

tsx 复制代码
import {useEffect, useState} from "react";

function Son() {
    useEffect(() => {
        const timer = setInterval(() => {
            console.log("定时器执行中...")
        }, 1000)
        return () => {
            //     清楚副作用
            clearInterval(timer)
        }
    }, []);
    return <div>this is son</div>
}

function AppDemo() {
    const [show, setShow] = useState(true)
    return <div>this is app
        {show && <Son/>}
        <button onClick={() => setShow(false)}>卸载组件</button>
    </div>
}

export default AppDemo;

自定义hook

暂时没有什么很好的例子 写一个比较简单的 之后再拓展

tsx 复制代码
import {useState} from "react";

function useToggle() {
// 可复用代码
    const [value, setValue] = useState(true);
    const toggle = () => {
        setValue(!value)
    }
    return {value, toggle}
}

function AppDemo() {
    const {value, toggle} = useToggle()
    return <div>this is app
        {value && <div>this is show Toggle</div>}
        <button onClick={toggle}>Toggle</button>
    </div>
}

export default AppDemo;

效果

点击

相关推荐
GIS好难学33 分钟前
《Vue进阶教程》第六课:computed()函数详解(上)
前端·javascript·vue.js
nyf_unknown36 分钟前
(css)element中el-select下拉框整体样式修改
前端·css
m0_548514771 小时前
前端打印功能(vue +springboot)
前端·vue.js·spring boot
执键行天涯1 小时前
element-plus中的resetFields()方法
前端·javascript·vue.js
Days20501 小时前
uniapp小程序增加加载功能
开发语言·前端·javascript
喵喵酱仔__1 小时前
vue 给div增加title属性
前端·javascript·vue.js
dazhong20121 小时前
HTML前端开发-- Iconfont 矢量图库使用简介
前端·html·svg·矢量图·iconfont
m0_748248771 小时前
前端vue使用onlyoffice控件实现word在线编辑、预览(仅列出前端部分需要做的工作,不包含后端部分)
前端·vue.js·word
雨中奔跑的小孩2 小时前
爬虫学习案例3
爬虫·python·学习
莫惊春2 小时前
HTML5 第五章
前端·html·html5