react特点
- 声明式编码,通过一些行为替代,例如语法糖
- 组件化编码,提高开发效率及组件复用率,js是命令式编码,通过获取->操作等步骤
- React Native 编写原生应用
- 高效(优秀的Diffing算法),通过虚拟DOM和优秀的diff算法,尽量减少与真实DOM的交互
创建react项目
npm create-react-app myapp
创建完毕之后,根据需要删除文件以及组件代码,例如:
App.css、App.test.js、index.css、logo.svg、reportWebvitals.js、setupTests.js等文件
index.js
index.js:删除多与代码,仅保留如下代码:
importReactfrom'react'; importReactDOMfrom'react-dom'; importAppfrom'./App'; ReactDOM.render( <App/>, document.getElementById('root') );
app.js
改名为 app.jsx ,并修改代码为:
exportdefaultfunctionApp() { return ( <div className="App"> </div> ); }
配置路由文件
安装react-router-dom
npm install react-router-dom
基础使用
在app.jsx中
import React from 'react' import { Link, BrowserRouter, Route, Routes } from 'react-router-dom' import Home from './views/Home' import About from './views/About' export default function App() { return ( <BrowserRouter> <Link to="/home">Home</Link> <Link to="/about">About</Link> <Routes> <Route path='/home' element={<Home></Home>}></Route> <Route path='/about' element={<About></About>}></Route> </Routes> </BrowserRouter> ); }
(PS:这里有个小技巧,BrowserRouter需要在每一个页面中使用,所以可以在index.js中:
import React from 'react'; import ReactDOM from 'react-dom'; import App from './App'; import {BrowserRouter} from 'react-router-dom' ReactDOM.render( <BrowserRouter><App /></BrowserRouter>, document.getElementById('root') );
)
NavLink
<NavLink>是一种特殊的 <Link>,知道它是否“活跃”。 这在构建导航菜单(如面包屑或一组选项卡)时很有用,您希望在其中显示当前选择了哪些选项卡;
只需要将原来的Link变成NavLink即可
{/* NavLink 默认添加active,可以通过函数传递给className*/} <NavLink className={({ isActive }) => isActive ? 'now' : '' } to="/home">Home</NavLink> <NavLink className={({ isActive }) => isActive ? 'now' : '' } to="/about">About</NavLink>
重定向
引入Navigate,并修改以下代码
<Routes> <Route path="/about" element={<About></ About >} /> <Route path="/home" element={<Home></Home>} /> {/* 重定向,当匹配不到路由时重定向至home */} <Route path="*" element={<Navigate to="/home" replace={true} />} /> </Routes>
嵌套路由
index页面:
import React from 'react' import { NavLink, Outlet } from 'react-router-dom' export default function Home() { return ( <div> <NavLink to="/home/first">first</NavLink> | <NavLink to="/home/second">second</NavLink> {/* 嵌套路由出口 */} <Outlet></Outlet> </div> ) }
App.jsx页面:
export default function App() { return ( <div> <NavLink to="/home">Home</NavLink> <NavLink to="/about">About</NavLink> <Routes> <Route path='/home' element={<Home></Home>}> <Route path='/home/' element={<First></First>}></Route> {/* 在V6版本中允许相对路径写法 */} <Route path='second' element={<Second></Second>}></Route> </Route> <Route path='/about' element={<About></About>}></Route> <Route path="*" element={<Navigate to="/home" replace={true} />} /> </Routes> </div> ); }
useRoutes
useRoutes钩子在功能上等同于<Routes>,但它使用JavaScript对象而不是<Route>元素来定义路由。这些对象具有与普通<Route>元素相同的属性
在src中新建router/index.js:
import { Navigate } from 'react-router-dom' import Home from '../views/Home' import About from '../views/About' import First from '../views/Home/First' import Second from '../views/Home/Second' let routers = [ { path: '/home', element: <Home></Home>, children: [ { path: '/home/', element: <First></First>, }, { path: '/home/second', element: <Second></Second>, } ] }, { path: '/about', element: <About></About> }, { path: '*', element: <Navigate to="/home" replace={true} ></Navigate> } ] export default routers;
App.js:
import React from 'react' import { NavLink, useRoutes } from 'react-router-dom' import router from './router' import "./App.css" export default function App() { let routers = useRoutes(router) return ( <div> <NavLink to="/home">Home</NavLink> <NavLink to="/about">About</NavLink> {routers} </div> ); }
路由传参
params传参
配置路由
path: '/about/:id',
跳转
<NavLink to="/about/1">About</NavLink>
页面获取:
import React from 'react' import { useParams} from 'react-router-dom'; export default function About(props) { let { id } = useParams() console.log(id); return ( <div>About</div> ) }
search传参
跳转
<NavLink to="/about?id=1">About</NavLink>
获取
import React from 'react' import { useSearchParams } from 'react-router-dom'; export default function About(props) { let [search] = useSearchParams() let id = search.get('id'); return ( <div>About</div> ) }
state传参
跳转:
<NavLink to="/about" state={{ id: 1 }}>About</NavLink>
获取
import React from 'react' import {useLocation} from 'react-router-dom'; export default function About(props) { let {state:{id}} = useLocation() console.log(id); return ( <div>About</div> ) }
编程式路由
useNavigate钩子返回一个函数,允许您以编程方式进行导航
let navigate = useNavigate() function jump() { navigate('/about',{ replace: true, state: { id: 1 } }) }
导航函数有两个签名:
- 传递一个To值(与的类型相同)和一个可选的second {replace, state}
- 或在历史堆栈中传递你想要的增量。例如,navigate(-1)相当于点击后退按钮。
页面开发
创建虚拟dom
js方式
<body> <!-- 1.准备一个容器,做为作用域 --> <div id="test"></div> <!-- 引入js文件,注意顺序 --> <!-- 引入react核心库 --> <script src="https://unpkg.com/react@16/umd/react.development.js"></script> <!-- 引入用于支持react操作dom的扩展 --> <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script> <script> // 1.创建虚拟dom const VDOM = React.createElement('h1', { id: 'test', className: 'cla', onClick() { alert('hello') // 绑定事件 } }, 'hello') // 标签名,标签属性(class需要改为className),标签内容 // const VDOM = React.createElement('h1', { // id: 'ttt', // class: 'uuuu' // }, React.createElement('span', {}, 'hello')) // 多个标签嵌套的写法,繁琐,应该使用jsx // 2.渲染虚拟dom到页面 ReactDOM.render(VDOM, document.getElementById('test')) // 两个参数:虚拟dom,容器 </script> </body>
jsx方式
<body> <!-- 1.准备一个容器,做为作用域 --> <div id="test"></div> <!-- 引入js文件,注意顺序 --> <!-- 引入react核心库 --> <script src="https://unpkg.com/react@16/umd/react.development.js"></script> <!-- 引入用于支持react操作dom的扩展 --> <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script> <!-- 引入babel,用于将jsx转换成js --> <script src="../js/babel.min.js"></script> <script type="text/babel">// 表示这里面写的是jsx,通过babel进行编译,一定要写 // 1.创建虚拟dom // const VDOM = <h1>hello</h1> // 此处一定不要写引号,不是字符串,jsx的写法 const VDOM = (// 多层嵌套的写法,但需要babel翻译,翻译后的代码React.createElement('h1',{},React.createElement('span',{},'hello')) <h1> <span>hello</span> </h1> ) // 2.渲染虚拟dom到页面 ReactDOM.render(VDOM, document.getElementById('test'))// 两个参数:虚拟dom,容器 </script> </body>
数据请求
首先:安装axios :npm install axios;
然后:
axios({ url:'地址', params:{ } }).then((res)=>{ console.log(res.data) }).catch((error)=>{ console.log(error) })
变量定义
- state是组件对象最重要的属性, 值是对象(可以包含多个key-value的组合)
- 组件被称为"状态机", 通过更新组件的state来更新对应的页面显示(重新渲染组件)
- 用来给组件提供组件内部使用的数据
注意!!!
- 只有通过class创建的组件才具有状态
- 组件中render方法中的this为组件实例对象
- 组件自定义的方法中this为undefined,如何解决?
强制绑定this: 通过函数对象的bind()
箭头函数+赋值语句 - 状态数据,不能直接修改或更新,必须使用setState()
- 状态是私有的,完全由组件来控制
- 不要在 state 中添加 render() 方法中不需要的数据,会影响渲染性能!
可以将组件内部使用但是不渲染在视图中的内容,直接添加给 this - 不要在 render() 方法中调用 setState() 方法来修改state的值
但是可以通过 this.state.name = 'rose' 方式设置state(不推荐!!!!)
配置代理
在src中,新建setupProxy.js(必须是这个名字,react脚手架会识别),在文件中写以下配置内容(最近的项目要使用高版本这个,不然会导致项目无法启动):
http-proxy-middleware高版本(2以上):
const proxy = require('http-proxy-middleware')//引入http-proxy-middleware,react脚手架已经安装 module.exports = function(app){ app.use( proxy.createProxyMiddleware('/api',{ //遇见/api1前缀的请求,就会触发该代理配置 target:'http://localhost:5000', //请求转发给谁 changeOrigin:true,//控制服务器收到的请求头中Host的值 pathRewrite:{'^/api':''} //重写请求路径,下面有示例解释 }), proxy.createProxyMiddleware('/api2',{ target:'http://localhost:5001', changeOrigin:true, pathRewrite:{'^/api2':''} }), ) }
http-proxy-middleware低版本(2以下):
const proxy = require('http-proxy-middleware')//引入http-proxy-middleware,react脚手架已经安装 module.exports = function(app){ app.use( proxy('/api',{ //遇见/api1前缀的请求,就会触发该代理配置 target:'http://localhost:5000', //请求转发给谁 changeOrigin:true,//控制服务器收到的请求头中Host的值 pathRewrite:{'^/api':''} //重写请求路径,下面有示例解释 }), proxy('/api2',{ target:'http://localhost:5001', changeOrigin:true, pathRewrite:{'^/api2':''} }), ) }
写好以后,重启项目!!!
然后进行请求