vue项目笔记2

5 阅读6分钟

export与import

js的模块机制核心是, 一个文件默认是一个“模块”,如果你不导出任何内容,其他文件就访问不到里面的内容。

这是为了 模块的封装性与安全性

在模块化系统中(比如 ES6 模块),每个 .js 文件都是一个作用域封闭的模块,里面定义的变量、函数、对象默认是私有的,外部看不到。

例如:

// math.js
const add = (a, b) => a + b;

如果没有export,别的文件就不能用这个 add

想要外部能用,就必须显式export:

// math.js
export const add = (a, b) => a + b;

然后在需要的文件中import:

// main.js
import { add } from './math.js';
console.log(add(2, 3)); // 5

你必须通过 export 把内容“显式地公开”,别人才能通过 import 使用,这就是模块之间的“通信规则”。

app.vue

在 Vue.js 项目中,App.vue 是项目的根组件,也就是整个应用程序的起点。它的主要作用可以概括为以下几点:

  1. 充当应用的根组件
  • 所有的子组件(页面组件、功能组件等)最终都会被嵌套在 App.vue 中。
  • App.vue 通常会被挂载到 index.html<div id="app"></div> 这个节点上
  1. 布局框架容器

App.vue 通常定义全局性的结构和样式,例如:

  • 顶部导航栏
  • 侧边栏
  • 页面整体布局(header、main、footer)
  • <router-view /><slot /> 的占位符,供子组件显示内容
  1. 引入全局资源

可以在 App.vue 中引入全局 CSS 文件、字体、图标库等:

<style>
@import './assets/global.css';
</style>

  1. 初始化数据或状态

可以在 App.vuemounted 生命周期钩子中初始化一些全局逻辑,例如:

  • 获取用户信息
  • 设置主题
  • 全局错误监听等
<template>
  <div id="app">
    <Navbar />
    <Sidebar />
    <router-view />
  </div>
</template>

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

<style>
/* 全局样式 */
#app {
  font-family: 'Arial', sans-serif;
}
</style>

App.vue 是 Vue 应用的“外壳”组件,负责包裹和管理整个项目的页面结构与逻辑入口。

如果你是用 Vite 创建的项目,它的入口通常是 main.jsmain.ts,里面会像这样使用 App.vue

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

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

项目实例中的app.vue文件

<script setup>
import {RouterView} from 'vue-router'
import {useAppStore} from "@/stores/AppSetting.js";
import zhCn from 'element-plus/es/locale/lang/zh-cn'

const appStore = useAppStore()
appStore.initThemeColor()

const font = reactive({
  color: 'rgba(0, 0, 0, .15)',
})


const locale = zhCn


</script>

<template>
  <el-config-provider :locale="locale">
      <RouterView/>
  </el-config-provider>

</template>

<style scoped>
@import './assets/styles/font.css';
</style>

  1. 根组件入口:
<template>
  <el-config-provider :locale="locale">//设置语言为中文
      <RouterView/>
  </el-config-provider>
</template>

  • <RouterView />:这里是 Vue Router 的出口,占位符,用于显示当前路由匹配的页面组件,即整个应用页面内容都会被渲染在这里。 当你访问

  • /,那么 <RouterView /> 会渲染:Home.vue

  • /about,那么 <RouterView /> 会渲染:About.vue <RouterView /> 会“占位”显示当前路由对应的组件,具体显示哪个组件,取决于当前浏览器地址栏的路径,和你在 Vue Router 中配置的 routes 一一对应。

  • 所有的页面组件都通过 RouterView 嵌套在 App.vue 中,体现了其作为“容器”的作用。

  1. 布局与全局结构
<el-config-provider :locale="locale">
  ...
</el-config-provider>

使用了 Element Plus 的 <el-config-provider> 来提供全局配置,这里设置了 中文语言包zhCn),会影响整个应用 Element UI 的默认文本(比如按钮、表格分页等的默认显示语言)。

  1. 引入全局资源与状态
import { useAppStore } from "@/stores/AppSetting.js";
const appStore = useAppStore()
appStore.initThemeColor()
  • 使用了 Pinia 状态管理useAppStore() 引入应用配置(比如主题颜色、水印开关等)。
  • initThemeColor() 表示在根组件初始化时,设置一次主题颜色,这是一种“全局初始化”的行为。
  1. 引入全局样式
<style scoped>
@import './assets/styles/font.css';
</style>

  • 引入了一个全局字体样式文件 font.css
  • 虽然使用了 scoped,但字体文件的效果(例如字体引入、通用字体类)通常仍然影响整个页面。
  • 虽然scoped本身会使效果只作用于当前组件,不能全局使用,但字体相关的规则(如 @font-facebody { font-family: ... }、全局类名 .my-font本质上是作用在全局作用域上的 CSS 规则,而不是组件内部的局部选择器。

所以,即使加了 scoped它们依然会影响整个页面

layout

通过router.js,可以看到路由配置首页为layout

在 Vue 项目中,layout 是一个页面的框架/壳,比如包含:

  • 顶部导航栏
  • 侧边菜单栏
  • 内容区域(真正渲染页面内容的地方)

这个 layout 通常作为首页 ('/') 的根组件,所有其他页面都是它里面的子页面。

  • / 页面渲染的是 Layout.vue + Home.vue 叠加的结果
  • Layout 是主框架,Home 是内容区域

layout:index.vue

  1. <template> 结构部分 —— 布局骨架
<template>
  <section class="main-layout" :class="collapseObj">
    <!-- 侧边栏 -->
    <SideBar v-if="['slide','mixin'].includes(appStore.layoutMode)"/>

    <!-- 主内容区域 -->
    <section class="main-container" :style="layoutStyle">

      <!-- 顶部导航栏区域 -->
      <section class="main-top" :class="{ 'fixed-header': true }">
        <NavBar/>
        <TagView/>
      </section>

      <!-- 页面主体内容(真正的页面组件由 <router-view> 渲染) -->
      <AppMain/>
    </section>
  </section>
</template>

结构分层说明:

位置组件说明
最外层.main-layout总框架容器,控制是否折叠侧边栏
左侧<SideBar />侧边导航栏(可折叠,控制菜单)
中间.main-container主内容区域(包含顶部和页面内容)
顶部<NavBar /> + <TagView />顶部菜单、标签页导航(类似标签切换)
下方<AppMain />实际页面内容,通过 <router-view /> 动态渲染

layout

sideBar

获取父组件传递来的值
const props = defineProps({
  mode: {
    type: String,
    default: 'vertical'
  }
})

从Layout父组件中获取mode

useRoute()获取路由对象
const currentRoute = useRoute();
  • useRoute():vue-router提供的组合式api,用来获取当前的路由对象,也就是你现在页面所在的路径参数元信息等。

例如:

假如你当前在 /user/123 页面,路由配置可能是这样:

{
  path: '/user/:id',
  component: UserPage
}

那么 useRoute() 获取的 currentRoute 就会是一个对象,里面包含:

currentRoute.path        // "/user/123"
currentRoute.params.id   // "123"
currentRoute.name        // 路由的名字(如果有命名)

你可以在组件内部根据当前路径判断菜单选中、权限、加载数据等等。

通过Pinia获取状态
const appStore = useAppStore();

这是通过 Pinia 提供的状态管理函数,用来访问全局共享状态
useAppStore 是你项目里自定义的 store 函数(通常在 stores/AppSetting.js 中定义),返回的是这个 store 的数据和方法。

Pinia 中的数据是响应式的,全局共享、自动同步
当你在一个组件中修改 store 的值,其他使用同一个 store 的组件都会自动感知并更新。

举例:

你可能在AppSetting.js里定义了这个store:

import { defineStore } from 'pinia';

export const useAppStore = defineStore('AppSetting', () => {
  // state:响应式数据
  const layoutMode = ref('slide');
  const sidebar = reactive({ opened: true });

  // actions:用于操作 state 的方法
  function toggleSidebar() {
    sidebar.opened = !sidebar.opened;
  }

  // return 暴露出去
  return {
    layoutMode,
    sidebar,
    toggleSidebar
  };
});

  • 其中"AppSetting"是唯一标识符,必须有,且不能和别的store重复
  • return用来“暴露”你想让外部组件访问的数据和方法,你 return 了什么,组件中用这个 store 时就能访问到什么。没有 return,就用不到。