React 基础中,我们都是用引包的方式,这里我们需要先搭建一个 React 脚手架。
所谓脚手架,说白了就是能够帮助你快速的来搭建一个环境,这样你就可以直接来开发东西了,它会给你一些最常用的功能,比如测试,发布,包括开发期间各种各样的一些工作。
首先,我们需要安装官方(fackbook)推出的 React 脚手架:
npm i -g create-react-app
然后创建一个项目:create-react-app react-demo
它现在就在帮我们装 react,react-dom,react-scripts。那么 react-scripts 是什么呢?
事实上来说,我们一般开发也用不着这个东西。它在这里的作用,就是把这个工程配置好了,打好包,供你直接下载就用,它的名字就叫 react-scripts。
换句话来说,create-react-app 其实只是一个外壳,它自己什么也没有。你真正需要这个项目的时候,它其实是帮助你从git官网上去下载 react-scripts,也就是它配好的项目。
顺便一说,React 它官网有自己的 node.js 包管理器 yarn。其实它官方是比较推荐用 yarn 来下载它的各种依赖的。
其实你用 yarn 和 npm 都行,它不是强制的。只不过它默认的情况下,它会用 yarn 给你下初期的这些包,所以你后期如果在拿 npm 去装东西的话,会导致包的结构混乱掉。
其实很简单,如果有这个情况发生,那么你就直接把原来它下载的 node_modules 全删了,然后拿 npm 重新下一遍,就可以避免这个问题了。
主要是因为 npm 和 yarn,它们的包结构不一样。
项目已经创建成功:
如果你的项目里面有 yarn.lock 这个文件,那么可以把它删掉,没啥用。它是在 yarn 安装东西的过程中,它自己创建的一个文件。
.git 是版本控制的文件,也可以删。因为它是直接从 git 上来克隆的,所以说会留下这个东西。
然后我们再来看下它的 package.json 文件:
它把所有的配置,其实都隐藏在了 react-scripts 里面,所以它的优点是比较干净。
而缺点,就是如果我想要去修改什么配置,是没有办法做到的。所以它有 eject 这样一个选项,就是弹出的意思。
eject 它其实可以把所有的配置以及模块都导出出来,这样的话,把东西都放到表面上,就便于我们去做自定义。
当然如果这些基本的足够你用了,就不用去做这个事了,不然你的工程会变得特别庞大,特别乱。
那么,我们来尝试下 npm run eject:
然后它会问你一些问题:
它说 TypeScript,Sass,CSS Modules 如果它们都拿出来了之后,就不能用了,你确定要这样吗?
我们选择 y,然后它就会安装一些东西。
因为以前都是归 react-scripts 管,现在归你管了,就需要一些东西来帮你。
然后现在再打开 package.json,就比较正常了:
那么让我们回到主题,路由这个东西到底是干什么的呢?
其实很简单,如果你是一个小项目,就1,2个页面,那么 if else 怎么做都行。但如果真的是一个很大的应用,那么如果你是通过自己去管理这些模块之间的关系,谁放上面,谁先出来,谁后出来,这将是一件很费劲的事。
所以路由这个东西,它的作用就是通过不同的地址,展现不同的组件,简化单页面应用的编写。
简单来说,就是帮助你来组织整个程序。就比如说你写了首页,登陆页,注册页,详情页等等很多页面,你都写完了之后,你自己不负责调用它们,你就把它们放在那,而是由路由来帮助你来调用这些东西。
在 react-router 中,与它相关的有四大组件:
1,react-router:它负责管理路由之间的关联,谁在前,谁在后,有没有参数之类的事情。
2,react-router-dom:react-router 的 DOM 绑定版,也就是网页中用的。
3,react-router-native:react-native 中用的。
4,react-router-config:它自己的相关配置。因为一般情况下,我们用 react-router-dom 的话,路由表是直接写在组件里面的。如果你希望把它抽离出来,让这个东西逻辑变得更清晰的话,你就可以用这个 react-router-config,它是一个专门帮助我们来静态去做配置的一个库。
略微了解之后,我们就先安装它:npm install react-router-dom -D
这里只装一个 react-router-dom 就可以了。
因为第一,我们是在 web 端来做,目前还没有触及 RN。
第二,你在装 react-router-dom 的时候,它会自己带上 react-router,不用你再去装一遍。
接下来,我们来看下它的使用:
react-router-dom 里面一共有三大对象:
首先它包括三个大组件:Router,Route,Link。
Router 组件主要是一个包裹。它包在所有路由的配置之外,它是最外层的。
Route 是路由的一个配置项。如果说 Router 是一个数组的话,那 Route 它就相当于数组里面的一个个元素。
Link 其实就是以前的 a 标签,它负责帮我们来跳转路由。当然,路由的跳转一般来说有两种方法,既可以用 js 来做跳转,也可以直接用Link,就看你需要。(Link 最终也会被编译成 a 标签。)
简单来说:
Router 是最外层的,它只负责包裹这个东西。
Route 就是用来配置那个路由,我对应的是哪个组件,它的路径是什么,等等一系列的东西。
Link 就是用来作为跳转的按钮。
而在 Router 里面,它还包含 BrowserRouter,HashRouter,MemoryRouter。这里我们只做一个介绍,下一篇博客会细讲。
BrowserRouter:基于 HTML5 的 historty API,直接以 path 形式呈现。需要注意的是,浏览器并未真正刷新,服务器也没有对应的地址,除非刷新,否则服务器也不会接到请求。所以它适合配合服务器。
HashRouter:基于 location.hash,页面不刷新。所以它是无法配合服务器使用的。
MemoryRouter:路由状态保存在内存,刷新页面会消失,所以它也无法配合服务器使用。
接下来就开始撸码了,我们先把 src 目录里面原先东西清除掉,写上我们自己的 demo:
我们一般将 Router 这个东西放到 index.js 里面。因为 App 就是在 index.js 里面来进行声明和初始化的。
那么我如果想包住整个程序,那我是不是只用把 App 包住就可以了?
首先,BrowserRouter 从名字就可以看出来,它是给浏览器用的 Router。
然后我个人一般习惯于起个别名,就叫做 Router。为什么呢?
因为我们有的时候,是需要更换这个路由的。比如我现在不想用 BrowserRouter 了,我要换成 HashRouter 了,那我这时候就可以直接换,我底下所有的东西都不用改。
可以看到,这样就很方便。
然后重点的路由逻辑就放到 App.js 里面。
那么既然我们在这里要写详细的路由信息了,我们就需要另外的两个东西:
那么接下来,路由到底怎么写?
路由,它其实对应的是组件。
也就是说,如果你真想做路由的话,至少先得准备几个组件。
我们在 src 目录下创建一个新的目录 components,并在里面创建 3 个组件:
接下来,我们就需要在 App.js 里面来声明路由的关系。
在 <Route /> 里面,至少需要两个东西:
一个是 path,就是你的这个路由节点,它的路径是什么。
另一个是 component,就是当你碰到这个路径的时候,你要找的是哪个组件。
但是现在还没有完,还有一个小问题,就是路由它实际上来说,是能够去兼容匹配的。什么意思呢?
比如说我现在路由的路径是 /course,那么 path="/course" 肯定是会被识别到的,但是 path="/" 也能。为什么呢?
因为你的 /course 里面包括了 /,也就是说,所有的在我下面的,都包括。
比如,我现在的路径是 "/course/2",但是实际上它能激活三个路由:
因为它们前面都是相同的。路由只要从左边开始能匹配到我,那就可以了。
所以为了避免这种问题,怎么办呢?我们可以加一个 exact。
exact 翻译过来就是精确的意思。
说白了,这个时候,你的路径必须得跟我的一模一样。加个 exact 就是精确匹配。
然后现在我们还少一点东西,目前我们现在还没有办法去跳转。
因为我们真正跳转是需要 Link 的:
Link 也需要2个东西:
首先,你得在标签里面来一些文字,然后还要有个 to,就是去到哪个地址。
这时候就可以看到,页面上有三个 a 链接,所以 Link 实际上编译出来就是 a 标签。
所以路由这个东西,实际上就是不同的地址,给你匹配不同的组件而已。