【AI Generated】从零学习Vue.js
从零学习Vue.js
目录
- 引言
- 准备工作
- Vue.js 基础
- 3.1 Vue 实例
- 3.2 模板语法
- 3.3 数据绑定
- 3.4 计算属性和侦听器
- 3.5 Class 与 Style 绑定
- 3.6 条件渲染
- 3.7 列表渲染
- 3.8 事件处理
- 3.9 表单输入绑定
- Vue.js 组件
- 4.1 组件基础
- 4.2 组件注册
- 4.3 父子组件通信
- 4.4 插槽
- 4.5 动态组件
- 4.6 异步组件
- Vue Router
- 5.1 路由基础
- 5.2 动态路由匹配
- 5.3 嵌套路由
- 5.4 路由守卫
- 5.5 路由元信息
- 5.6 导航守卫
- 5.7 路由懒加载
- Vuex 状态管理
- 6.1 Vuex 基础
- 6.2 核心概念
- 6.3 模块化
- 6.4 中间件
- 6.5 辅助函数
- 项目实战
- 7.1 项目初始化
- 7.2 组件设计
- 7.3 路由配置
- 7.4 状态管理
- 7.5 API 集成
- 7.6 部署与优化
- 进阶概念
- 8.1 自定义指令
- 8.2 混入
- 8.3 插件
- 8.4 服务端渲染 (SSR)
- 8.5 Vue 3 新特性
- 总结与展望
1. 引言
Vue.js 是一个用于构建用户界面的渐进式 JavaScript 框架。它的设计理念是尽量简单,同时提供足够的灵活性和性能来应对复杂的应用需求。本书将带你从零开始学习 Vue.js,逐步掌握其核心概念和高级特性。
2. 准备工作
在开始学习 Vue.js 之前,你需要具备以下基础知识:
- HTML/CSS 基础
- JavaScript 基础
此外,你需要准备以下开发工具:
- 一个现代浏览器(如 Chrome 或 Firefox)
- 一个代码编辑器(如 VS Code 或 Sublime Text)
- Node.js 和 npm(用于管理项目依赖)
安装 Node.js 和 npm:
- 访问 Node.js 官网 下载并安装适用于你操作系统的版本。
- 安装完成后,打开终端(或命令提示符)并运行以下命令,确认安装成功:
node -v npm -v
3. Vue.js 基础
3.1 Vue 实例
Vue.js 应用的核心是 Vue 实例。你可以通过创建一个新的 Vue 实例来启动一个 Vue 应用。
<!DOCTYPE html>
<html>
<head>
<title>Vue.js 学习</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
</head>
<body>
<div id="app">{{ message }}</div>
<script>
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
}
});
</script>
</body>
</html>
3.2 模板语法
Vue.js 使用一种基于 HTML 的模板语法,允许你声明式地绑定数据到 DOM。
<div id="app">
<p>{{ message }}</p>
<p v-bind:title="message">鼠标悬停查看消息</p>
</div>
<script>
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
}
});
</script>
3.3 数据绑定
Vue.js 提供了两种主要的数据绑定方式:插值和指令。
<div id="app">
<p>{{ message }}</p>
<input v-model="message">
</div>
<script>
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
}
});
</script>
3.4 计算属性和侦听器
计算属性用于对数据进行计算和处理,而侦听器用于监听数据的变化。
<div id="app">
<p>原始消息: {{ message }}</p>
<p>反转消息: {{ reversedMessage }}</p>
</div>
<script>
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
},
computed: {
reversedMessage: function () {
return this.message.split('').reverse().join('');
}
}
});
</script>
3.5 Class 与 Style 绑定
你可以动态地绑定 HTML 元素的 class 和 style。
<div id="app">
<div v-bind:class="{ active: isActive }">Class 绑定</div>
<div v-bind:style="styleObject">Style 绑定</div>
</div>
<script>
var app = new Vue({
el: '#app',
data: {
isActive: true,
styleObject: {
color: 'red',
fontSize: '20px'
}
}
});
</script>
3.6 条件渲染
使用 v-if
指令可以根据条件渲染元素。
<div id="app">
<p v-if="seen">现在你看到我了</p>
</div>
<script>
var app = new Vue({
el: '#app',
data: {
seen: true
}
});
</script>
3.7 列表渲染
使用 v-for
指令可以渲染一个列表。
<div id="app">
<ul>
<li v-for="item in items" v-bind:key="item.id">
{{ item.text }}
</li>
</ul>
</div>
<script>
var app = new Vue({
el: '#app',
data: {
items: [
{ id: 1, text: '苹果' },
{ id: 2, text: '香蕉' },
{ id: 3, text: '橙子' }
]
}
});
</script>
3.8 事件处理
使用 v-on
指令可以监听 DOM 事件。
<div id="app">
<button v-on:click="greet">点击我</button>
</div>
<script>
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
},
methods: {
greet: function () {
alert(this.message);
}
}
});
</script>
3.9 表单输入绑定
使用 v-model
指令可以实现表单输入与应用状态的双向绑定。
<div id="app">
<input v-model="message">
<p>{{ message }}</p>
</div>
<script>
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
}
});
</script>
4. Vue.js 组件
4.1 组件基础
组件是 Vue.js 的核心概念,用于构建可复用的 UI 片段。
<div id="app">
<my-component></my-component>
</div>
<script>
Vue.component('my-component', {
template: '<p>这是一个组件</p>'
});
var app = new Vue({
el: '#app'
});
</script>
4.2 组件注册
组件可以全局注册或局部注册。
<!-- 全局注册 -->
<script>
Vue.component('my-component', {
template: '<p>这是一个全局注册的组件</p>'
});
</script>
<!-- 局部注册 -->
<script>
var Child = {
template: '<p>这是一个局部注册的组件</p>'
};
var app = new Vue({
el: '#app',
components: {
'my-component': Child
}
});
</script>
4.3 父子组件通信
父组件可以通过 props 向子组件传递数据,子组件可以通过事件向父组件发送消息。
<div id="app">
<child-component v-bind:message="parentMessage"></child-component>
</div>
<script>
Vue.component('child-component', {
props: ['message'],
template: '<p>{{ message }}</p>'
});
var app = new Vue({
el: '#app',
data: {
parentMessage: '来自父组件的消息'
}
});
</script>
4.4 插槽
插槽允许你在组件中插入内容。
<div id="app">
<alert-box>
<strong>注意!</strong> 这是一个重要的消息。
</alert-box>
</div>
<script>
Vue.component('alert-box', {
template: `
<div class="alert-box">
<slot></slot>
</div>
`
});
var app = new Vue({
el: '#app'
});
</script>
4.5 动态组件
动态组件允许你在同一个挂载点动态切换多个组件。
<div id="app">
<component v-bind:is="currentComponent"></component>
<button v-on:click="currentComponent = 'component-a'">显示 A</button>
<button v-on:click="currentComponent = 'component-b'">显示 B</button>
</div>
<script>
Vue.component('component-a', {
template: '<p>组件 A</p>'
});
Vue.component('component-b', {
template: '<p>组件 B</p>'
});
var app = new Vue({
el: '#app',
data: {
currentComponent: 'component-a'
}
});
</script>
4.6 异步组件
异步组件可以按需加载,减少初始加载时间。
Vue.component('async-example', function (resolve, reject) {
setTimeout(function () {
// 向 `resolve` 回调传递组件定义
resolve({
template: '<div>异步组件加载成功!</div>'
})
}, 1000)
})
5. Vue Router
5.1 路由基础
Vue Router 是 Vue.js 的官方路由管理器,用于构建单页应用。
<!DOCTYPE html>
<html>
<head>
<title>Vue Router 学习</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
<script src="https://cdn.jsdelivr.net/npm/vue-router@3"></script>
</head>
<body>
<div id="app">
<router-link to="/home">首页</router-link>
<router-link to="/about">关于</router-link>
<router-view></router-view>
</div>
<script>
const Home = { template: '<p>首页</p>' }
const About = { template: '<p>关于</p>' }
const routes = [
{ path: '/home', component: Home },
{ path: '/about', component: About }
]
const router = new VueRouter({
routes
})
var app = new Vue({
el: '#app',
router
});
</script>
</body>
</html>
5.2 动态路由匹配
动态路由匹配允许你在路由路径中使用参数。
<div id="app">
<router-link to="/user/1">用户 1</router-link>
<router-link to="/user/2">用户 2</router-link>
<router-view></router-view>
</div>
<script>
const User = {
template: '<p>用户 ID: {{ $route.params.id }}</p>'
}
const routes = [
{ path: '/user/:id', component: User }
]
const router = new VueRouter({
routes
})
var app = new Vue({
el: '#app',
router
});
</script>
5.3 嵌套路由
嵌套路由允许你在路由视图中嵌套其他路由视图。
<div id="app">
<router-link to="/user/1">用户 1</router-link>
<router-link to="/user/2">用户 2</router-link>
<router-view></router-view>
</div>
<script>
const User = {
template: `
<div>
<h2>用户 ID: {{ $route.params.id }}</h2>
<router-link to="profile">个人资料</router-link>
<router-link to="posts">帖子</router-link>
<router-view></router-view>
</div>
`
}
const UserProfile = { template: '<p>个人资料</p>' }
const UserPosts = { template: '<p>帖子</p>' }
const routes = [
{ path: '/user/:id', component: User,
children: [
{ path: 'profile', component: UserProfile },
{ path: 'posts', component: UserPosts }
]
}
]
const router = new VueRouter({
routes
})
var app = new Vue({
el: '#app',
router
});
</script>
5.4 路由守卫
路由守卫允许你在导航到某个路由之前执行一些逻辑。
<div id="app">
<router-link to="/home">首页</router-link>
<router-link to="/about">关于</router-link>
<router-view></router-view>
</div>
<script>
const Home = { template: '<p>首页</p>' }
const About = { template: '<p>关于</p>' }
const routes = [
{ path: '/home', component: Home },
{ path: '/about', component: About, beforeEnter: (to, from, next) => {
if (confirm('你确定要进入关于页面吗?')) {
next()
} else {
next(false)
}
}}
]
const router = new VueRouter({
routes
})
var app = new Vue({
el: '#app',
router
});
</script>
5.5 路由元信息
路由元信息允许你在路由配置中添加自定义数据。
<div id="app">
<router-link to="/home">首页</router-link>
<router-link to="/about">关于</router-link>
<router-view></router-view>
</div>
<script>
const Home = { template: '<p>首页</p>' }
const About = { template: '<p>关于</p>' }
const routes = [
{ path: '/home', component: Home },
{ path: '/about', component: About, meta: { requiresAuth: true } }
]
const router = new VueRouter({
routes
})
router.beforeEach((to, from, next) => {
if (to.matched.some(record => record.meta.requiresAuth)) {
// 这里可以添加你的认证逻辑
if (!auth.isAuthenticated()) {
next({ path: '/login' })
} else {
next()
}
} else {
next()
}
})
var app = new Vue({
el: '#app',
router
});
</script>
5.6 导航守卫
导航守卫可以在路由切换前后执行逻辑。
<div id="app">
<router-link to="/home">首页</router-link>
<router-link to="/about">关于</router-link>
<router-view></router-view>
</div>
<script>
const Home = { template: '<p>首页</p>' }
const About = { template: '<p>关于</p>' }
const routes = [
{ path: '/home', component: Home },
{ path: '/about', component: About }
]
const router = new VueRouter({
routes
})
router.beforeEach((to, from, next) => {
console.log('全局前置守卫')
next()
})
router.afterEach((to, from) => {
console.log('全局后置守卫')
})
var app = new Vue({
el: '#app',
router
});
</script>
5.7 路由懒加载
路由懒加载可以按需加载路由组件,减少初始加载时间。
const routes = [
{
path: '/home',
component: () => import('./components/Home.vue')
},
{
path: '/about',
component: () => import('./components/About.vue')
}
]
const router = new VueRouter({
routes
})
6. Vuex 状态管理
6.1 Vuex 基础
Vuex 是一个专为 Vue.js 应用设计的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
<!DOCTYPE html>
<html>
<head>
<title>Vuex 学习</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
<script src="https://cdn.jsdelivr.net/npm/vuex@3"></script>
</head>
<body>
<div id="app">
<p>{{ count }}</p>
<button @click="increment">增加</button>
</div>
<script>
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
}
})
var app = new Vue({
el: '#app',
store,
computed: {
count () {
return this.$store.state.count
}
},
methods: {
increment () {
this.$store.commit('increment')
}
}
});
</script>
</body>
</html>
6.2 核心概念
Vuex 的核心概念包括状态(state)、变更(mutations)、动作(actions)和 getters。
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
},
actions: {
incrementAsync ({ commit }) {
setTimeout(() => {
commit('increment')
}, 1000)
}
},
getters: {
doubleCount: state => state.count * 2
}
})
6.3 模块化
Vuex 允许你将状态管理逻辑拆分成模块,每个模块拥有自己的 state、mutations、actions 和 getters。
const moduleA = {
state: { count: 0 },
mutations: { increment (state) { state.count++ } },
actions: { incrementAsync ({ commit }) { commit('increment') } },
getters: { doubleCount: state => state.count * 2 }
}
const moduleB = {
state: { count: 0 },
mutations: { increment (state) { state.count++ } },
actions: { incrementAsync ({ commit }) { commit('increment') } },
getters: { doubleCount: state => state.count * 2 }
}
const store = new Vuex.Store({
modules: {
a: moduleA,
b: moduleB
}
})
6.4 中间件
Vuex 支持插件机制,可以在状态变更时执行一些逻辑。
const myPlugin = store => {
store.subscribe((mutation, state) => {
console.log(mutation.type)
console.log(mutation.payload)
})
}
const store = new Vuex.Store({
state: { count: 0 },
mutations: { increment (state) { state.count++ } },
plugins: [myPlugin]
})
6.5 辅助函数
Vuex 提供了一些辅助函数,帮助你简化代码。
<div id="app">
<p>{{ count }}</p>
<button @click="increment">增加</button>
</div>
<script>
const store = new Vuex.Store({
state: { count: 0 },
mutations: { increment (state) { state.count++ } },
actions: { incrementAsync ({ commit }) { commit('increment') } },
getters: { doubleCount: state => state.count * 2 }
})
var app = new Vue({
el: '#app',
store,
computed: Vuex.mapState(['count']),
methods: Vuex.mapMutations(['increment'])
});
</script>
7. 项目实战
7.1 项目初始化
使用 Vue CLI 初始化一个新的 Vue 项目。
npm install -g @vue/cli
vue create my-project
cd my-project
npm run serve
7.2 组件设计
根据项目需求设计和实现各个组件。假设我们要构建一个简单的待办事项应用。
vue create todo-app
cd todo-app
npm run serve
创建 components/TodoItem.vue
:
<template>
<li>
<input type="checkbox" v-model="todo.done">
<span>{{ todo.text }}</span>
</li>
</template>
<script>
export default {
props: ['todo']
}
</script>
创建 components/TodoList.vue
:
<template>
<ul>
<todo-item v-for="todo in todos" :key="todo.id" :todo="todo"></todo-item>
</ul>
</template>
<script>
import TodoItem from './TodoItem.vue'
export default {
components: {
TodoItem
},
data () {
return {
todos: [
{ id: 1, text: '学习 Vue', done: true },
{ id: 2, text: '学习 Vuex', done: false },
{ id: 3, text: '学习 Vue Router', done: false }
]
}
}
}
</script>
在 App.vue
中使用 TodoList
组件:
<template>
<div id="app">
<h1>待办事项</h1>
<todo-list></todo-list>
</div>
</template>
<script>
import TodoList from './components/TodoList.vue'
export default {
components: {
TodoList
}
}
</script>
7.3 路由配置
使用 Vue Router 配置项目的路由。
安装 Vue Router:
npm install 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: '/', component: Home },
{ path: '/about', component: About }
]
})
在 main.js
中引入路由:
import Vue from 'vue'
import App from './App.vue'
import router from './router'
Vue.config.productionTip = false
new Vue({
router,
render: h => h(App)
}).$mount('#app')
创建 components/Home.vue
和 components/About.vue
:
Home.vue
:
<template>
<div>
<h1>首页</h1>
<todo-list></todo-list>
</div>
</template>
<script>
import TodoList from './TodoList.vue'
export default {
components: {
TodoList
}
}
</script>
About.vue
:
<template>
<div>
<h1>关于</h1>
<p>这是关于页面。</p>
</div>
</template>
7.4 状态管理
使用 Vuex 管理项目的全局状态。
安装 Vuex:
npm install vuex
创建 store/index.js
:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
todos: [
{ id: 1, text: '学习 Vue', done: true },
{ id: 2, text: '学习 Vuex', done: false },
{ id: 3, text: '学习 Vue Router', done: false }
]
},
mutations: {
addTodo (state, todo) {
state.todos.push(todo)
}
},
actions: {
addTodo ({ commit }, todo) {
commit('addTodo', todo)
}
},
getters: {
doneTodos: state => {
return state.todos.filter(todo => todo.done)
}
}
})
在 main.js
中引入 Vuex:
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
Vue.config.productionTip = false
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
在 TodoList.vue
中使用 Vuex 状态:
<template>
<ul>
<todo-item v-for="todo in todos" :key="todo.id" :todo="todo"></todo-item>
</ul>
</template>
<script>
import TodoItem from './TodoItem.vue'
import { mapState } from 'vuex'
export default {
components: {
TodoItem
},
computed: {
...mapState(['todos'])
}
}
</script>
7.5 API 集成
假设我们有一个简单的 API 来获取和添加待办事项。
创建 api/todos.js
:
import axios from 'axios'
const API_URL = 'http://example.com/api/todos'
export default {
getTodos () {
return axios.get(API_URL)
},
addTodo (todo) {
return axios.post(API_URL, todo)
}
}
在 Vuex 中使用 API:
import Vue from 'vue'
import Vuex from 'vuex'
import api from '@/api/todos'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
todos: []
},
mutations: {
setTodos (state, todos) {
state.todos = todos
},
addTodo (state, todo) {
state.todos.push(todo)
}
},
actions: {
fetchTodos ({ commit }) {
api.getTodos().then(response => {
commit('setTodos', response.data)
})
},
addTodo ({ commit }, todo) {
api.addTodo(todo).then(response => {
commit('addTodo', response.data)
})
}
},
getters: {
doneTodos: state => {
return state.todos.filter(todo => todo.done)
}
}
})
在组件中触发 API 请求:
<template>
<div>
<ul>
<todo-item v-for="todo in todos" :key="todo.id" :todo="todo"></todo-item>
</ul>
<input v-model="newTodoText" placeholder="添加新任务">
<button @click="addTodo">添加</button>
</div>
</template>
<script>
import TodoItem from './TodoItem.vue'
import { mapState, mapActions } from 'vuex'
export default {
components: {
TodoItem
},
data() {
return {
newTodoText: ''
}
},
computed: {
...mapState(['todos'])
},
methods: {
...mapActions(['fetchTodos', 'addTodo']),
addTodo() {
const newTodo = {
text: this.newTodoText,
done: false
}
this.addTodo(newTodo)
this.newTodoText = ''
}
},
created() {
this.fetchTodos()
}
}
</script>
7.6 部署与优化
将项目部署到生产环境,并进行性能优化。
- 构建项目:
npm run build
- 部署到服务器:
将 dist
目录中的内容上传到你的服务器。
- 性能优化:
- 使用 Vue Router 的懒加载功能按需加载组件。
- 使用 Vuex 的模块化功能减少状态管理的复杂性。
- 使用 Webpack 的代码分割功能减少初始加载时间。
- 使用 gzip 压缩减少传输数据量。
8. 进阶概念
8.1 自定义指令
自定义指令允许你在 DOM 元素上应用自定义行为。
Vue.directive('focus', {
inserted: function (el) {
el.focus()
}
})
在组件中使用自定义指令:
<template>
<input v-focus>
</template>
8.2 混入
混入提供了一种分发 Vue 组件可复用功能的非常灵活的方式。
const myMixin = {
created: function () {
this.hello()
},
methods: {
hello: function () {
console.log('Hello from mixin!')
}
}
}
const Component = Vue.extend({
mixins: [myMixin]
})
8.3 插件
插件是 Vue.js 的一个核心概念,用于为 Vue 添加全局功能。
const MyPlugin = {
install (Vue, options) {
Vue.mixin({
created: function () {
console.log('Hello from plugin!')
}
})
}
}
Vue.use(MyPlugin)
8.4 服务端渲染 (SSR)
Vue.js 也支持服务端渲染(SSR),用于提升首屏加载速度和 SEO。
安装 Vue SSR 工具:
npm install vue-server-renderer express
创建 server.js
:
const express = require('express')
const renderer = require('vue-server-renderer').createRenderer()
const createApp = require('./path/to/your/app')
const server = express()
server.get('*', (req, res) => {
const app = createApp()
renderer.renderToString(app, (err, html) => {
if (err) {
res.status(500).end('Internal Server Error')
return
}
res.end(`
<!DOCTYPE html>
<html lang="en">
<head><title>Hello</title></head>
<body>${html}</body>
</html>
`)
})
})
server.listen(8080)
8.5 Vue 3 新特性
Vue 3 引入了一些新的特性和改进,包括组合式 API、性能优化、TypeScript 支持等。
组合式 API
组合式 API 提供了一种更灵活的方式来组织组件逻辑。
<template>
<div>
<p>{{ count }}</p>
<button @click="increment">增加</button>
</div>
</template>
<script>
import { ref } from 'vue'
export default {
setup() {
const count = ref(0)
const increment = () => {
count.value++
}
return {
count,
increment
}
}
}
</script>
9. 总结与展望
通过本书的学习,你应该已经掌握了 Vue.js 的基础知识和一些高级特性。希望你能将这些知识应用到实际项目中,不断实践和探索,成为一名优秀的 Vue.js 开发者。未来,Vue.js 生态系统还会不断发展,期待你能持续关注和学习。