Appearance
第5章:页面与视图基础
1. 页面组件编写(基础页面结构、样式编写)
1.1 基础页面结构
页面组件:在 pages 目录下创建的 .vue 文件,每个页面组件对应一个路由。
基本结构:
vue
<template>
<div>
<h1>Page Title</h1>
<p>Page content</p>
</div>
</template>
<script setup>
// 组件逻辑
</script>
<style scoped>
/* 组件样式 */
</style>示例:
vue
<!-- pages/index.vue -->
<template>
<div class="home">
<h1>Welcome to Nuxt.js</h1>
<p>This is the home page</p>
<Button text="Click me" />
</div>
</template>
<script setup>
// 无需导入 Button 组件,自动导入
</script>
<style scoped>
.home {
padding: 20px;
max-width: 800px;
margin: 0 auto;
}
h1 {
color: #333;
font-size: 2rem;
}
p {
color: #666;
font-size: 1rem;
}
</style>1.2 样式编写
1.2.1 单文件组件样式
使用 <style scoped>:
vue
<template>
<div class="page">
<h1>Page Title</h1>
</div>
</template>
<style scoped>
.page {
padding: 20px;
}
h1 {
color: #333;
}
</style>使用 <style>:全局样式
vue
<template>
<div class="page">
<h1>Page Title</h1>
</div>
</template>
<style>
/* 全局样式 */
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
}
.page {
padding: 20px;
}
</style>1.2.2 CSS 预处理器
使用 SCSS:
安装依赖:
bashnpm install --save-dev sass使用 SCSS:
vue<template> <div class="page"> <h1>Page Title</h1> </div> </template> <style lang="scss" scoped> .page { padding: 20px; h1 { color: #333; font-size: 2rem; } } </style>
使用 Less:
安装依赖:
bashnpm install --save-dev less使用 Less:
vue<template> <div class="page"> <h1>Page Title</h1> </div> </template> <style lang="less" scoped> .page { padding: 20px; h1 { color: #333; font-size: 2rem; } } </style>
2. 组件自动导入与全局注册
2.1 组件自动导入
特性:在 components 目录下的组件会被自动导入,无需手动导入。
使用方法:
vue
<template>
<div>
<Button text="Click me" />
<Card title="Card Title">
Card content
</Card>
</div>
</template>
<script setup>
// 无需导入 Button 和 Card 组件
</script>2.2 组件目录结构
嵌套目录:组件可以放在 components 目录的子目录中,自动导入时会使用目录名作为组件名的前缀。
示例:
components/ui/Button.vue→ 组件名:UiButtoncomponents/form/Input.vue→ 组件名:FormInput
使用方法:
vue
<template>
<div>
<UiButton text="Click me" />
<FormInput v-model="inputValue" placeholder="Enter text" />
</div>
</template>
<script setup>
const inputValue = ref('')
</script>2.3 全局注册组件
在 plugins 目录下创建插件:
typescript
// plugins/global-components.ts
import { defineNuxtPlugin } from '#app'
import MyGlobalComponent from '../components/MyGlobalComponent.vue'
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.vueApp.component('MyGlobalComponent', MyGlobalComponent)
})使用方法:
vue
<template>
<div>
<MyGlobalComponent />
</div>
</template>
<script setup>
// 无需导入,全局可用
</script>3. 组件分层(页面组件、公共组件、业务组件拆分规范)
3.1 组件分层
3.1.1 页面组件
- 位置:
pages目录 - 作用:对应路由,负责页面布局和逻辑
- 特点:通常包含多个子组件,处理页面级别的状态和逻辑
示例:
vue
<!-- pages/products/index.vue -->
<template>
<div class="products-page">
<h1>Products</h1>
<ProductList :products="products" />
<Pagination :total="total" :page="page" @change="handlePageChange" />
</div>
</template>
<script setup>
const { data: products, pending, error } = useFetch('/api/products')
const { data: total } = useFetch('/api/products/count')
const page = ref(1)
function handlePageChange(newPage) {
page.value = newPage
}
</script>3.1.2 公共组件
- 位置:
components/ui或components/common目录 - 作用:可复用的 UI 组件,如按钮、输入框、卡片等
- 特点:独立、可复用、无业务逻辑
示例:
vue
<!-- components/ui/Button.vue -->
<template>
<button
class="btn"
:class="{ 'btn-primary': primary, 'btn-secondary': !primary }"
@click="$emit('click')"
>
<slot />
</button>
</template>
<script setup>
defineProps({
primary: {
type: Boolean,
default: false
}
})
defineEmits(['click'])
</script>
<style scoped>
.btn {
padding: 8px 16px;
border: none;
border-radius: 4px;
cursor: pointer;
}
.btn-primary {
background-color: #007bff;
color: white;
}
.btn-secondary {
background-color: #6c757d;
color: white;
}
</style>3.1.3 业务组件
- 位置:
components目录下按业务模块组织 - 作用:包含业务逻辑的组件
- 特点:与具体业务相关,可在多个页面中复用
示例:
vue
<!-- components/product/ProductCard.vue -->
<template>
<div class="product-card">
<img :src="product.image" :alt="product.name" />
<h3>{{ product.name }}</h3>
<p>{{ product.description }}</p>
<p class="price">${{ product.price }}</p>
<Button @click="addToCart">Add to Cart</Button>
</div>
</template>
<script setup>
defineProps({
product: {
type: Object,
required: true
}
})
defineEmits(['add-to-cart'])
function addToCart() {
$emit('add-to-cart', product)
}
</script>
<style scoped>
.product-card {
border: 1px solid #ddd;
border-radius: 8px;
padding: 16px;
margin-bottom: 16px;
}
.product-card img {
width: 100%;
height: 200px;
object-fit: cover;
border-radius: 4px;
}
.price {
font-weight: bold;
color: #007bff;
}
</style>4. 静态资源处理(图片、字体、样式文件存放规则与引用方式)
4.1 静态资源存放
public 目录:存放静态资源,如图片、字体、图标等。
目录结构:
public/
├── images/ # 图片
├── fonts/ # 字体
├── icons/ # 图标
└── favicon.ico # 网站图标4.2 引用静态资源
直接引用:
vue
<template>
<div>
<img src="/images/logo.png" alt="Logo" />
<link rel="stylesheet" href="/css/main.css" />
</div>
</template>在 CSS 中引用:
css
/* assets/css/main.css */
body {
background-image: url('/images/bg.jpg');
font-family: 'CustomFont', sans-serif;
}
@font-face {
font-family: 'CustomFont';
src: url('/fonts/custom-font.woff2') format('woff2');
font-weight: normal;
font-style: normal;
}4.3 资产目录
assets 目录:存放需要经过构建处理的资源,如 SCSS、Less 文件等。
目录结构:
assets/
├── css/ # 样式文件
├── scss/ # SCSS 文件
├── js/ # JavaScript 文件
└── images/ # 图片(会被构建处理)引用 assets 目录中的资源:
vue
<template>
<div>
<img src="~/assets/images/logo.png" alt="Logo" />
</div>
</template>
<script setup>
// 导入 assets 中的样式
import '~/assets/css/main.css'
</script>5. 元标签配置(useHead 钩子,自定义页面标题、描述、meta 标签)
5.1 基本用法
使用 useHead 钩子:
vue
<template>
<div>
<h1>Home Page</h1>
</div>
</template>
<script setup>
useHead({
title: 'Home Page - My Nuxt App',
meta: [
{ name: 'description', content: 'Welcome to my Nuxt.js application' },
{ name: 'keywords', content: 'nuxt, vue, javascript' }
],
link: [
{ rel: 'canonical', href: 'https://example.com' }
]
})
</script>5.2 动态元标签
使用响应式数据:
vue
<template>
<div>
<h1>{{ product.name }}</h1>
</div>
</template>
<script setup>
const route = useRoute()
const { data: product } = useFetch(`/api/products/${route.params.id}`)
useHead(() => ({
title: product.value ? `${product.value.name} - Product` : 'Loading...',
meta: [
{
name: 'description',
content: product.value ? product.value.description : 'Loading product...'
}
]
}))
</script>5.3 全局元标签配置
在 nuxt.config.ts 中配置:
typescript
export default defineNuxtConfig({
app: {
head: {
title: 'My Nuxt App',
meta: [
{ name: 'description', content: 'A Nuxt.js application' },
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' }
],
link: [
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
]
}
}
})5.4 布局中的元标签
在布局组件中使用 useHead:
vue
<!-- layouts/default.vue -->
<template>
<div>
<header>Header</header>
<main>
<slot />
</main>
<footer>Footer</footer>
</div>
</template>
<script setup>
useHead({
meta: [
{ name: 'author', content: 'John Doe' }
]
})
</script>小结
本章介绍了 Nuxt.js 的页面与视图基础,包括页面组件编写、组件自动导入、组件分层、静态资源处理和元标签配置。通过本章的学习,你应该已经掌握了如何创建和组织 Nuxt.js 页面和组件,以及如何处理静态资源和配置元标签。
在接下来的章节中,我们将学习 Nuxt.js 的数据获取与状态管理、布局与组件化开发等核心特性,帮助你更深入地理解和使用 Nuxt.js。
