一、基础语法与指令
1. 插值表达式
插值表达式是 Vue 中最基础的数据绑定方式,使用双大括号{{ }}
将数据包裹起来,例如{{ message }}
,它会将 Vue 实例中的message
属性的值渲染到页面相应位置。这种方式可以方便地在页面中展示动态数据,如从后端获取的数据或者用户输入的信息。
2. 指令
Vue 提供了一系列指令来增强 HTML 的功能。
v-bind
:用于动态绑定 HTML 属性,缩写为:
。例如<img v-bind:src="imageSrc">
,可以根据imageSrc
变量的值动态改变图片的源地址。v-on
:用于绑定事件监听器,缩写为@
。比如<button v-on:click="handleClick">点击我</button>
,当按钮被点击时,会触发handleClick
方法。v-model
:实现双向数据绑定,常用于表单元素。例如<input v-model="inputValue">
,用户在输入框中输入的值会自动同步到inputValue
变量,反之亦然。v-if
和v-show
:用于控制元素的显示与隐藏。v-if
是真正的条件渲染,会根据条件决定元素是否被添加到 DOM 中;v-show
则是通过 CSS 的display
属性来控制元素的可见性,元素始终在 DOM 中存在。
二、组件化开发
1. 组件的创建与注册
在 Vue 中,组件是构建应用的核心单元。可以使用Vue.component
方法全局注册组件,或者在单文件组件(.vue
文件)中局部注册。一个简单的全局组件示例如下:
javascript
Vue.component('my-component', {template: '<div>这是一个自定义组件</div>'
})
在单文件组件中,结构更加清晰:
vue
<template><div>这是一个局部组件</div>
</template><script>
export default {name: 'MyLocalComponent'
}
</script>
2. 组件通信
组件之间的通信是项目开发中常见的需求。
- 父子组件通信:父组件可以通过
props
向子组件传递数据,子组件通过$emit
触发自定义事件向父组件传递消息。例如,父组件:
vue
<template><div><child-component :message="parentMessage" @child-event="handleChildEvent"></child-component></div>
</template><script>
import ChildComponent from './ChildComponent.vue'export default {components: {ChildComponent},data() {return {parentMessage: '来自父组件的消息'}},methods: {handleChildEvent(payload) {console.log('收到子组件消息:', payload)}}
}
</script>
子组件:
vue
<template><div><p>{{ message }}</p><button @click="sendMessageToParent">向父组件发送消息</button></div>
</template><script>
export default {props: ['message'],methods: {sendMessageToParent() {this.$emit('child-event', '这是子组件发送的消息')}}
}
</script>
- 非父子组件通信:可以使用 Vuex 状态管理库或者事件总线(
Event Bus
)来实现。事件总线的实现方式如下:
首先创建一个事件总线实例:
javascript
// event-bus.js
import Vue from 'vue'
export const EventBus = new Vue()
然后在组件中使用:
组件 A 发送事件:
vue
<template><div><button @click="sendMessage">发送消息</button></div>
</template><script>
import { EventBus } from './event-bus.js'export default {methods: {sendMessage() {EventBus.$emit('global-event', '这是组件 A 发送的消息')}}
}
</script>
组件 B 接收事件:
vue
<template><div>接收消息的组件 B</div>
</template><script>
import { EventBus } from './event-bus.js'export default {mounted() {EventBus.$on('global-event', (message) => {console.log('组件 B 收到消息:', message)})},beforeDestroy() {EventBus.$off('global-event')}
}
</script>
三、Vue 路由
Vue Router 是 Vue.js 的官方路由管理器,用于实现单页面应用(SPA)的页面导航。
1. 路由的基本配置
首先安装 Vue Router:
bash
npm install vue-router
然后在main.js
中引入并使用:
javascript
import Vue from 'vue'
import VueRouter from 'vue-router'
import App from './App.vue'
import Home from './views/Home.vue'
import About from './views/About.vue'Vue.use(VueRouter)const routes = [{path: '/',name: 'Home',component: Home},{path: '/about',name: 'About',component: About}
]const router = new VueRouter({routes
})new Vue({router,render: h => h(App)
}).$mount('#app')
在组件中通过<router-link>
和<router-view>
来实现页面跳转和视图渲染:
vue
<template><div><router-link to="/">首页</router-link><router-link to="/about">关于</router-link><router-view></router-view></div>
</template>
2. 动态路由与路由参数
可以在路由路径中定义动态参数,例如:
javascript
const routes = [{path: '/user/:id',name: 'User',component: User}
]
在组件中通过$route.params
获取路由参数:
vue
<template><div>用户 ID:{{ $route.params.id }}</div>
</template>
3. 路由导航守卫
路由导航守卫可以用于在路由跳转前进行权限验证、页面加载前的数据获取等操作。例如:
javascript
const router = new VueRouter({routes
})router.beforeEach((to, from, next) => {// 检查用户是否登录const isLoggedIn = falseif (to.meta.requiresAuth &&!isLoggedIn) {next('/login')} else {next()}
})
在路由配置中可以设置meta
字段来指定是否需要权限验证:
javascript
const routes = [{path: '/admin',name: 'Admin',component: Admin,meta: {requiresAuth: true}}
]
四、Vuex 状态管理
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 + 库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
1. Vuex 的核心概念
- State:存储应用的状态数据,是单一数据源。例如:
javascript
const store = new Vuex.Store({state: {count: 0}
})
- Mutations:用于修改 State 的唯一途径,是同步函数。例如:
javascript
const store = new Vuex.Store({state: {count: 0},mutations: {increment(state) {state.count++}}
})
- Actions:用于处理异步操作,如发送 AJAX 请求等,通过提交 Mutations 来间接修改 State。例如:
javascript
const store = new Vuex.Store({state: {count: 0},mutations: {increment(state) {state.count++}},actions: {incrementAsync({ commit }) {setTimeout(() => {commit('increment')}, 1000)}}
})
- Getters:类似于计算属性,用于从 State 中派生出一些新的数据。例如:
javascript
const store = new Vuex.Store({state: {todos: [{ id: 1, text: '学习 Vue', done: false },{ id: 2, text: '做项目', done: true }]},getters: {doneTodos(state) {return state.todos.filter(todo => todo.done)}}
})
2. 在组件中使用 Vuex
在组件中可以通过this.$store
访问 Vuex 实例,从而获取 State、触发 Actions 等。例如:
vue
<template><div><p>计数:{{ count }}</p><button @click="increment">加 1</button><button @click="incrementAsync">异步加 1</button></div>
</template><script>
export default {computed: {count() {return this.$store.state.count}},methods: {increment() {this.$store.commit('increment')},incrementAsync() {this.$store.dispatch('incrementAsync')}}
}
</script>
五、生命周期钩子
Vue 组件在创建、更新和销毁的过程中会经历一系列的生命周期钩子函数,开发者可以在这些钩子函数中执行特定的操作。
beforeCreate
:在实例初始化之后,数据观测(data observer
)和event/watcher
事件配置之前被调用。此时,组件的选项对象还未初始化,this
指向当前组件实例,但无法访问到data
、methods
等属性。created
:在实例创建完成后被立即调用。此时,实例已完成以下配置:数据观测(data observer
)、属性和方法的运算、watch/event
事件回调。然而,挂载阶段还未开始,$el
属性目前不可见。beforeMount
:在挂载开始之前被调用:相关的render
函数首次被调用。此时,模板编译成渲染函数,但尚未挂载到页面上,this.$el
还未生成。mounted
:el
被新创建的vm.$el
替换,并挂载到实例上去之后调用该钩子。此时,组件已经渲染到页面上,可以进行 DOM 操作,获取this.$el
等。beforeUpdate
:数据更新时调用,发生在虚拟 DOM 重新渲染和打补丁之前。可以在这个钩子中进一步地更改状态,这不会触发附加的重渲染过程。updated
:由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。此时,组件的 DOM 已经更新,适合执行依赖于 DOM 的操作。beforeDestroy
:实例销毁之前调用。在这一步,实例仍然完全可用。可以在这个钩子中清除定时器、解绑事件监听器等。destroyed
:Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。
例如:
vue
<template><div>{{ message }}</div>
</template><script>
export default {data() {return {message: '初始消息'}},beforeCreate() {console.log('beforeCreate')},created() {console.log('created')},beforeMount() {console.log('beforeMount')},mounted() {console.log('mounted')},beforeUpdate() {console.log('beforeUpdate')},updated() {console.log('updated')},beforeDestroy() {console.log('beforeDestroy')},destroyed() {console.log('destroyed')}
}
</script>
当组件的数据发生变化或者组件被销毁时,相应的生命周期钩子函数会被触发。
六、过渡与动画
Vue 提供了内置的过渡效果和动画支持,可以让页面元素的切换更加平滑和生动。
1. 单元素 / 组件的过渡
使用<transition>
组件包裹需要过渡的元素或组件,并定义过渡类名。例如:
vue
<transition name="fade"><p v-if="show">这是一个过渡效果示例</p>
</transition><button @click="show =!show">切换显示</button>
在 CSS 中定义过渡类名对应的样式:
css
.fade-enter-active,
.fade-leave-active {transition: opacity 0.5s;
}
.fade-enter,
.fade-leave-to {opacity: 0;
}
2. 列表过渡
对于列表元素的过渡,可以使用<transition-group>
组件。例如:
vue
<transition-group name="list" tag="ul"><li v-for="(item, index) in list" :key="index">{{ item }}</li>
</transition-group><button @click="addItem">添加项目</button>
在 CSS 中定义列表过渡类名的样式:
css
.list-enter-active,
.list-leave-active {transition: all 0.5s;
}
.list-enter,
.list-leave-to {opacity: 0;transform: translateX(30px);
}
在 JavaScript 中定义添加项目的方法:
javascript
export default {data() {return {list: ['项目 1', '项目 2']}},methods: {addItem() {this.list.push('新项目')}}
}
七、网络请求
在 Vue 项目中,通常使用axios
库来进行网络请求。
首先安装axios
:
bash
npm install axios
然后在组件中使用:
vue
<template><div><ul><li v-for="user in users">{{ user.name }}</li></ul></div>
</template><script>
import axios from 'axios'export default {data() {return {users: []}},mounted() {axios.get('https://jsonplaceholder.typicode.com/users').then(response => {this.users = response.data}).catch(error => {console.log(error)})}
}
</script>
axios
支持多种请求方式,如GET
、POST
、PUT
、DELETE
等,并可以设置请求头、请求参数等。
八、错误处理
在 Vue 项目中,错误处理是确保应用稳定性的重要环节。
1. 组件内错误处理
可以在组件的生命周期钩子函数或者方法中使用try...catch
语句来捕获错误。例如:
vue
<template><div><button @click="fetchData">获取数据</button></div>
</template><script>
export default {methods: {fetchData() {try {// 可能出错的代码const result = someFunctionThatMayThrowError()console.log(result)} catch (error) {console.log('组件内错误:', error)}}}
}
</script>
2. 全局错误处理
使用Vue.config.errorHandler
可以设置全局的错误处理函数,用于捕获所有组件渲染和生命周期钩子函数中的错误。例如:
javascript
Vue.config.errorHandler = function (err, vm, info) {// 处理错误console.log('全局错误:', err, vm, info)
}
3. 路由导航错误处理
在 Vue Router 中,可以通过路由的onError
方法来处理路由导航过程中的错误。例如:
javascript
const router = new VueRouter({routes
})router.onError((error) => {console.log('路由导航错误:', error)
})