从0开始搭建Vue博客——ch1前端初始化

223 阅读3分钟

我们已经学习过了vue的基础语法,也有了一点点的项目经验,下面要尝试自己搭建一个vue博客啦。

项目环境

在开始之前,先来了解一下这个项目依赖的环境。
最基础的工具有npm、nodejs、nvm(切换node的工具,不是必须但很方便)
vue当然不必多说,除了vue外,还需要vite
根据官方文档可知,vite是一种快速的新型的前端构建工具,性能好效率高,也是vue3推荐的构建工具。具体实现原理暂时看不懂,但是我们知道相比于Vue CLI3内置的npm run serve命令,vite提供的npm run dev要快上不少。
vite的安装也很简单,执行npm install vite -g即可。安装完vite再创建vue项目,就会默认捆绑vue了。

项目创建

做项目的第一步当然是初始化! 在终端中打开想要创建项目的文件夹,然后npm init vue就可以创建我们要的项目了(也可以使用npm init vite@latest 项目名 -- --template vue)。
然后根据需要选择需要的库。我这里选了使用ts、eslint和prettier。其他的库等用到再安装。
接着进入我们的项目文件夹,npm install安装运行web应用所需要的库。
最后就可以通过npm run dev命令运行项目啦!(默认端口是5173)
需要注意的是,vite要求node的版本要>=18,否则会报错TypeError: crypto$2.getRandomValues is not a function,我就遇到了,用nvm把node版本改成20才解决。
image.png

项目结构

先来大致看一下整个项目的基本结构

vueblog
├─ .editorconfig // 项目编码规范
├─ .prettierrc.json
├─ eslint.config.ts
├─ tsconfig.json // ts配置文件
├─ env.d.ts
├─ tsconfig.app.json
├─ tsconfig.node.json
├─ package.json // 项目依赖和脚本配置
├─ package-lock.json // 锁定安装时的npm包版本号
├─ README.md // 项目文档
├─ index.html  // 项目入口文件
├─ public // 存放静态资源的目录
│  └─ favicon.ico
├─ src // 源码目录
│  ├─ App.vue // vue根组件
│  ├─ assets // 美术资源目录
│  │  ├─ base.css
│  │  ├─ logo.svg
│  │  └─ main.css
│  ├─ components //组件目录
│  │  ├─ HelloWorld.vue
│  │  ├─ icons
│  │  │  ├─ IconCommunity.vue
│  │  │  ├─ IconDocumentation.vue
│  │  │  ├─ IconEcosystem.vue
│  │  │  ├─ IconSupport.vue
│  │  │  └─ IconTooling.vue
│  │  ├─ TheWelcome.vue
│  │  └─ WelcomeItem.vue
│  └─ main.ts // node应用入口文件
└─ vite.config.ts // vite配置文件

下面来具体分析几个重要的文件

package.json

{
  "name": "vueblog", // 项目名称
  "version": "0.0.0", // 项目版本
  "private": true, // 是否公开
  "type": "module", // 采用ESModule规范
  "scripts": { // 脚本命令
    "dev": "vite",
    "build": "run-p type-check \"build-only {@}\" --",
    "preview": "vite preview",
    "build-only": "vite build",
    "type-check": "vue-tsc --build",
    "lint": "eslint . --fix",
    "format": "prettier --write src/"
  },
  "dependencies": { // 开发时依赖的包和版本
    "vue": "^3.5.13"
  },
  "devDependencies": { // 生产环境中依赖的包和版本
    "@tsconfig/node22": "^22.0.0",
    "@types/node": "^22.13.1",
    "@vitejs/plugin-vue": "^5.2.1",
    "@vue/eslint-config-prettier": "^10.1.0",
    "@vue/eslint-config-typescript": "^14.3.0",
    "@vue/tsconfig": "^0.7.0",
    "eslint": "^9.18.0",
    "eslint-plugin-vue": "^9.32.0",
    "jiti": "^2.4.2",
    "npm-run-all2": "^7.0.2",
    "prettier": "^3.4.2",
    "typescript": "~5.7.3",
    "vite": "^6.0.11",
    "vite-plugin-vue-devtools": "^7.7.1",
    "vue-tsc": "^2.2.0"
  }
}

index.html

index.html是整个项目的入口文件,负责加载整个应用。浏览器访问vue项目时,实际上时访问的index.html,通过这个文件,浏览器找到并加载vue应用的其他组件和资源。

<!DOCTYPE html>
<html lang="">
  <head>
    <meta charset="UTF-8">
    <link rel="icon" href="/favicon.ico">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Vite App</title>
  </head>
  <body>
    <!-- vue根实例的挂载点 -->
    <div id="app"></div>
    <!-- 引入main.ts文件作为node应用入口 -->
    <script type="module" src="/src/main.ts"></script>
  </body>
</html>

main.ts

正常来说应该是js文件,但是我们使用的ts规范,所以后缀就是ts。
main.ts项目入口的ts文件,引入所需要的组件并创建vue实例,再挂载到id为app的html元素中(正是index.html里那个)。也可以在其中设置vue应用的全局变量、路由等。

import './assets/main.css'

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

createApp(App).mount('#app')

App.vue

这个我们就很熟悉了,vue项目的根组件嘛,它是整个vue应用的骨架。所有的页面都是在这个组件下进行切换的,所有的路由都是这个组件的子组件。id是app,接管index.html中div要渲染的内容。

// js脚本
<script setup lang="ts">
import HelloWorld from './components/HelloWorld.vue'
import TheWelcome from './components/TheWelcome.vue'
</script>

// html页面
<template>
  <header>
    <img alt="Vue logo" class="logo" src="./assets/logo.svg" width="125" height="125" />

    <div class="wrapper">
      <HelloWorld msg="You did it!" />
    </div>
  </header>

  <main>
    <TheWelcome />
  </main>
</template>

// css样式
<style scoped>
header {
  line-height: 1.5;
}

.logo {
  display: block;
  margin: 0 auto 2rem;
}

@media (min-width: 1024px) {
  header {
    display: flex;
    place-items: center;
    padding-right: calc(var(--section-gap) / 2);
  }

  .logo {
    margin: 0 2rem 0 0;
  }

  header .wrapper {
    display: flex;
    place-items: flex-start;
    flex-wrap: wrap;
  }
}
</style>