前端框架React快速入门
本文需要一点点的前端相关基础,介绍了node的下载与安装,关于React的快速入门,非常适合想要速成的后端选手
文章目录
node 简介与安装
简介
- node.js是浏览器的 js 引擎
- 浏览器中有一个 js 引擎来解析 js 代码,只能解析 js 代码中的 ECMAScript,dom 和 bom 的解析依赖的是浏览器本身
- 将整个 js 引擎单独拿出来,就是 node
要让整这个引擎运行起来,有人将他做成了一个软件,安装在电脑上,js 代码就不用依赖浏览器运行了,在电脑的命令行也能运行 js 代码,这样 js 就能写后台了
下载安装
- 我们的电脑是没有自带 node 环境的
- 需要我们手动下载一个 node 安装包 ,安装node 环境
- 有了 node 环境以后,我们就可以运行 node 了
- 下载方式:
- 官网:https://nodejs.org/en
- 中文网:http://nodejs.cn(推荐)
下载
- 在 node 中文网下载的时候,选择安装包,不要选择 二进制文件
- 因为 二进制文件 是一个简单版,我们需要自己配置 环境变量 才可以使用
安装
- 下载好以后,我们直接把下载好的文件双击运行就行
- 找到
node-v10.16.2-x64.msi
对应的文件
- 总结:傻瓜式的点下一步就行了
检测安装环境
- 我们打开运行窗口 (win + r)
- 写入 cmd 然后按下回车,来到我们的命令行
- 然后再命令行写入一个指令:
node -v
- 然后按下回车,会得到一个 node 的版本号
- 能看到版本号表示 node 环境安装成功
配置 vscode(win10)
- 右击VSCode图标,选择
属性
,选择兼容性
,勾选以管理员身份运行此程序
,最后点击确定
2. vscode 中 调出终端
3. 输入命令:get-ExecutionPolicy
4. 输入命令:set-ExecutionPolicy RemoteSigned
5. 输入命令:get-ExecutionPolicy
Restricted
:表示禁止终端使用命令的RemoteSigned
:表示可以使用终端命令了
全局安装脚手架
React团队推荐使用create-react-app(相当于vue的vue-cli)来创建React新的单页应用项目,它提供了一个零配置的现代构建设置。
React脚手架(create-react-app)意义:
脚手架是官方提供,零配置,无需手动配置繁琐的工具即可使用
充分利用Webpack,Babel,ESLint等工具辅助项目开发
关注业务,而不是工具配置
- create-react-app会配置我们的开发环境,以便使我们能够使用最新的 JavaScript特性,
- 提供良好的开发体验,并为生产环境优化你的应用程序。
- 为了能够顺利的使用create-react-app脚手架,
我们需要在我们的机器上安装:- Node >= 8.10 和 npm >= 5.6。
- 在终端输入命令:
npm install -g create-react-app
- 这需要等待一段时间,这个过程在安装三个东西
react
: react的顶级库react-dom
: react在web段的运行环境react-scripts
: 包含运行和打包react应用程序的所有脚本及配置
创建项目
- 先创建一个放置项目的文件夹
www
- 在终端中使用
cd
指令跳转到这个文件夹 - 创建项目指令:
create-react-app your-app
(your-app是项目名,可以自己取)
- 出现下面的界面,表示创建项目成功:
- 通过
cd your-app
命令进入目录 - 运行
npm start
即可运行项目
自定义React空项目
- 上面创建的项目是一个例程项目,有自带的代码文件,若想编写自定义的React程序则需要先
删除src目录中的所有文件
,这样该项目就是一个空项目了 - 重新创建一个
index.js
文件
JSX 语法
JSX
是React
中使用的一种语法,其建立在JS
的基础之上,可以直接在JavaScript
中插入HTML
,极大方便了前端页面的构建。
如下图所示,APP函数直接返回了一个HTML的标签
:
React快速入门
例程
index.js
// 从 react 的包当中引入了 React。
//只要你要写 React.js 组件就必须引入React,
//因为react里有一种语法叫JSX,要写JSX,就必须引入React
import React from 'react'
//ReactDOM 可以帮助我们把 React 组件渲染到页面上去,
//没有其它的作用了。它是从 react-dom 中引入的,
//而不是从 react 引入。
import ReactDOM from 'react-dom'
//从APP.js中引入函数APP
import APP from './APP'
//通过构建DOM树
const root=ReactDOM.createRoot(
document.getElementById('root'))
root.render( //render 对根组件(DOM树)进行渲染
// <React.StrictMode></React.StrictMode> 该标签是
//React中一种标准的模式,用于排错,可以省略
<React.StrictMode>
<h1>欢迎进入React的世界</h1>
<APP />
</React.StrictMode>
//<APP /> 该标签用于调用APP.js中的APP函数
)
APP.js
//构建函数,该函数用于页面渲染
function APP()
{
const divContent="标题内容"
const divTitle="标题"
return(
<div title={divTitle}>{divContent}</div>
//{divContent}在标签div内容中的插值
//{divTitle}在标签div属性中的插值
)
//当返回多行内容时,return后面必须加()
//return 后面只能返回一个标签,若有多个标签要返回,
//需要在最外面套一个共同的父标签
//也可以采用下面两种方法:
//1.<></>在外面套一个空标签
//2.<Fragment></Fragment> 在外面套一个Fragment标签
}
export default APP;
map 循环遍历
render() {
const data = ['apple', 'banana', 'orange'];
const componentList = data.map((item, index) => {
return <Component key={index} data={item} />;
});
return (
<div>
{componentList}
</div>
);
}
在这个例子中,data
数组包含了三个水果名称,我们使用map()
方法遍历data
数组,并针对每个元素创建一个<Component>
组件,通过key
属性来唯一标识每个组件(下标index
标识),同时将当前元素作为data
属性传递给组件。最后,将生成的组件列表放在<div>
容器中进行渲染。
需要注意的是,使用
map()
方法时,需要给每个生成的元素指定一个唯一的key
属性,以便React能够准确地进行组件的识别和更新
事件
React 事件的命名采用小驼峰式(camelCase),而不是纯小写。如点击事件onClick
使用 JSX 语法时你需要传入一个函数作为事件处理函数,而不是一个字符串
function hello (e) { //事件函数
console.log("哈喽我是点击事件",e);
}
//e 中存放的是该事件的一些信息,如鼠标坐标
function A () {
return (
<div>
<button onClick={this.hello}>你好</button>
</div>
//onClick后面跟上事件对应的方法名
)}
React Hooks(钩子函数)
useState 状态处理
useState
设置出的变量,叫状态变量,该变量的改变会引起页面的自动刷新
//构建函数,该函数用于页面渲染
function APP()
{
const [content,setcontent]=useState("当前内容")
//设置状态变量,并设置其初始值,返回值为两个变量,
//一个用于读取,一个用于修改
//参数content用来读取该状态变量的当前值,参数setcontent
//用来修改值
function handle(e) //事件函数
{
setcontent("修改后的新内容");
//将setcontent对应的状态变量值进行修改
//修改方式:用传入的值来替换原来的值
//因此,若状态变量是一个对象,则修改时需要将所有成员
//变量都书写出来
//若成员变量太多,可以将对象展开
//展开的代码属性形式: `...读取状态变量值的参数名,`
//在这后面再对其中部分数据进行修改
//(重复声明的变量,后面值会覆盖前面值)
console.log("点击了按钮",e);
//e 中存放的是该事件的一些信息,如鼠标坐标
}
return(
<Fragment>
<div >{content}</div>
<button onClick={handle}>按钮</button>
</Fragment>
);
}
useContext逐层传递
CreateContext
设置出的变量,该变量能够逐层传递,从而由此可以改变每一层的Props(属性)
const levelContent=CreateContent(5)
//使用CreateContent()设置了一个Context变量,并为其设初值
//………………
const level=useContext(levelContent)
//获取对应Content变量的值,该值由上层组件中距离当前组件最近的
//`<MyContext.Provider>` 的 `value prop(属性)` 决定。
//若已经是最高层了,则对应的Context变量值由其初值决定
<levelContext.Provider value={level+1}>
…………
</levelContext.Provider>
useReducer统一管理
useReducer
是一个 React hooks,它允许你在组件中使用状态管理。useReducer
接受两个参数:一个函数作为计算状态的 reducer(状态管理函数
),以及初始状态(初始值)。reducer 函数接收 state(状态变量
) 和 action(对该状态变量进行什么操作
) 作为参数,并返回一个新的 state(状态变量
)。
useReducer
还提供了一个函数 useReducerPayload
,它可以直接在组件中获取由 action 传递的属性。
定义一个 reducer 函数,它接收 state
和 action
作为参数:
const counterReducer = (state = 0, action) => {
//action.type 表示对state状态变量操作的类型
switch (action.type) {
case 'INCREMENT':
return state + 1;
case 'DECREMENT':
return state - 1;
default:
return state;
}
};
在组件中使用 useReducer
和 useReducerPayload
:
const Counter = () => {
const [state, setState] = useReducer(counterReducer,0);
//useReducer()参数1是该状态变量对应的状态管理函数,
//参数2是状态变量的初始值
//返回值为 state 状态变量,setState 状态管理函数触发函数
const increment = () => {
setState({ type: 'INCREMENT' });
//传入操作类型
};
const decrement = () => {
setState({ type: 'DECREMENT' });
};
const getPayload = () => {
return state;
};
return (
<div>
<button onClick={increment}>Increment</button>
<button onClick={decrement}>Decrement</button>
<p>Counter: {getPayload()}</p>
</div>
);
};
在这个示例中,我们定义了一个简单的计数器组件,它使用了
useReducer
来管理状态。我们定义了一个名为counterReducer
的 reducer 函数,它根据 action 的类型来更新 state。然后,我们使用useReducer
获取 state 并将其传递给组件。我们还定义了两个函数increment
和decrement
,它们分别用于增加和减少计数。最后,我们使用useReducerPayload
函数直接获取 state,并在组件中显示它。
useRef获取状态
useRef
是一个 React hook,它允许你在函数组件中创建一个 ref。ref 是一个指向 DOM 元素的引用,你可以使用它来记录 DOM 元素的状态。ref 不会被渲染,所以它们不会出现在最终的 DOM 结构中。
在组件中使用 useRef
:
const Counter = () => {
const [state,setstate]=useState(2)
const count = useRef();
//设置一个叫count的ref
count.current=state;
//将当前状态变量的值赋值给count
const increment = () => {
state++;
};
const decrement = () => {
state--;
};
//最终结果是点击按钮,状态变量state不断在改变,但count的值
//不变,想要改变count的值需要操作count.current
return (
<div>
<button onClick={increment}>Increment</button>
<button onClick={decrement}>Decrement</button>
<p>Counter: {count.current}</p>
</div>
);
};
注意,useRef
仅在函数组件中有效
Ref不仅可以获取值,还可以获取标签:
const inputEl = useRef(null)
//设置Ref变量并与input标签关联
const handleFocus = () => {
inputEl.current.focus()
//获取input标签,并调用其focus()方法,使其获得焦点
//(即选中输入框)
}
return (
<p>
<input ref={inputEl} type="text" />
{/*将ref变量inputEl与该输入框关联*/}
<button onClick={handleFocus}>按钮</button>
</p>
)
Ref还可以获取一个组件:
如上图所示,组件APP
中有一个子组件Child
, 设置一个ref 变量childRef
与其关联,同时,子组件Child
函数需要使用forwardRef()
来处理,以方便子组件与Ref变量关联,这样在父组件中就可以通过操作childRef
来直接使用该子组件了
父组件还可以通过Ref变量
使用子组件中的部分方法
:
如上图所示,子组件可以通过参数ref
来接收与之关联的Ref变量
,通过useImperativeHandle()
来将其中的子组件方法提供给父组件使用。
- 参数1是与该组件关联的
Ref变量
- 参数2是一个函数,该函数返回值必须是一个对象,因此才会有
{}
的出现
下图是父组件App
使用子组件Child
中的方法myFn
:
useEffect 副作用函数
useEffect()
设置的函数可以在非用户触发时自动执行
,默认是在组件渲染开始时进行,每刷新页面一次,执行一次
useEffect()
:
-
参数1是要执行的函数
-
参数2是个数组,其中存放触发函数执行的变量(
变量改变,函数执行
),若数组为空,则没有变量能促发函数执行(页面刷新除外
),该参数可以缺省,缺省则页面刷新一次,执行一次
useMemo 数据缓存
如上图所示,通过useMemo可以将函数对应的返回值进行缓存。
- 参数1 函数,该函数的返回值会进行缓存,
result
中存放着函数的返回值 - 参数2 是个数组,
当其中对应的变量发生变化时,缓存中的值才会更新
,即函数会重新执行
useCallback函数缓存
如上图所示,Button
是一个子组件,传入的参数onClick
是一个函数,该组件通过memo()
变为了一个记忆组件,即只要传入的Props不变,子组件就不会重新执行
如上图所示,通过useCallback()
将对应函数进行缓存,只有当参数2([])
中的变量改变时,对应的函数才会重新执行。
展开语法
通过...参数名
可以将对象性质的变量展开
const value={
title:"标题",
content:"内容",
id:1
};
...value //将变量value展开
//
// 等价于(不再有大括号)
// title:"标题",
// content:"内容",
// id:1
组件间通信与插槽
React中组件分两种类型,一种是React DOM组件
,一种是React组件
。DOM组件
是指所有React支持的HTML和SVG标签,React组件
表示用户自定义标签。
React组件中的所有的标签属性统称为Props
,并通过Props
来管理。
DOM组件中CSS的写法
CSS中的标签类名属性class在React中要改为className
,以防止与js中的类class
重名。
return(
<Fragment>
<button
onClick={handle}
className="button"
style={{
width:200,
height:200,
backgroundColor:"red"
}}>
按钮
</button>
</Fragment>
//CSS中的类名class改为了className
//style属性中第一对{}为React中的插值功能,
//第二对{}及其中内容表明这是CSS属性,是CSS属性的常规写法
);
也可以采用展开语法,其效果与上述代码等价:
const imgData={
className:"button"
style:{
width:200,
height:200,
backgroundColor:"red"
}
}
return(
<Fragment>
<button
onClick={handle}
{...imgData}
>
按钮
</button>
</Fragment>
//{...imgData} 外面{}是插值语法,里面就是展开语法
);
自定义标签中的Props(属性)设置
如上图所示,自定义标签Article
传入的自定义的标签属性title
与content
,由props
来接收与管理。也可以直接设置参数来接收属性,而不用props
,如下图
在函数Article中设置了参数title,content
来接收对应的标签属性
自定义标签的属性多级传递
如上面所示,函数Article(自定义标签Article
)中又嵌套了一个子组件Detail
,当标签Article传入参数时,将子组件的属性单独封装一下(如 detailData
),将参数传入Article后,将子组件属性detailData
原封不动的传入子组件Detail
中,子组件Detail接收属性。
插槽
自定义组件不仅可以传递一些普通的自定义属性值,也可以直接传递JSX标签,这就叫插槽
。
如上图所示,自定义标签<List></List>
直接存在子标签<li></li>
,这些标签在函数List(自定义标签List
)中,用children来接收,其用来接收和管理该标签下的所有子标签
子组件向父组件传递
如上图所示,父组件App
中设置了一个事件函数handleActive()
,将该事件函数作为属性Props
传入子组件Detail
中,并在子组件中触发该事件。
更多推荐
所有评论(0)