很多人把“搭建网站”和“学编程”划上等号,认为必须啃完一本厚厚的编程书才有资格动手。这个认知偏差让大量有实际需求的人卡在起点。真相是,现代前端框架的设计初衷就是用组件化和声明式语法降低开发门槛。你不需要理解JavaScript原型链,也不需要手写复杂的DOM操作,只要跟着一条清晰的路径,用最小的必要知识就能把一个完整的网站跑起来。这篇文章要做的事,就是带你用React或Vue这两个主流框架,从空白文件夹开始,搭出一个包含首页、列表页、详情页和导航的多页面网站。

选React还是Vue:一张表终结选择困难

零基础阶段最怕在工具选择上反复横跳。直接给结论:如果你更喜欢写类似HTML的模板,希望上手曲线平缓,选Vue 3;如果你不排斥把结构和逻辑写在一起,且未来可能接触移动端开发,选React。两个框架都能完成今天的目标,我下面会分别给出两条完整路径。无论选哪个,你需要提前在电脑上安装Node.js 18或更高版本,这是运行所有前端工具链的基础环境。安装方式就是去Node.js官网下载LTS版本,一路点下一步,装完后在终端输入node -v确认版本号出现即可。

项目初始化:一个命令搞定脚手架

现代框架都提供了官方的项目脚手架工具,不需要手动配置Webpack或Vite。创建React项目使用Vite:打开终端,进入你想存放项目的文件夹,执行npm create vite@latest my-site -- --template react,然后cd my-site进入项目目录,执行npm install安装依赖。创建Vue项目同样用Vite:执行npm create vite@latest my-site -- --template vue,同样进入目录安装依赖。这两个命令会分别生成一个带有默认配置和示例代码的完整项目结构。src文件夹是你之后所有工作的主战场,里面的main.js是入口文件,App.js或App.vue是根组件。

理解组件思维:把页面拆成乐高积木

框架开发的核心不是写页面,而是写组件。一个网站最终由几十个小组件嵌套组合而成。零基础最容易上手的拆分方式是按视觉区块来:顶部导航栏是一个组件,底部版权信息是一个组件,首页的英雄区域是一个组件,文章列表是一个组件。每个组件就是一个独立的文件,里面包含这个区块需要的HTML结构、CSS样式和交互逻辑。这种拆分的好处是,你修改导航栏时完全不用担心影响到文章列表,每个组件都是一个独立的作用域。

React路径:从零写出第一个页面

打开React项目的src文件夹,删除App.css里的默认样式,清空App.jsx的内容,我们从头写。先建立组件文件夹结构:在src下创建components文件夹,里面新建Navbar.jsx、Footer.jsx、HomePage.jsx、ListPage.jsx、DetailPage.jsx五个文件。然后安装React Router来实现页面跳转:在终端执行npm install react-router-dom。

Navbar.jsx的内容如下,这是一个固定在顶部的导航栏组件,使用Link组件实现无刷新跳转:

import { Link } from 'react-router-dom'

function Navbar() {
  const navStyle = {
    display: 'flex',
    gap: '20px',
    padding: '16px 32px',
    background: '#1a1a2e',
    color: 'white',
    listStyle: 'none'
  }

  return (
    
  )
}

export default Navbar

HomePage.jsx是首页组件,展示一个简单的欢迎区域:

function HomePage() {
  return (
    

欢迎来到我的网站

这是一个用React搭建的完整网站示例

) } export default HomePage

ListPage.jsx展示文章列表,数据先用一个静态数组模拟,后续可以替换为真实API请求:

import { Link } from 'react-router-dom'

const articles = [
  { id: 1, title: '零基础学React的核心心法', summary: '掌握这三个概念就能上手' },
  { id: 2, title: 'Vue 3组合式API入门指南', summary: 'setup函数的正确打开方式' },
  { id: 3, title: '前端路由实现原理浅析', summary: '从hash到history的演进' }
]

function ListPage() {
  return (
    

文章列表

{articles.map(article => (

{article.title}

{article.summary}

))}
) } export default ListPage

DetailPage.jsx根据URL中的文章ID显示对应内容,这里用useParams获取动态参数:

import { useParams, Link } from 'react-router-dom'

const articles = [
  { id: 1, title: '零基础学React的核心心法', content: 'React的核心是组件、状态和单向数据流。组件让你把UI拆成独立可复用的单元,状态让组件拥有记忆,单向数据流保证了数据变化的可预测性。这三个概念掌握后,80%的业务场景都能应对。' },
  { id: 2, title: 'Vue 3组合式API入门指南', content: '组合式API的核心是setup函数,它在组件创建之前执行,让你可以用更灵活的方式组织逻辑。ref和reactive是定义响应式数据的两种方式,computed用于派生状态,watch用于监听变化。' },
  { id: 3, title: '前端路由实现原理浅析', content: '前端路由的本质是监听URL变化并匹配对应的组件渲染。Hash模式通过监听hashchange事件实现,History模式通过pushState和popstate事件实现,后者需要服务端配合处理404回退。' }
]

function DetailPage() {
  const { id } = useParams()
  const article = articles.find(a => a.id === parseInt(id))

  if (!article) return 
文章不存在
return (

{article.title}

{article.content}

← 返回列表
) } export default DetailPage

Footer.jsx是一个简单的底部组件:

function Footer() {
  return (
    

© 2025 我的网站. 保留所有权利.

) } export default Footer

最后修改App.jsx,用BrowserRouter和Routes配置路由表,把所有组件组装起来:

import { BrowserRouter, Routes, Route } from 'react-router-dom'
import Navbar from './components/Navbar'
import Footer from './components/Footer'
import HomePage from './components/HomePage'
import ListPage from './components/ListPage'
import DetailPage from './components/DetailPage'

function App() {
  return (
    
      
      
        } />
        } />
        } />
      
      
) } export default App

在终端执行npm run dev,浏览器打开显示的本地地址,你就能看到一个带有导航、首页、列表和详情页的完整网站。点击导航链接可以在页面间切换,点击文章标题会进入对应的详情页,URL也会同步变化。

Vue路径:用组合式API实现同样的功能

Vue项目的结构和React类似,在src下创建components文件夹,建立Navbar.vue、Footer.vue、HomePage.vue、ListPage.vue、DetailPage.vue五个文件。安装Vue Router:在终端执行npm install vue-router@4。

Navbar.vue使用router-link组件实现导航:

<template>
  <nav class="navbar">
    <router-link to="/">首页</router-link>
    <router-link to="/articles">文章列表</router-link>
  </nav>
</template>

<script setup>
</script>

<style scoped>
.navbar {
  display: flex;
  gap: 20px;
  padding: 16px 32px;
  background: #1a1a2e;
}
.navbar a {
  color: white;
  text-decoration: none;
}
</style>

HomePage.vue的内容:

<template>
  <div class="home">
    <h1>欢迎来到我的网站</h1>
    <p>这是一个用Vue搭建的完整网站示例</p>
  </div>
</template>

<script setup>
</script>

<style scoped>
.home {
  padding: 40px;
  text-align: center;
}
</style>

ListPage.vue用v-for指令渲染文章列表:

<template>
  <div class="list-page">
    <h2>文章列表</h2>
    <div v-for="article in articles" :key="article.id" class="article-card">
      <router-link :to="`/article/${article.id}`">
        <h3>{{ article.title }}</h3>
      </router-link>
      <p>{{ article.summary }}</p>
    </div>
  </div>
</template>

<script setup>
const articles = [
  { id: 1, title: '零基础学Vue的核心心法', summary: '掌握响应式数据和模板语法' },
  { id: 2, title: 'React Hooks入门指南', summary: 'useState和useEffect的配合使用' },
  { id: 3, title: '前端路由实现原理浅析', summary: '从hash到history的演进' }
]
</script>

<style scoped>
.list-page { padding: 40px; }
.article-card { margin: 20px 0; padding: 16px; border: 1px solid #eee; }
</style>

DetailPage.vue使用useRoute获取路由参数:

<template>
  <div class="detail" v-if="article">
    <h1>{{ article.title }}</h1>
    <p class="content">{{ article.content }}</p>
    <router-link to="/articles">← 返回列表</router-link>
  </div>
  <div v-else class="detail">文章不存在</div>
</template>

<script setup>
import { useRoute } from 'vue-router'
import { computed } from 'vue'

const route = useRoute()

const articles = [
  { id: 1, title: '零基础学Vue的核心心法', content: 'Vue的响应式系统是其灵魂。通过ref和reactive定义的变量会自动追踪依赖,当数据变化时视图自动更新。模板语法让你用类似HTML的方式绑定数据和事件,v-if控制显示隐藏,v-for处理列表渲染。' },
  { id: 2, title: 'React Hooks入门指南', content: 'Hooks让函数组件拥有了状态和生命周期能力。useState返回一个状态变量和更新函数,useEffect处理副作用如数据请求和DOM操作。自定义Hook可以将可复用逻辑抽离出来。' },
  { id: 3, title: '前端路由实现原理浅析', content: '前端路由的核心是URL变化时不向服务器发请求,而是由JavaScript接管处理。Vue Router和React Router都基于这个原理,通过监听URL变化匹配对应的组件进行渲染。' }
]

const article = computed(() => {
  return articles.find(a => a.id === parseInt(route.params.id))
})
</script>

<style scoped>
.detail { padding: 40px; max-width: 800px; margin: 0 auto; }
.content { line-height: 1.8; font-size: 16px; }
</style>

Footer.vue组件:

<template>
  <footer class="footer">
    <p>© 2025 我的网站. 保留所有权利.</p>
  </footer>
</template>

<script setup>
</script>

<style scoped>
.footer { text-align: center; padding: 20px; background: #f5f5f5; margin-top: 40px; }
</style>

接下来配置路由。在src下创建router文件夹,里面新建index.js:

import { createRouter, createWebHistory } from 'vue-router'
import HomePage from '../components/HomePage.vue'
import ListPage from '../components/ListPage.vue'
import DetailPage from '../components/DetailPage.vue'

const routes = [
  { path: '/', component: HomePage },
  { path: '/articles', component: ListPage },
  { path: '/article/:id', component: DetailPage }
]

const router = createRouter({
  history: createWebHistory(),
  routes
})

export default router

修改main.js,注册路由插件:

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'

const app = createApp(App)
app.use(router)
app.mount('#app')

最后修改App.vue,用router-view渲染匹配的页面组件:

<template>
  <Navbar />
  <router-view />
  <Footer />
</template>

<script setup>
import Navbar from './components/Navbar.vue'
import Footer from './components/Footer.vue'
</script>

执行npm run dev,Vue版本的完整网站也跑起来了。你会发现两个框架在实现同样功能时的代码结构高度相似:都是组件化拆分,都用路由库管理页面跳转,都用动态参数实现详情页的数据区分。

从静态到动态:接入真实数据的三种方案

上面用的是硬编码的静态数据,实际项目中数据通常来自后端接口。零基础阶段推荐三种渐进方案。第一种是使用公开的免费API,比如JSONPlaceholder这个测试服务,把ListPage里的静态数组替换为fetch请求,在useEffect或onMounted里调用接口获取数据存入状态变量。第二种是使用Headless CMS,比如Strapi或Contentful,它们提供可视化的内容管理后台和RESTful或GraphQL接口,你只需要在前端发请求拿数据渲染。第三种是使用静态站点生成器,比如VitePress或Astro,它们允许你用Markdown写内容,构建时生成静态HTML,适合博客和文档类网站。三种方案的学习成本依次递增,但都能让你摆脱硬编码数据。

部署上线:让全世界看到你的网站

网站开发完成后,本地地址只有你自己能访问。要让别人看到,需要把代码构建成静态文件并上传到服务器。两个框架都内置了构建命令:npm run build。执行后会在项目根目录生成一个dist文件夹,里面是所有优化压缩后的HTML、CSS和JavaScript文件。部署方案推荐使用Vercel或Netlify这类静态托管平台,它们提供免费额度,支持Git仓库自动部署。你只需要把项目推送到GitHub,在平台上关联仓库,每次推送代码就会自动构建并更新线上网站。整个过程不需要手动操作服务器,也不需要购买域名即可获得一个可访问的网址。

避坑指南:零基础最容易卡住的三个点

第一是Node版本问题。很多教程使用的命令在旧版本Node上无法运行,务必确保Node版本在18以上。第二是路径拼写错误。组件导入时文件名大小写必须完全一致,Windows系统不区分大小写但部署平台是Linux环境会区分,本地能跑线上报错往往就是这个原因。第三是路由配置的basename问题。如果把网站部署到子目录而非根目录,需要在创建路由实例时配置basename或history的base选项,否则所有路由匹配都会失效。这三个问题覆盖了零基础学习者80%的卡壳场景,提前知道就能少走很多弯路。

整个流程走下来你会发现,用框架搭网站的门槛已经被工具链降到极低。你不需要理解打包配置,不需要手写路由解析,甚至不需要深入理解框架原理。只要掌握了组件拆分、路由配置、数据渲染这三板斧,就能把一个功能完整的网站从零搭建到上线。后续的提升方向也很清晰:学习状态管理应对复杂数据流,学习CSS框架提高样式开发效率,学习接口对接让数据真正动态化。但那是之后的事了,现在你已经拥有了让一个网站跑起来的全部能力。