本文详细介绍了如何从零开始使用Vue3框架进行开发,包括安装步骤、创建首个Vue3项目以及基础组件的使用。文中还探讨了Vue3的数据绑定、状态管理以及路由配置,并通过实战案例展示了如何打造一个个人博客网站。
Vue3入门教程:从零开始学习Vue3框架 Vue3简介与安装什么是Vue3
Vue是一个用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue被设计为可以自底向上逐层按需集成。Vue的开发目标是通过尽可能简单的API实现响应的数据绑定和组合的视图组件。Vue3是Vue的最新版本,它对性能、API和开发体验进行了重大改进。
安装Vue3
要开始使用Vue3,首先需要安装Node.js。Node.js是一个基于Chrome V8引擎的JavaScript运行环境,它使得直接在服务器端也能运行JavaScript代码。安装Node.js后,可以通过npm(Node.js的包管理器)安装Vue CLI,它是Vue的一个命令行工具,用于快速搭建Vue项目。
- 安装Node.js(如果尚未安装):
# 下载安装包
wget https://nodejs.org/dist/v14.17.0/node-v14.17.0-linux-x64.tar.xz
# 解压
tar xf node-v14.17.0-linux-x64.tar.xz
# 进入解压后的目录
cd node-v14.17.0-linux-x64
# 将解压后的bin目录添加到环境变量
export PATH=$PATH:/path/to/unpacked/node-v14.17.0-linux-x64/bin
- 安装Vue CLI:
npm install -g @vue/cli
- 使用Vue CLI创建Vue项目:
vue create my-vue3-project
在选择预设时,可以通过以下命令来指定使用Vue3:
vue create --defaultPreferCjs my-vue3-project
此命令用于创建一个使用CJS(CommonJS)模块系统的Vue项目,CJS模块系统是Vue3默认使用的模块系统。通过这种方式,可以直接指定使用Vue3。
创建第一个Vue3项目
接下来,我们将使用Vue CLI创建一个新的Vue3项目,并在项目中添加一些基本的代码。
- 创建项目:
vue create my-vue3-project
选择“Manually select features”选项,取消选择“Router”、“Vuex”、“CSS Pre-processors”和“Linter / Formatter”,然后选择“Vue 3”。
- 进入项目目录并启动开发服务器:
cd my-vue3-project
npm run serve
- 在项目中添加一些基本代码。首先,打开
src/App.vue
文件,这是Vue项目的入口组件。
<template>
<div id="app">
<img alt="Vue logo" class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="./assets/logo.png">
<HelloWorld msg="Hello Vue 3 + Vite" />
</div>
</template>
<script setup>
import HelloWorld from './components/HelloWorld.vue'
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
- 在
src/components/HelloWorld.vue
中添加一个简单的组件:
<template>
<div class="hello">
<h1>{{ msg }}</h1>
</div>
</template>
<script setup>
defineProps({
msg: {
type: String,
required: true
}
})
</script>
<style scoped>
.hello {
text-align: center;
margin-top: 40px;
}
</style>
现在,你可以访问http://localhost:8080
来查看你的第一个Vue3项目。
组件的基本结构
组件是Vue应用的基本构建块。每个组件都有自己的视图模板、逻辑和数据模型。在Vue中,组件的定义通常包含三个主要部分:模板(template)、脚本(script)和样式(style)。以下是一个简单的组件结构:
<template>
<div>
<h1>{{ title }}</h1>
<p>{{ message }}</p>
</div>
</template>
<script>
import { ref } from 'vue';
export default {
name: 'MyComponent',
setup() {
const title = ref('Hello, Vue3');
const message = ref('This is a simple component');
return {
title,
message
};
}
};
</script>
<style scoped>
h1 {
color: #343a40;
font-size: 1.5em;
}
p {
color: #6c757d;
font-size: 1em;
}
</style>
Props和Events的使用
Props(属性)允许你将数据从父组件传入子组件。Events(事件)允许子组件向父组件传递消息。以下是一个使用Props和Events的简单示例:
- 在父组件中定义Props和Events:
<template>
<div>
<child-component :message="parentMessage" @child-event="handleChildEvent" />
</div>
</template>
<script>
import { ref } from 'vue';
import ChildComponent from './ChildComponent.vue';
export default {
components: {
ChildComponent
},
setup() {
const parentMessage = ref('Hello from Parent');
const handleChildEvent = (msg) => {
console.log('Message from child:', msg);
};
return {
parentMessage,
handleChildEvent
};
}
};
</script>
- 在子组件中使用Props和触发Events:
<template>
<div>
<p>{{ message }}</p>
<button @click="sendMessage">Send Message to Parent</button>
</div>
</template>
<script>
import { ref, defineProps, defineEmits } from 'vue';
export default {
props: {
message: {
type: String,
required: true
}
},
emits: ['child-event'],
setup(props, { emit }) {
const sendMessage = () => {
emit('child-event', 'Hello from Child');
};
return { sendMessage };
}
};
</script>
插槽(Slots)的应用
插槽允许你将父组件的内容注入到子组件的特定位置。以下是一个使用默认插槽和具名插槽的简单示例:
- 定义一个带有插槽的子组件:
<template>
<div>
<header>
<slot name="header">Default Header</slot>
</header>
<main>
<slot>Default Content</slot>
</main>
<footer>
<slot name="footer">Default Footer</slot>
</footer>
</div>
</template>
<script>
export default {
name: 'SlotComponent'
};
</script>
- 在父组件中使用插槽:
<template>
<div>
<slot-component>
<template v-slot:header>
<h1>Custom Header</h1>
</template>
<p>This is custom content</p>
<template v-slot:footer>
<p>Custom Footer</p>
</template>
</slot-component>
</div>
</template>
<script>
import SlotComponent from './SlotComponent.vue';
export default {
components: {
SlotComponent
}
};
</script>
组件组合示例
为了展示如何将组件组合成更复杂的视图,假设我们有一个博客应用,它包含一个主页和文章详情页。主页展示文章列表,点击文章标题可以跳转到文章详情页。
- 主页组件(
Home.vue
):
<template>
<div>
<h1>Blog Posts</h1>
<ul>
<li v-for="post in posts" :key="post.id">
<router-link :to="`/post/${post.id}`">{{ post.title }}</router-link>
<p>{{ post.summary }}</p>
</li>
</ul>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue';
import { useRouter } from 'vue-router';
const router = useRouter();
const posts = ref([]);
onMounted(() => {
fetchPosts();
});
const fetchPosts = async () => {
const response = await fetch('/api/posts');
const data = await response.json();
posts.value = data;
};
</script>
<style scoped>
ul {
list-style-type: none;
padding: 0;
}
li {
margin: 10px 0;
}
</style>
- 文章详情组件(
PostDetail.vue
):
<template>
<div>
<h1>{{ post.title }}</h1>
<p>{{ post.content }}</p>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue';
import { useRoute } from 'vue-router';
const post = ref({});
const route = useRoute();
onMounted(() => {
fetchPost();
});
const fetchPost = async () => {
const { id } = route.params;
const response = await fetch(`/api/posts/${id}`);
const data = await response.json();
post.value = data;
};
</script>
<style scoped>
h1 {
color: #343a40;
font-size: 1.5em;
}
p {
color: #6c757d;
font-size: 1em;
}
</style>
- 路由定义(
router/index.js
):
import { createRouter, createWebHistory } from 'vue-router';
import Home from './views/Home.vue';
import PostDetail from './views/PostDetail.vue';
const routes = [
{ path: '/', component: Home },
{ path: '/post/:id', component: PostDetail }
];
const router = createRouter({
history: createWebHistory(),
routes
});
export default router;
Vue3数据绑定与指令
模板语法
模板语法是Vue的视图层描述语言。通过模板语法,你可以方便地将DOM绑定到Vue实例的数据层上。以下是一些常见的模板语法示例:
- 插值(Interpolation):
<p>{{ message }}</p>
- 指令(Directives):
<div v-if="flag"></div>
<div v-for="item in items" :key="item.id">{{ item.name }}</div>
- 事件绑定(Event Handling):
<button @click="increment">Click me</button>
v-bind与v-model的使用
v-bind
用于绑定元素属性,而v-model
用于双向数据绑定。以下是一些具体的示例:
- 使用
v-bind
绑定属性:
<template>
<div>
<img v-bind:class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="imageSrc" alt="Image" />
</div>
</template>
<script>
import { ref } from 'vue';
export default {
setup() {
const imageSrc = ref('https://example.com/image.jpg');
return { imageSrc };
}
};
</script>
- 使用
v-model
进行双向绑定:
<template>
<div>
<input v-model="message" type="text" placeholder="Type something..." />
<p>{{ message }}</p>
</div>
</template>
<script>
import { ref } from 'vue';
export default {
setup() {
const message = ref('');
return { message };
}
};
</script>
<script setup>
import { ref } from 'vue';
const message = ref('');
// 当输入框中的值变化时,绑定的变量会自动更新
message.value = 'Hello, Vue 3';
</script>
自定义指令
自定义指令允许你在DOM元素上添加自定义行为。以下是一个简单的自定义指令示例:
- 定义自定义指令:
import { createApp } from 'vue';
const app = createApp(App);
app.directive('focus', {
mounted(el) {
el.focus();
}
});
- 在模板中使用自定义指令:
<template>
<div>
<input v-focus type="text" placeholder="Get focus" />
</div>
</template>
Vue3状态管理
使用Composition API管理状态
Composition API是Vue3中新增的API,它提供了更灵活的状态管理方式。以下是一个使用Composition API管理状态的简单示例:
<template>
<div>
<p>{{ count }}</p>
<button @click="increment">Increment</button>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue';
const count = ref(0);
const increment = () => {
count.value++;
};
onMounted(() => {
console.log('Component is mounted');
});
</script>
响应式原理简介
Vue的响应式系统基于其内部的依赖追踪系统。当数据发生变化时,Vue会自动更新受影响的视图部分。以下是一个使用响应式API的简单示例:
import { reactive, watch } from 'vue';
const state = reactive({
count: 0
});
watch(() => state.count, (newValue, oldValue) => {
console.log(`Count changed from ${oldValue} to ${newValue}`);
});
setInterval(() => {
state.count++;
}, 1000);
使用Vuex进行全局状态管理
Vuex是一个集中式状态管理库,适用于Vue应用程序。它可以帮助你更好地管理和共享状态。以下是一个使用Vuex的基本示例:
- 安装Vuex:
npm install vuex@next --save
- 创建Vuex store:
import { createStore } from 'vuex';
export default createStore({
state: {
counter: 0
},
mutations: {
increment(state) {
state.counter++;
}
},
actions: {
increment({ commit }) {
commit('increment');
}
}
});
- 在Vue项目中使用Vuex:
<template>
<div>
<p>{{ counter }}</p>
<button @click="incrementCounter">Increment</button>
</div>
</template>
<script>
import { mapState, mapActions } from 'vuex';
export default {
computed: {
...mapState(['counter'])
},
methods: {
...mapActions(['increment'])
}
};
</script>
<script setup>
import { useStore } from 'vue';
const store = useStore();
console.log(store.state.counter); // 输出初始的counter值
</script>
Vue3路由与项目结构
Vue Router的基本使用
Vue Router是Vue官方的路由库,用于实现单页面应用的路由功能。以下是一个使用Vue Router的基本示例:
- 安装Vue Router:
npm install vue-router@next --save
- 创建路由配置:
import { createRouter, createWebHistory } from 'vue-router';
import Home from './views/Home.vue';
import About from './views/About.vue';
const routes = [
{ path: '/', component: Home },
{ path: '/about', component: About }
];
const router = createRouter({
history: createWebHistory(),
routes
});
export default router;
- 在主应用中使用路由:
<template>
<div>
<router-view></router-view>
</div>
</template>
<script>
import router from './router';
export default {
router
};
</script>
路由导航与参数传递
你可以在路由之间传递参数,这可以通过路由的动态参数来实现。以下是一个传递参数的示例:
- 定义带有动态参数的路由:
const routes = [
{ path: '/user/:id', component: User }
];
- 在组件中获取传递的参数:
<template>
<div>
<p>User ID: {{ userId }}</p>
</div>
</template>
<script>
import { useRoute } from 'vue-router';
export default {
setup() {
const route = useRoute();
const userId = route.params.id;
return { userId };
}
};
</script>
项目文件结构规划
一个合理的项目结构可以帮助你更好地组织代码,以下是一个简单的项目结构示例:
my-vue3-project/
├── public/
│ └── index.html
├── src/
│ ├── assets/
│ ├── components/
│ ├── views/
│ ├── App.vue
│ ├── main.js
│ └── router/
│ └── index.js
├── package.json
└── README.md
Vue3实战:打造个人博客网站
项目需求分析
- 主页:展示博客文章列表,包括标题、作者、发布日期和简短摘要。
- 文章详情页:展示文章的详细内容,包括评论区。
- 文章创建与编辑:管理员可以创建和编辑文章。
- 用户注册和登录:用户可以注册和登录,注册后可以发布评论。
- 后台管理:管理员可以管理所有文章和用户。
功能模块划分
-
主页模块:
Home.vue
:展示博客文章列表。ArticleCard.vue
:展示文章卡片。ArticleList.vue
:展示所有文章列表。ArticleForm.vue
:创建和编辑文章表单。
-
文章详情模块:
ArticleDetail.vue
:展示文章详细内容。ArticleComment.vue
:展示和提交评论。
-
文章管理模块:
ArticleStore.js
:文章数据存储和管理。
-
用户管理模块:
UserRegister.vue
:用户注册表单。UserLogin.vue
:用户登录表单。UserStore.js
:用户数据存储和管理。
- 后台管理模块:
AdminDashboard.vue
:后台管理首页。AdminArticleList.vue
:展示所有文章列表。AdminUserList.vue
:展示所有用户列表。
具体实现代码示例
主页模块
Home.vue
:
<template>
<div>
<h1>Blog Posts</h1>
<ul>
<li v-for="post in posts" :key="post.id">
<router-link :to="`/post/${post.id}`">{{ post.title }}</router-link>
<p>{{ post.summary }}</p>
</li>
</ul>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue';
import { useRouter } from 'vue-router';
import { fetchPosts } from '../../services/articleService';
const router = useRouter();
const posts = ref([]);
onMounted(() => {
fetchPosts().then(data => {
posts.value = data;
});
});
</script>
<style scoped>
ul {
list-style-type: none;
padding: 0;
}
li {
margin: 10px 0;
}
</style>
ArticleCard.vue
:
<template>
<div class="card">
<h2>{{ post.title }}</h2>
<p>{{ post.summary }}</p>
</div>
</template>
<script setup>
import { defineProps } from 'vue';
defineProps({
post: {
type: Object,
required: true
}
});
</script>
<style scoped>
.card {
border: 1px solid #ccc;
padding: 10px;
margin: 10px 0;
border-radius: 5px;
}
</style>
文章详情模块
ArticleDetail.vue
:
<template>
<div>
<h1>{{ post.title }}</h1>
<p>{{ post.content }}</p>
<ArticleComment :postId="post.id" />
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue';
import { useRoute } from 'vue-router';
import { fetchPost } from '../../services/articleService';
import ArticleComment from '../../components/ArticleComment.vue';
const route = useRoute();
const post = ref({});
onMounted(() => {
fetchPost(route.params.id).then(data => {
post.value = data;
});
});
</script>
<style scoped>
h1 {
color: #343a40;
font-size: 1.5em;
}
p {
color: #6c757d;
font-size: 1em;
}
</style>
ArticleComment.vue
:
<template>
<div>
<h2>Comments</h2>
<ul>
<li v-for="comment in comments" :key="comment.id">
<p>{{ comment.content }}</p>
</li>
</ul>
<form @submit.prevent="submitComment">
<textarea v-model="commentContent" placeholder="Type your comment..." />
<button type="submit">Submit</button>
</form>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue';
import { fetchComments, addComment } from '../../services/commentService';
const postId = ref(null);
const commentContent = ref('');
const comments = ref([]);
const submitComment = () => {
addComment(postId.value, commentContent.value).then(() => {
commentContent.value = '';
fetchComments(postId.value);
});
};
onMounted(() => {
if (postId.value) {
fetchComments(postId.value).then(data => {
comments.value = data;
});
}
});
</script>
<style scoped>
textarea {
width: 100%;
margin-bottom: 10px;
}
button {
background-color: #28a745;
color: white;
border: none;
padding: 5px 10px;
cursor: pointer;
}
</style>
文章管理模块
ArticleList.vue
:
<template>
<div>
<h1>Article List</h1>
<ul>
<li v-for="post in posts" :key="post.id">
<router-link :to="`/post/${post.id}`">{{ post.title }}</router-link>
<button @click="deletePost(post.id)">Delete</button>
</li>
</ul>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue';
import { fetchPosts } from '../../services/articleService';
const posts = ref([]);
onMounted(() => {
fetchPosts().then(data => {
posts.value = data;
});
});
const deletePost = (postId) => {
// 实现删除逻辑
};
</script>
<style scoped>
ul {
list-style-type: none;
padding: 0;
}
li {
margin: 10px 0;
}
</style>
ArticleForm.vue
:
<template>
<div>
<h2>Article Form</h2>
<form @submit.prevent="submitArticle">
<label>
Title:
<input v-model="title" type="text" />
</label>
<label>
Content:
<textarea v-model="content" placeholder="Type your article..." />
</label>
<button type="submit">Submit</button>
</form>
</div>
</template>
<script setup>
import { ref } from 'vue';
const title = ref('');
const content = ref('');
const submitArticle = () => {
// 实现提交逻辑
};
</script>
<style scoped>
input, textarea {
width: 100%;
margin-bottom: 10px;
}
button {
background-color: #28a745;
color: white;
border: none;
padding: 5px 10px;
cursor: pointer;
}
</style>
项目部署与上线
部署Vue项目可以通过几种方法实现,以下是两种常见的方法:
- 使用Vite部署:
npm run build
构建完成后,将生成的dist
文件夹上传到服务器。
- 使用GitHub Pages部署:
npm run build
npm run deploy
构建完成后,将生成的dist
文件夹中的内容上传到GitHub Pages。
部署完成后,可以通过浏览器访问你的博客网站。
总结
通过以上步骤,你已经掌握了Vue3的基本概念和开发流程,从安装到项目结构规划,再到实战演练,你已经完成了一个简单的博客网站的开发。如果你想要深入学习Vue3,建议参考Vue官方文档或参加在线课程,例如Muicoo提供的Vue3教程。
共同學習,寫下你的評論
評論加載中...
作者其他優質文章