本文全面介绍了Vue.js的基础知识和核心特性,包括响应式数据绑定、组件化开发和虚拟DOM等概念。文章还详细讲解了Vue的学习路径,涵盖了安装配置、项目搭建以及组件化开发等多个方面,帮助读者快速掌握Vue.js的学习。
Vue.js是由尤雨青(Evan You)开发的一个前端JavaScript框架。它具有轻量、易用、灵活和可扩展性等特点,适用于从小型到大型的单页应用开发。Vue的核心理念是为前端开发人员提供一个简洁、高效、渐进式的工具,以帮助开发人员构建动态的用户界面。
Vue的核心特性包括:
v-bind
指令,用于实现单向数据绑定,而v-model
指令则用于实现双向数据绑定。v-if
、v-for
、v-bind
等,这些指令可以操作DOM或更新视图。created
、mounted
等,允许在组件的各个阶段执行特定的操作。vuex
进行状态管理。vuex是一个专为 Vue.js 应用程序开发的状态管理模式和可组合的可预测的状态容器。vue-router
、vuex
等。Vue通过依赖追踪机制实现了响应式系统。当数据发生变化时,Vue会自动更新视图。主要步骤如下:
Object.defineProperty
(在 Vue 2.x 中)或Proxy
(在 Vue 3.x 中)对数据对象进行拦截。// 示例代码:响应式初始化 const data = { count: 0 }; // 使用Object.defineProperty实现响应式 const observe = (obj) => { if (typeof obj !== 'object') return; Object.keys(obj).forEach((key) => { defineReactive(obj, key, obj[key]); }); }; const defineReactive = (obj, key, value) => { Object.defineProperty(obj, key, { get() { return value; }, set(newVal) { if (newVal === value) return; value = newVal; console.log(`属性 ${key} 的值已更新为 ${newVal}`); } }); }; observe(data); data.count = 1; // 输出:属性 count 的值已更新为 1
<template> <div> <p>{{ message }}</p> <input v-model="message"> </div> </template> <script> export default { data() { return { message: 'Hello, World!' } } } </script>
<template> <div> <p>{{ message }}</p> <input v-model="message"> </div> </template> <script> export default { data() { return { message: 'Hello, World!' } } } </script>
<template> <div> <p>{{ user.name }}</p> <input v-model="user.name"> </div> </template> <script> export default { data() { return { user: { name: 'John' } } } } </script>
my-vue-project
。npm init -y
npm install vue@2.6.14 --save
src/index.js
:import Vue from 'vue'; import App from './App.vue'; new Vue({ el: '#app', components: { App }, template: '<App/>' });
public/index.html
:<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Vue项目</title> </head> <body> <div id="app"></div> <!-- 引入Vue.js --> <script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="/js/vue.js"></script> <!-- 引入本项目js --> <script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="/js/index.js"></script> </body> </html>
src/App.vue
:<template> <div> <h1>{{ message }}</h1> </div> </template> <script> export default { data() { return { message: 'Hello, Vue!' } } } </script>
Vue CLI 是 Vue 的脚手架工具,用于快速搭建项目。可以通过以下步骤创建一个 Vue 项目:
npm install -g @vue/cli
vue create my-vue-project
按照提示选择所需的配置,例如模板、插件等。
cd my-vue-project npm run serve
这将启动开发服务器并开启热重载功能,便于实时查看修改后的效果。
一个典型的 Vue 项目目录结构如下:
my-vue-project/ ├── node_modules/ ├── public/ │ └── index.html ├── src/ │ ├── assets/ │ ├── components/ │ │ └── HelloWorld.vue │ ├── App.vue │ ├── main.js │ └── router/ │ └── index.js ├── .gitignore ├── babel.config.js ├── package.json └── vue.config.js
public/
:存放静态资源,如 index.html
。src/
:存放源代码,包括组件、样式、路由配置等。assets/
:存放静态资源文件,如图片、字体等。components/
:存放 Vue 组件。App.vue
:应用的根组件。main.js
:应用的入口文件。router/
:存放路由配置。.gitignore
:配置 Git 忽略的文件。babel.config.js
:配置 Babel。package.json
:存放项目配置和依赖。vue.config.js
:配置 Vue CLI 选项。创建一个名为 HelloWorld.vue
的组件:
<template> <div> <h1>{{ message }}</h1> </div> </template> <script> export default { name: 'HelloWorld', data() { return { message: 'Hello, World!' } } } </script> <style scoped> h1 { color: #42b983; } </style>
<template> <div id="app"> <HelloWorld /> </div> </template> <script> import HelloWorld from './components/HelloWorld.vue'; export default { name: 'App', components: { HelloWorld } } </script>
<template> <div id="app"> <h1>App Component</h1> <hello-world></hello-world> </div> </template>
父组件通过 props
向子组件传递数据。
<!-- ParentComponent.vue --> <template> <div> <ChildComponent :message="parentMessage" /> </div> </template> <script> import ChildComponent from './ChildComponent.vue'; export default { name: 'ParentComponent', data() { return { parentMessage: 'Hello from Parent' } }, components: { ChildComponent } } </script>
<!-- ChildComponent.vue --> <template> <div> <p>{{ message }}</p> </div> </template> <script> export default { name: 'ChildComponent', props: ['message'] } </script>
子组件通过 $emit
触发自定义事件,将数据传递给父组件。
<!-- ParentComponent.vue --> <template> <div> <ChildComponent @child-event="handleChildEvent" /> </div> </template> <script> import ChildComponent from './ChildComponent.vue'; export default { name: 'ParentComponent', methods: { handleChildEvent(data) { console.log('Child event received:', data); } }, components: { ChildComponent } } </script>
<!-- ChildComponent.vue --> <template> <div> <button @click="sendDataToParent">Send Data</button> </div> </template> <script> export default { name: 'ChildComponent', methods: { sendDataToParent() { this.$emit('child-event', 'Hello from Child'); } } } </script>
props
是父组件向子组件传递数据的一种方式。子组件通过 props
接收数据,可以在模板中使用这些数据。
<!-- ChildComponent.vue --> <template> <div> <p>{{ message }}</p> </div> </template> <script> export default { name: 'ChildComponent', props: { message: { type: String, required: true } } } </script>
子组件通过 $emit
触发自定义事件,将数据传递给父组件。父组件通过监听这些事件来接收数据。
<!-- ChildComponent.vue --> <template> <div> <button @click="sendDataToParent">Send Data</button> </div> </template> <script> export default { name: 'ChildComponent', methods: { sendDataToParent() { this.$emit('child-event', 'Hello from Child'); } } } </script>
<!-- ParentComponent.vue --> <template> <div> <ChildComponent @child-event="handleChildEvent" /> </div> </template> <script> import ChildComponent from './ChildComponent.vue'; export default { name: 'ParentComponent', methods: { handleChildEvent(data) { console.log('Child event received:', data); } }, components: { ChildComponent } } </script>
首先,安装 Vue Router:
npm install vue-router@3.1.6 --save
然后,在项目中引入 Vue Router 并进行配置。
// router/index.js import Vue from 'vue'; import Router from 'vue-router'; import Home from '../components/Home.vue'; import About from '../components/About.vue'; Vue.use(Router); export default new Router({ routes: [ { path: '/', name: 'Home', component: Home }, { path: '/about', name: 'About', component: About } ] });
// src/main.js import Vue from 'vue'; import App from './App.vue'; import router from './router'; new Vue({ el: '#app', router, render: h => h(App) });
<template> <div> <router-link to="/">Home</router-link> <router-link to="/about">About</router-link> <router-view></router-view> </div> </template> <script> export default { name: 'App' } </script>
// router/index.js import Vue from 'vue'; import Router from 'vue-router'; import Home from '../components/Home.vue'; import About from '../components/About.vue'; import Auth from '../components/Auth.vue'; Vue.use(Router); const router = new Router({ routes: [ { path: '/', name: 'Home', component: Home }, { path: '/about', name: 'About', component: About }, { path: '/auth', name: 'Auth', component: Auth } ] }); router.beforeEach((to, from, next) => { if (to.name === 'Auth' && !isAuthenticated()) { next('/about'); } else { next(); } }); export default router; function isAuthenticated() { return true; // 模拟认证逻辑 }
<template> <div> <router-link to="/">Home</router-link> <router-link to="/about">About</router-link> <router-link to="/about/child1">Child1</router-link> <router-link to="/about/child2">Child2</router-link> <router-view></router-view> </div> </template> <script> export default { name: 'App' } </script>
// router/index.js import Vue from 'vue'; import Router from 'vue-router'; import Home from '../components/Home.vue'; import About from '../components/About.vue'; import Child1 from '../components/Child1.vue'; import Child2 from '../components/Child2.vue'; Vue.use(Router); const router = new Router({ routes: [ { path: '/', name: 'Home', component: Home }, { path: '/about', name: 'About', component: About, children: [ { path: 'child1', name: 'Child1', component: Child1 }, { path: 'child2', name: 'Child2', component: Child2 } ] } ] }); export default router;
<template> <div> <router-link to="/user/123">User 123</router-link> <router-link to="/user/456">User 456</router-link> <router-view></router-view> </div> </template> <script> export default { name: 'App' } </script>
// router/index.js import Vue from 'vue'; import Router from 'vue-router'; import User from '../components/User.vue'; Vue.use(Router); const router = new Router({ routes: [ { path: '/user/:id', name: 'User', component: User, props: true } ] }); export default router;
<template> <div> <router-link to="/user/123">User 123</router-link> <router-link to="/user/456">User 456</router-link> <router-view></router-view> </div> </template> <script> export default { name: 'App' } </script>
// router/index.js import Vue from 'vue'; import Router from 'vue-router'; import User from '../components/User.vue'; Vue.use(Router); const router = new Router({ routes: [ { path: '/user/:id', name: 'User', component: User, props: route => ({ id: route.params.id }) } ] }); export default router;
my-todo-app/ ├── node_modules/ ├── public/ │ └── index.html ├── src/ │ ├── assets/ │ ├── components/ │ │ └── TodoList.vue │ │ └── TodoInput.vue │ ├── App.vue │ ├── main.js │ └── router/ │ └── index.js ├── .gitignore ├── babel.config.js ├── package.json └── vue.config.js
<template> <div> <input v-model="newTodo" @keyup.enter="addTodo"> <button @click="addTodo">Add Todo</button> </div> </template> <script> export default { data() { return { newTodo: '' } }, methods: { addTodo() { if (this.newTodo.trim()) { this.$emit('add-todo', this.newTodo); this.newTodo = ''; } } } } </script>
<template> <div> <ul> <li v-for="(todo, index) in todos" :key="index" @click="completeTodo(index)"> {{ todo.text }} <button @click="removeTodo(index)">Remove</button> </li> </ul> </div> </template> <script> export default { props: ['todos'], methods: { removeTodo(index) { this.$emit('remove-todo', index); }, completeTodo(index) { this.$emit('complete-todo', index); } } } </script>
<template> <div> <h1>Todo List</h1> <TodoInput @add-todo="addTodo" /> <TodoList :todos="todos" @remove-todo="removeTodo" @complete-todo="completeTodo" /> </div> </template> <script> import TodoInput from './components/TodoInput.vue'; import TodoList from './components/TodoList.vue'; export default { components: { TodoInput, TodoList }, data() { return { todos: [] } }, methods: { addTodo(todo) { this.todos.push({ text: todo, completed: false }); }, removeTodo(index) { this.todos.splice(index, 1); }, completeTodo(index) { this.todos[index].completed = true; } } } </script>
my-blog-app/ ├── node_modules/ ├── public/ │ └── index.html ├── src/ │ ├── assets/ │ ├── components/ │ │ └── BlogPost.vue │ ├── App.vue │ ├── main.js │ └── router/ │ └── index.js ├── .gitignore ├── babel.config.js ├── package.json └── vue.config.js
<template> <div> <h2>{{ post.title }}</h2> <p>{{ post.content }}</p> </div> </template> <script> export default { props: ['post'] } </script>
<template> <div> <h1>My Blog</h1> <BlogPost v-for="post in posts" :key="post.id" :post="post" /> </div> </template> <script> import BlogPost from './components/BlogPost.vue'; export default { components: { BlogPost }, data() { return { posts: [ { id: 1, title: 'First Post', content: 'This is the first post in my blog.' }, { id: 2, title: 'Second Post', content: 'This is the second post in my blog.' } ] } } } </script>
npm run build
构建应用。dist
文件夹上传到 GitHub 仓库。gh-pages
分支。# 构建应用 npm run build # 将dist文件夹上传到GitHub仓库 git add dist git commit -m "Build dist" git push origin master # 设置GitHub Pages # 在GitHub仓库设置中,选择"Settings" -> "GitHub Pages",将源设置为"gh-pages"分支
package.json
中添加部署设置:{ "name": "my-project", "version": "1.0.0", "homepage": "https://username.github.io/my-project" }
npm run build
作为构建命令。# 构建应用 npm run build # 连接GitHub仓库到Netlify # 在Netlify网站中,选择"New site from Git",连接GitHub仓库 # 设置构建设置 # 在Netlify网站中,选择"Build & Deploy" -> "Build settings",指定"Build Command"为"npm run build","Publish directory"为"dist"
npm run build
作为构建命令。# 构建应用 npm run build # 连接GitHub仓库到Vercel # 在Vercel网站中,选择"New Project",连接GitHub仓库 # 设置构建设置 # 在Vercel网站中,选择"Build & Output" -> "Build settings",指定"Build Command"为"npm run build","Output Directory"为"dist"
通过以上步骤,可以将 Vue 应用部署到不同的平台上,实现线上发布。