说在最前面
由于本人并非Web前端高手,所以会以我的理解去讲述一些经验,若有差错还请您海涵,如果有哪里讲的不清楚的可以在群里提问!
框架介绍&准备
我熟悉的网站技术栈是Next.js,是一个基于React的更强大的框架,同时它们都基于运行环境Node.js;以及React的相关语法(如JSX)会在很多地方(比如Koishi的消息元素 h )有更加灵活和强大的应用!接下来教程将直接在Next.js中进行!
首先需要一台Windows/Mac/Linux电脑,然后我们安装Node.js,前往这里,下载完安装包打开后一路继续即可。
然后我们需要一款IDE(集成开发环境),这里我们选择VS Code,前往这里,下载完安装包打开后一路继续即可。
然后我们打开VS Code,看到以下界面:

选择打开,前往你的代码总文件夹(若没有就随意新建一个),然后在顶栏的终端中点击新建终端,然后我们需要切换镜像源,以获得更好的网络连接。我们输入并回车:
npm config set registry https://npm.aliyun.com
Hello World!
接下来新建Next.js项目。我们输入并替换其中内容:
npx create-next-app@latest 你喜欢的项目名称 --yes
然后回车,遇到Ok to proceed再回车一下。这里假设项目名称叫做my-app,然后我们在文件/打开文件夹中打开my-app文件夹:

然后启动开发模式,我们在终端输入并回车:
npm run dev
然后我们按住Ctrl(Mac中的Command键)然后左键Local的地址,即可在浏览器中打开网页:

如果显示这个界面,那表示Next.js的项目就启动成功了!在资源管理器中我们可以找到app文件夹,其中globals.css、layout.css与page.tsx,是代码的核心文件。接下来我们尝试自己写一个Hello World。
首先把globals.css除了@import "tailwindcss";都删除,然后把layout.tsx用以下内容替换:
import type { Metadata } from "next";
import "./globals.css";
export const metadata: Metadata = {
title: "Create Next App",
description: "Generated by create next app",
};
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en">
<body>
{children}
</body>
</html>
);
}
最后把page.tsx用以下内容替换:
export default function Home() {
return <div>Hello World!</div>;
}
记得所有文件需要使用Ctrl+S进行保存!由于Next.js具有热重载的特性,不需要重新编译,我们可以立刻在网页中查看到刚才保存的代码的效果:

基础讲解
在这里涉及到两个文件,一个是tsx,另一个是css。先从网站基础构成讲起:
一个网站是由内容、样式和脚本构成的,内容决定了网站组织的结构是什么,比如说网站中有导航栏,导航栏中包含标题和几个按钮;样式决定了网站长什么样,比如说导航栏始终处于页面的最上侧,按钮是蓝色的等等。内容通常放在*.html文件中,而样式通常放在*.css文件中。html是一种标记语言,用于记录结构的组合和嵌套,我们可以在刚才的网页中点击键盘上的F12:

中间这里就是html的代码,表示这个网站是怎么构成的。html是由元素(Element)或者叫标签构成的,每个元素都是一对用尖括号括起来的组合,比如说段落(Paragraph)就是
这是一个段落
,用开启的同时也需要用
去关闭标签。我们现在不用去关心具体的内容,了解这个概念即可。右边是css的内容。css是层叠样式表,它分为一个个的对象,每个对象表示一个类,包含了这个类具有哪些属性,比如说外边距为0,字体大小,当鼠标移动上去会有什么效果,甚至是动画等等。然后html会让css的类挂靠到html的某些元素当中,让他具有类中指定的特性。这里也不用了解每个属性的含义是什么,后面会详细讲解。

点击控制台中的源代码/来源,这里会有很多复杂的代码,这些就是Javascript代码,可以做到许多通过html和css做不到的内容,比如说在运行时根据条件渲染不同的内容,或者根据点击做出一些反应,都需要通过JS来实现。
回到正题,内容样式与脚本中有非常紧密的关联,但是这种古老的架构十分繁琐且难以写作,并且很难满足需求,所以网页框架就孕育而生了,比如说React,Vue.js等等。它们将网页的三大部分用非常简单的方式组合起来,便于写作并且具有更加强大的功能。对于React以及它的衍生框架(比如Next.js)来说,它将html和js的部分整合在了JSX(或者TSX)文件中,使得网页内容和逻辑控制更加紧密,并且允许使用Node.js的包管理器(npm)用来导入很多外部代码,使得工作更加便捷。
page.tsx是我们主要的页面内容,而layout.tsx则是套在page.tsx外的一层壳,比如说page.tsx会放一篇博客的正文,而layout.tsx可能是博客的导航栏和页脚。而layout.tsx中需要导入globals.css,表示全局的样式。这就是一个单页网站的基本结构。
JSX与TSX
前置知识:Javascript介绍,JSX就在JS代码中加入了类似html的结构,下面会具体讲解。
JSX元素
首先先引入一个概念,JSX元素。JSX元素是一种扩展的html,可以包含一切html元素(同样的,目前可以先不了解有哪些元素,不过可以记一下
是段落,是盒子),但是它要求最外层只能有一个元素,比如说:<div>
<p>段落1</p>
<p>段落2</p>
<p>段落3</p>
<p>段落4</p>
</div>
这样是可行的,但是下面这种就不可行,因为最外层包含了多个元素:
<div>
<p>段落1</p>
<p>段落2</p>
</div>
<div>
<p>段落3</p>
<p>段落4</p>
</div>
我们称这些
对于
是父元素,这个关系是相互的。原生的html元素都自带了嵌套渲染的逻辑:它符合直觉,在没有改变样式的情况下,它就是从内到外(指子元素和父元素的关系),从上到下(指这些子元素之间的关系)渲染的。
React赋予了我们强大的能力,可以去自定义元素,将一个自定义JSX元素像函数一样,像原生html元素一样使用。接下来会讲解如何自定义组件,以及如何指定子元素渲染逻辑的。
组件
首先刚才我们把layout的内容几乎清空了,所以说我们现在只用关注app/page.tsx。我们打开page.tsx:
export default function Home() {
return <div>Hello World!</div>;
}
在JSX的世界中,每一个用大写字母开头命名的函数且返回值是一个JSX元素都可以作为一个组件,比如这个函数Home就可以作为一个组件来使用,我们写(对于一个没有子元素渲染逻辑的组件,我们可以直接在同一个标签内开启且闭合,比如说可以写成),它会渲染一个Hello World。
那我们现在就可以区分原生html元素和自定义组件的区别了:原生html元素是以小写字母开头的(其实后面也都是小写字母),比如说
和
另外,我们可以在JSX里写js表达式,使用大括号括起来即可。比如说我们修改page.tsx为:
export default function Example() {
const a=5;
return <div>{a==5?"Yes":"No"}</div>;
}
我们可以看到它渲染了一个Yes。
那接下来说怎么渲染子元素,我们修改page.tsx为:
function Example({children}) {
const a=5;
return (
<div>
{a==5?"Yes":"No"}
{children}
</div>
);
}
此处函数接受一个参数,并将其children属性解构为对象children,写法就是{children}。此处不理解也没关系,知道就这样写即可。然后在返回值中放入children这个对象即可,比如说上面这个自定义组件Example返回了一个盒子(div)元素,里面会渲染一个表达式的值(Yes),在这个表达式下面渲染所有的子元素。比如说这样,我们在page.tsx的Example函数下面追加这一段:
export default function Main() {
return (
<Example>
<div>test</div>
</Example>
);
}
我们将它展开,是这样的一个结构:
<div>
{a==5?"Yes":"No"}
<div>test</div>
</div>
自定义组件的导出与导入
当项目规模逐渐扩大的时候,我们不能把所有代码全部塞在page.tsx中,以及我们知道还有多页面网站的需求,需要共享一些组件。所以在React(或者Next.js)当中,肯定也是支持多文件编程的。
在讲导入和导出之前先讲一下惯例上的自定义组件管理方法。我们一般把自定义组件放在根目录的components文件夹里,当然在components中也可以根据需求和喜好使用一些文件夹进行分组。结构大致如下:
app
├── favicon.ico
├── globals.css
├── layout.tsx
└── page.tsx
components
└── groupA
└── Example.tsx
然后比如说需要导入components/groupA/component1.tsx中的某个组件,它的路径写为@/components/groupA/component1,其中@的意思是根目录。
在React中,一个文件可以导出多个自定义组件。导出有两种形式,一种叫做默认(default)导出,另外一种叫做具名导出。对于一个文件,只能有一个默认导出,但是可以有很多具名导出。但是对于page.tsx,必须要有一个默认导出作为页面渲染的依据,但是别的文件就没有这个限制。
对于默认导出,在函数前面写export default即可,比如说上面的例子中就一直用的是默认导出:
export default function Example() {
const a=5;
return <div>{a==5?"Yes":"No"}</div>;
}
我们把上面这个组件放在components/example.tsx中,对于默认导出,如何导入呢?因为默认导出是一种匿名导出,我们在另一个组件中使用这个自定义组件可以不叫Example,实际上,React只认识这是一个默认导出,并不关心它的名字。比如说我们在page.tsx中需要使用这个Example组件,并且想称之为Component,可以这样写:
import Component from "@/components/example"
export default function Main() {
return (
<Component />
);
}
对于具名导出,直接写一个export即可。和默认导出相反,因为一个文件可以有多个具名导出组件,所以React是根据它的名字去寻找它的。比如说我们把example.tsx写成具名导出,然后我们再添加另一个具名导出组件:
// 一个文件中可以不止一个具名导出
export function Example() {
const a=5;
return <div>{a==5?"Yes":"No"}</div>;
}
export function Example1() {
return "Another Component"; // 一个字符串也可以作为JSX元素
}
在page.tsx中如果需要导入这两个组件,需要对导入的文件进行解构,我们可以这样写:
import { Example, Example1 } from "@/components/example"
export default function Main() {
return (
<div>
<Example />
<Example1 />
</div>
);
}
最后
到这里,我们就学会了现代框架React的基础:自定义组件以及导入导出,敬请期待下一篇杂谈

Comments NOTHING