好看网站手机版,深圳做网站乐云seo费用优惠,标志设计公司网站,没有网站可以做域名解析吗React介绍
React由Meta公司开发#xff0c;是一个用于构建Web和原生交互界面的库
React的优势
相较于传统基于DOM开发的优势
组件化的开发方式不错的性能
相较于其它前端框架的优势
丰富的生态跨平台支持
开发环境创建
create-react-app是一个快速创建React开发环境的…React介绍
React由Meta公司开发是一个用于构建Web和原生交互界面的库
React的优势
相较于传统基于DOM开发的优势
组件化的开发方式不错的性能
相较于其它前端框架的优势
丰富的生态跨平台支持
开发环境创建
create-react-app是一个快速创建React开发环境的工具底层由Webpack构件封装了配置细节开箱即用 执行命令
npx create-react-app react-basicnpx - Node.js工具命令查找并执行后续的包命令create-react-app - 核心包固定写法用于创建React项目react-basic React项目的名称可以自定义 启动项目 npm start
渲染流程App.js跟组件导入到index.js里把根组件渲染到id为root的index.html
JSX基础
什么是JSX JSX是JavaScript和XMl(HTML)的缩写表示在JS代码中编写HTML模版结构它是React中构建UI的方式 const message this is message
function App(){return (divh1this is title/h1{message}/div)
}优势
HTML的声明式模版写法JavaScript的可编程能力
JSX高频场景-JS表达式 在JSX中可以通过 大括号语法{} 识别JavaScript中的表达式比如常见的变量、函数调用、方法调用等等 使用引号传递字符串 使用JS变量 函数调用和方法调用 使用JavaScript对象
注意if语句、switch语句、变量声明不属于表达式不能出现在{}中
const message this is message
function getAge(){return 18
}
function App(){return (divh1this is title/h1{/* 字符串识别 */}{this is str}{/* 变量识别 */}{message}{/* 函数调用 渲染为函数的返回值 */}{getAge()}/div)
}JSX高频场景-列表渲染 在JSX中可以使用原生js种的map方法 实现列表渲染 key的作用React框架内部使用提升更新性能的
const list [{id:1001, name:Vue},{id:1002, name: React},{id:1003, name: Angular}
]
function App() {return (div classNameAppthis is App{/* 渲染列表 */}{/* map循环哪个结构return哪个结构 */}ul{list.map(item li key{item.id} {item.name} /li)}/ul/div)
}JSX高频场景-条件渲染 在React中可以通过逻辑与运算符、三元表达式(? 实现基础的条件渲染 const flag true
const loading false
function App(){return (div{flag spanthis is span/span}{loading ? spanloading.../span:spanthis is span/span}/div)
}JSX高频场景-复杂条件渲染 解决方案自定义函数 判断语句 const type 1 // 0|1|3function getArticleJSX(){if(type 0){return div无图模式模版/div}else if(type 1){return div单图模式模版/div}else(type 3){return div三图模式模版/div}
}
function App(){return (div{ getArticleJSX() }/div)
}React的事件绑定
基础实现 React中的事件绑定通过语法 on 事件名称 { 事件处理程序 }整体上遵循驼峰命名法 function App(){const clickHandler (){console.log(button按钮点击了)}return (button onClick{clickHandler}click me/button)
}使用事件参数 在事件回调函数中设置形参e即可 function App(){const clickHandler (e){console.log(button按钮点击了, e)}return (button onClick{clickHandler}click me/button)
}传递自定义参数 语法事件绑定的位置改造成箭头函数的写法在执行clickHandler实际处理业务函数的时候传递实参 function App(){const clickHandler (name){console.log(button按钮点击了, name)}return (button onClick{()clickHandler(jack)}click me/button)
}注意不能直接写函数调用这里事件绑定需要一个函数引用
同时传递事件对象和自定义参数 语法在事件绑定的位置传递事件实参e和自定义参数clickHandler中声明形参注意顺序对应 function App(){const clickHandler (name,e){console.log(button按钮点击了, name,e)}return (button onClick{(e)clickHandler(jack,e)}click me/button)
}React组件基础使用
一个组件就是一个用户界面的一部分它可以有自己的逻辑和外观组件之间可以互相嵌套也可以服用多次
组件基础使用 在React中一个组件就是首字母大写的函数内部存放了组件的逻辑和视图UI, 渲染组件只需要把组件当成标签书写即可 // 1. 定义组件
function Button(){return buttonclick me/button
}
// 2. 使用组件
function App(){return (div{/*方式1 自闭和 */}Button/{/*方式2 成对标签 */}Button/Button/div)
}组件状态管理-useState
基础使用 1.useState 是一个 React Hook函数返回值是一个数组 2.数组中第一个参数是状态变量第二个参数是set函数用来修改状态变量 3.useState参数将作为count的初始值 和普通JS变量不同的是状态变量一旦发生变化组件的视图UI也会跟着变化数据驱动视图 import {useState} from react
function App() {const [ count, setCount ] useState(0)return (div classNameAppbutton onClick{()setCount(count1)}{ count }/button/div);
}状态的修改规则 在React中状态被认为是只读的我们应该始终替换它而不是修改它, 直接修改状态不能引发视图更新 修改对象状态 对于对象类型的状态变量应该始终给set方法一个全新的对象 来进行修改 import {useState} from react
function App() {const [form,setForm] useState({name:jack})const changeForm (){//错误写法直接修改 form.name john//正确写法setForm({...form,name:apple})}return (div classNameAppbutton onClick{changeForm}{ form.name }/button/div);
}
export default App;组件的基础样式处理 React组件基础的样式控制有俩种方式行内样式和class类名控制 div style{{ color:red}}this is div/div.foo{ //index.css的内容color: red;
}import ./index.css //导入css文件
function App(){return (divspan classNamefoothis is span/span/div)
}B站评论案例
渲染评论列表删除评论实现 删除显示------条件渲染删除功能------拿到当前项id以id为条件对评论列表做filter过滤 渲染导航Tab和高亮实现评论列表排序功能实现
完成版本 import { useState } from react
import ./App.scss
import avatar from ./images/bozai.png
import orderBy from lodash/orderBy/*** 评论列表的渲染和操作** 1. 根据状态渲染评论列表* 2. 删除评论*/// 评论列表数据
const defaultList [{// 评论idrpid: 3,// 用户信息user: {uid: 13258165,avatar: ,uname: 周杰伦,},// 评论内容content: 哎哟不错哦,// 评论时间ctime: 10-18 08:15,like: 88,},{rpid: 2,user: {uid: 36080105,avatar: ,uname: 许嵩,},content: 我寻你千百度 日出到迟暮,ctime: 11-13 11:29,like: 88,},{rpid: 1,user: {uid: 30009257,avatar,uname: 黑马前端,},content: 学前端就来黑马,ctime: 10-19 09:00,like: 66,},
]
// 当前登录用户信息
const user {// 用户iduid: 30009257,// 用户头像avatar,// 用户昵称uname: 黑马前端,
}/*** 导航 Tab 的渲染和操作** 1. 渲染导航 Tab 和高亮* 2. 评论列表排序* 最热 喜欢数量降序* 最新 创建时间降序*/// 导航 Tab 数组
const tabs [{ type: hot, text: 最热 },{ type: time, text: 最新 },
]const App () {// 导航 Tab 高亮的状态const [activeTab, setActiveTab] useState(hot)const [list, setList] useState(defaultList)// 删除评论const onDelete rpid {// 如果要删除数组中的元素需要调用 filter 方法并且一定要调用 setList 才能更新状态setList(list.filter(item item.rpid ! rpid))}// tab 高亮切换const onToggle type {setActiveTab(type)let newListif (type time) {// 按照时间降序排序// orderBy(对谁进行排序, 按照谁来排, 顺序)newList orderBy(list, ctime, desc)} else {// 按照喜欢数量降序排序newList orderBy(list, like, desc)}setList(newList)}return (div classNameapp{/* 导航 Tab */}div classNamereply-navigationul classNamenav-barli classNamenav-titlespan classNamenav-title-text评论/span{/* 评论数量 */}span classNametotal-reply{list.length}/span/lili classNamenav-sort{/* 高亮类名 active */}{tabs.map(item {return (divkey{item.type}className{item.type activeTab ? nav-item active : nav-item}onClick{() onToggle(item.type)}{item.text}/div)})}/li/ul/divdiv classNamereply-wrap{/* 发表评论 */}div classNamebox-normal{/* 当前用户头像 */}div classNamereply-box-avatardiv classNamebili-avatarimg classNamebili-avatar-img src{avatar} alt用户头像 //div/divdiv classNamereply-box-wrap{/* 评论框 */}textareaclassNamereply-box-textareaplaceholder发一条友善的评论/{/* 发布按钮 */}div classNamereply-box-senddiv classNamesend-text发布/div/div/div/div{/* 评论列表 */}div classNamereply-list{/* 评论项 */}{list.map(item {return (div key{item.rpid} classNamereply-item{/* 头像 */}div classNameroot-reply-avatardiv classNamebili-avatarimgclassNamebili-avatar-imgsrc{item.user.avatar}alt//div/divdiv classNamecontent-wrap{/* 用户名 */}div classNameuser-infodiv classNameuser-name{item.user.uname}/div/div{/* 评论内容 */}div classNameroot-replyspan classNamereply-content{item.content}/spandiv classNamereply-info{/* 评论时间 */}span classNamereply-time{item.ctime}/span{/* 评论数量 */}span classNamereply-time点赞数:{item.like}/span{user.uid item.user.uid (spanclassNamedelete-btnonClick{() onDelete(item.rpid)}删除/span)}/div/div/div/div)})}/div/div/div)
}export default AppReact表单控制
受控绑定 概念用React组件的状态useState控制input表单的状态 React(state) ----- state绑定到input 的value属性 ----- input(value)
React(state)----- 把input最新的value值设置给state ----- value
//通过value属性绑定react状态
//绑定onchange事件通过事件参数e拿到输入框最新的值反向修改到react状态
function App(){const [value, setValue] useState()return (input typetext value{value} onChange{e setValue(e.target.value)}/)
}获取DOM非受控绑定 useRef生成ref对象绑定到dom标签身上dom可用时ref.current获取dom (渲染完毕之后 dom生成之后才能用) import { useRef } from react;
function App() {const inputRef useRef(null)const showDom () {console.dir(inputRef.current)}return (div classNameAppinput typetext ref{inputRef}/ //绑定到dom标签身上button onClick{showDom} 获取DOM/button/div);
}
export default App;
}时间格式修改
npm install dayjs //插件安装import dayjs from dayjs;
function App() {const showDom () {console.log(dayjs(new Date()).format(MM-DD hh:mm));}
组件通信
父子通信-父传子
**实现步骤 **
父组件传递数据 - 在子组件标签上绑定属性子组件接收数据 - 子组件通过props参数接收数据
props是一个对象里面包含了父组件传递过来的所有数据
function Son(props){return div{ props.name }/div
}
function App(){const name this is app namereturn (divSon name{name}/ //父组件中使用子组件/div)
}特殊的prop-chilren 场景当我们把内容嵌套在组件的标签内部时组件会自动在名为children的prop属性中接收该内容 function Son(props){console.log(props)return div {props.children}/div
}
function App() {]return (divSonspanthis is span/span/Son/div)
}
export default App;父子通信-子传父 核心思路在子组件中调用父组件中的函数并传递实参 function Son({ onGetMsg }){ //解构const sonMsg this is son msgreturn (div{/* 在子组件中执行父组件传递过来的函数 */}button onClick{()onGetMsg(sonMsg)}send/button/div)
}
function App(){const getMsg (msg)console.log(msg)return (div{/* 传递父组件中的函数到子组件 */}Son onGetMsg{ getMsg }//div)
}兄弟组件通信 实现思路: 借助 状态提升 机制通过共同的父组件进行兄弟之间的数据传递 A组件先通过子传父的方式把数据传递给父组件App A — AppApp拿到数据之后通过父传子的方式再传递给B组件 App — B // 1. 通过子传父 A - App
// 2. 通过父传子 App - Bimport { useState } from reactfunction A ({ onGetAName }) {// Son组件中的数据const name this is A namereturn (divthis is A compnent,button onClick{() onGetAName(name)}send/button/div)
}function B ({ name }) {return (divthis is B compnent,{name}/div)
}function App () {const [name, setName] useState()const getAName (name) {setName(name)}return (divthis is AppA onGetAName{getAName} /B name{name} //div)
}export default Appcontext跨层组件通信
比如一个层级关系为APP(A(B)) ,想实现APP—B 的通信
实现步骤
使用 createContext方法创建一个上下文对象Ctx在顶层组件App中通过 Ctx.Provider 组件提供数据在底层组件B中通过 useContext 钩子函数获取消费数据
// App - A - Bimport { createContext, useContext } from react// 1. createContext方法创建一个上下文对象const MsgContext createContext()function A () {return (divthis is A componentB //div)
}function B () {// 3. 在底层组件 通过useContext钩子函数使用数据const msg useContext(MsgContext)return (divthis is B compnent,{msg}/div)
}function App () {const msg this is app msgreturn (div{/* 2. 在顶层组件 通过Provider组件提供数据 */}MsgContext.Provider value{msg}this is AppA //MsgContext.Provider/div)
}export default AppReact副作用管理-useEffect
useEffect是一个React Hook函数用于在React组件中创建不是由事件引起而是由渲染本身引起的操作比如发送AJAX请求更改DOM等等
基础使用 需求在组件渲染完毕之后立刻从服务端获取平道列表数据并显示到页面中 useEffect(() { } , [ ])说明 参数1是一个函数可以把它叫做副作用函数在函数内部可以放置要执行的操作 参数2是一个数组可选参依赖项数组不同依赖项会影响第一个参数函数的执行当是一个空数组的时候副作用函数只会在组件渲染完毕之后执行一次 接口地址http://geek.itheima.net/v1_0/channels
useEffect依赖说明
useEffect副作用函数的执行时机存在多种情况根据传入依赖项的不同会有不同的执行表现
依赖项副作用功函数的执行时机没有依赖项组件初始渲染执行一次 任意组件更新时执行空数组依赖只在初始渲染时执行一次添加特定依赖项组件初始渲染 依赖项变化时执行
清除副作用 概念在useEffect中编写的由渲染本身引起的对接组件外部的操作社区也经常把它叫做副作用操作比如在useEffect中开启了一个定时器我们想在组件卸载时把这个定时器再清理掉这个过程就是清理副作用 说明清除副作用的函数最常见的执行时机是在组件卸载时自动执行
useEffect(() {//实现副作用操作逻辑return(){//清除副作用逻辑}
},[])//例子在Son组件渲染时开启一个定时器卸载时清除这个定时器
import { useEffect, useState } from react
function Son () {// 1. 渲染时开启一个定时器useEffect(() {const timer setInterval(() {console.log(定时器执行中...)}, 1000)return () {// 清除副作用(组件卸载时)clearInterval(timer)}}, [])return divthis is son/div
}
function App () {// 通过条件渲染模拟组件卸载const [show, setShow] useState(true)return (div{show Son /} //条件渲染button onClick{() setShow(false)}卸载Son组件/button/div)
}export default App自定义Hook实现 概念自定义Hook是以 use打头的函数通过自定义Hook函数可以用来实现逻辑的封装和复用 // 封装自定义Hook// 问题: 布尔切换的逻辑 当前组件耦合在一起的 不方便复用// 解决思路: 自定义hookimport { useState } from reactfunction useToggle () {// 可复用的逻辑代码const [value, setValue] useState(true)const toggle () setValue(!value)// 哪些状态和回调函数需要在其他组件中使用 returnreturn {value,toggle}
}// 封装自定义hook通用思路// 1. 声明一个以use打头的函数
// 2. 在函数体内封装可复用的逻辑只要是可复用的逻辑
// 3. 把组件中用到的状态或者回调return出去以对象或者数组
// 4. 在哪个组件中要用到这个逻辑就执行这个函数解构出来状态和回调进行使用function App () {const { value, toggle } useToggle()return (div{value divthis is div/div}button onClick{toggle}toggle/button/div)
}export default AppReact Hooks使用规则
只能在组件中或者其他自定义Hook函数中调用只能在组件的顶层调用不能嵌套在if、for、其它的函数中