今年的就业形势是真的严峻,后端java的薪资直线下降,不仅薪资大幅下降,而且要求也提高了不少,很多后端java开发岗位,都要求会前端Vue框架以及一些其他前端框架。所以以后前后端都得熟练开发。以后前后端分离,人不分离的趋势怕是越来越明显了。
Vue.js(通常简称为 Vue)是一个开源的JavaScript框架,用于构建用户界面和单页面应用程序。它由前谷歌工程师尤雨溪(Evan You)创建,并在2014年首次发布。Vue的设计注重渐进式和灵活性,使得它很容易与项目的部分功能集成,或者用于构建完整的前端应用。
Vue的核心特性包括:
-
响应式数据绑定:Vue的数据处理方式是响应式的,这意味着当Vue应用中的数据变化时,视图会自动更新。
-
组件系统:Vue允许开发者通过小型、独立和可复用的组件来构建大型应用,每个组件管理自己的状态和逻辑。
-
虚拟DOM:Vue使用虚拟DOM来提高性能和重新渲染视图的效率。当应用的状态改变时,Vue会生成一个新的虚拟DOM树,并与旧的树进行比较,计算出最小的更新操作。
-
易于上手:Vue有一个清晰的、易于理解的API,使得它容易上手,并且有丰富的文档和社区支持。
-
灵活性:Vue既可以作为一个简单的视图层库使用,也可以作为一个全栈的前端框架使用,特别是当它与像Vuex(状态管理库)和Vue Router(官方路由管理器)这样的库结合时。
-
工具生态系统:Vue有一个强大的工具生态系统,包括Vue CLI(项目脚手架工具)、Vuex(状态管理)、Vue Router(路由管理器)等。
-
单文件组件 (.vue文件):Vue支持单文件组件,这使得开发者可以在一个文件中编写HTML、JavaScript和CSS,便于组织和维护。
-
服务器端渲染 (SSR):Vue支持服务器端渲染,有助于提高首屏加载性能,对SEO也有好处。
-
TypeScript支持:Vue提供了对TypeScript的官方支持,允许开发者使用TypeScript来开发Vue应用。
-
可扩展性:Vue的插件系统允许开发者扩展Vue的功能,社区中有许多第三方插件可供选择。
Vue的应用场景:
- 交互原型:快速创建具有复杂交互的前端原型。
- 单页面应用 (SPA):构建响应式、动态的单页面应用。
- 大型前端应用:构建和维护大型的、数据驱动的前端应用。
- 移动端:使用Weex(一个基于Vue的框架)开发原生渲染的移动端应用。
- 渐进式增强:为现有的项目添加前端模块。
Vue.js是一个不断发展的生态系统,它的灵活性和易用性使其成为前端开发中的一个受欢迎选择。
目录
[3. Vue组件](#3. Vue组件)
[4.Vue路由(Vue Router)](#4.Vue路由(Vue Router))
16.Vue单文件组件 (Single File Components)
[19.Vue CLI](#19.Vue CLI)
[20. Vue服务器端渲染 (SSR)](#20. Vue服务器端渲染 (SSR))
1.Vue实例
属性/方法 | 描述 | 示例 |
---|---|---|
data |
Vue实例的数据对象,用于响应式更新视图 | data: { count: 0 } |
methods |
Vue实例的方法,用于定义可复用的功能 | methods: { increment() { this.count++ } } |
computed |
计算属性,依赖于data 中的数据,并且具有缓存 |
computed: { doubledCount() { return this.count * 2 } } |
watch |
观察者,用于监听数据的变化,并在变化时执行某些操作 | watch: { count(newValue) { console.log(newValue) } } |
el |
Vue实例挂载的DOM元素选择器 | el: '#app' |
template |
Vue实例的模板,用于定义视图的结构 | template: '<div>{``{ count }}</div>' |
示例代码:
javascript
new Vue({
el: '#app',
data: {
count: 0
},
methods: {
increment() {
this.count++;
}
},
computed: {
doubledCount() {
return this.count * 2;
}
},
watch: {
count(newValue) {
console.log(newValue);
}
}
});
2.Vue模板语法
属性/指令 | 描述 | 示例 |
---|---|---|
{``{ }} |
插值表达式,用于在模板中输出数据 | {``{ message }} |
v-bind |
属性绑定,用于动态绑定HTML属性 | <img v-bind:src="imageSrc"> |
v-model |
表单输入和应用状态的双向绑定 | <input v-model="message"> |
v-on |
事件处理,用于监听DOM事件,并在事件触发时执行某些操作 | <button v-on:click="counter += 1">Click me</button> |
v-if |
条件渲染,用于根据条件决定是否渲染元素 | <p v-if="user.isLoggedIn">Welcome, {``{ user.name }}!</p> |
v-for |
列表渲染,用于基于源数据多次渲染元素或模板块 | <li v-for="item in items">{``{ item.text }}</li> |
v-once |
只渲染一次,用于性能优化,不随数据变化更新视图 | <span v-once>{``{ staticText }}</span> |
示例代码:
javascript
<div id="app">
<p>{{ message }}</p>
<img v-bind:src="imageSrc" alt="Vue logo">
<input v-model="message">
<button v-on:click="counter += 1">Click me</button>
<p v-if="user.isLoggedIn">Welcome, {{ user.name }}!</p>
<ul>
<li v-for="item in items">{{ item.text }}</li>
</ul>
<span v-once>{{ staticText }}</span>
</div>
<script>
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!',
imageSrc: 'path/to/vue.png',
counter: 0,
user: {
isLoggedIn: true,
name: 'John Doe'
},
items: [
{ text: 'Item 1' },
{ text: 'Item 2' },
{ text: 'Item 3' }
],
staticText: 'This will not change'
}
});
</script>
3. Vue组件
属性/方法 | 描述 | 示例 |
---|---|---|
components |
定义组件,用于创建可复用的自定义元素 | components: { 'my-component': MyComponent } |
props |
子组件接收从父组件传递过来的数据 | <child-component :my-prop="someValue"></child-component> |
customDirectives |
自定义指令,用于封装对DOM的底层操作 | directives: { 'my-directive': { bind: function() { ... } } } |
mixins |
混入,允许组件复用可复用的代码 | mixins: [myMixin] |
extends |
继承,允许组件继承其他组件的选项 | extends: AnotherComponent |
provide/inject |
依赖注入,用于实现跨组件的通信 | provide: { myThing: 'some value' } , inject: ['myThing'] |
slots |
插槽,用于分发内容到组件内部 | <template v-slot="slotProps">...</template> |
示例代码:
javascript
// 定义一个组件
Vue.component('my-component', {
props: ['myProp'],
template: '<div>A custom component prop: {{ myProp }}</div>'
});
// 使用组件
new Vue({
el: '#app',
data: {
myData: 'Hello from parent'
}
});
// 在父组件中使用子组件并传递数据
<div id="app">
<my-component :my-prop="myData"></my-component>
</div>
javascript
// 定义一个混入
var myMixin = {
created: function () {
console.log('Mixin is mixed in!');
}
};
// 定义一个组件使用混入
var ComponentWithMixin = Vue.extend({
mixins: [myMixin],
data: function () {
return {
message: 'Hello from component'
};
}
});
javascript
// 定义一个自定义指令
Vue.directive('my-directive', {
bind: function (el, binding, vnode) {
el.textContent = 'bound by directive';
}
});
4.Vue路由(Vue Router)
属性/方法 | 描述 | 示例 |
---|---|---|
routes |
定义应用的路由配置 | routes: [{ path: '/home', component: Home }] |
mode |
定义路由的模式,如hash或history | mode: 'history' |
base |
应用的基础路径 | base: '/my-app/' |
linkExactActiveClass |
配置默认的激活链接CSS类 | linkExactActiveClass: 'active-link' |
scrollBehavior |
控制路由跳转时页面滚动的行为 | scrollBehavior(to, from, savedPosition) { return { x: 0, y: 0 } } |
beforeEach |
路由守卫,用于全局路由守卫 | beforeEach: (to, from, next) => { next() } |
component |
定义路由的组件 | component: () => import('./views/MyView.vue') |
示例代码:
javascript
// Vue Router 3.x
const routes = [
{
path: '/',
component: Home,
},
{
path: '/about',
component: About,
},
// ...
];
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes,
});
new Vue({
router,
render: h => h(App),
}).$mount('#app');
javascript
// 路由守卫示例
router.beforeEach((to, from, next) => {
if (to.matched.some(record => record.meta.requiresAuth)) {
if (!auth.check()) {
next({
path: '/login',
query: { redirect: to.fullPath }
});
} else {
next();
}
} else {
next();
}
});
5.Vue状态管理(Vuex)
概念/方法 | 描述 | 示例 |
---|---|---|
state |
应用的状态,是响应式的 | state: { count: 0 } |
getters |
从state中派生出一些状态,相当于计算属性 | getters: { doubleCount: state => state.count * 2 } |
mutations |
用于同步地改变state中的状态 | mutations: { increment(state) { state.count++ } } |
actions |
类似于mutation,但可以执行异步操作 | actions: { incrementAsync({ commit }) { setTimeout(() => { commit('increment') }, 1000) } } |
modules |
允许将单一的store拆分成多个模块 | modules: { moduleA, moduleB } |
mapState |
辅助函数,用于将state映射到组件的计算属性 | ['count'].mapState(store) |
mapGetters |
辅助函数,用于将getters映射到组件的计算属性 | { doubleCount }.mapGetters(store) |
mapActions |
辅助函数,用于将actions映射到组件的方法 | ['incrementAsync'].mapActions(store) |
示例代码:
javascript
// 创建一个新的store实例
const store = new Vuex.Store({
state: {
count: 0
},
getters: {
doubleCount: state => state.count * 2
},
mutations: {
increment(state) {
state.count++;
}
},
actions: {
incrementAsync({ commit }) {
setTimeout(() => {
commit('increment');
}, 1000);
}
}
});
// 在组件中使用
new Vue({
store,
// ...
});
javascript
// 组件内使用mapState
export default {
computed: {
...mapState({
count: state => state.count,
doubledCount: state => state.doubleCount
})
}
};
javascript
// 组件内使用mapGetters、mapActions
export default {
computed: {
...mapGetters(['doubleCount'])
},
methods: {
...mapActions(['incrementAsync'])
}
};
6,Vue事件处理
指令 | 描述 | 示例 |
---|---|---|
v-on 或 @ |
监听DOM事件,并在事件触发时执行表达式或方法 | <button v-on:click="counter += 1">Click me</button> |
.stop |
阻止事件冒泡 | <div @click.stop="doSomething">Click here</div> |
.prevent |
阻止默认事件行为 | <a @click.prevent="doSomething" href="#foo">Don't go anywhere</a> |
.capture |
使用事件捕获模式 | <div @click.capture="doThis">Capture me</div> |
.self |
只有当事件的target是绑定的元素本身时才会触发 | <div @click.self="doThat">Click on me</div> |
.once |
事件将只会触发一次 | <button @click.once="doThisOnce">Do this once</button> |
.native |
监听组件根元素的原生事件 | <MyComponent @click.native="doSomething" /> |
示例代码:
javascript
<!-- 使用v-on监听点击事件 -->
<button v-on:click="counter += 1">增加</button>
<!-- 使用@作为v-on的缩写 -->
<button @click="counter += 1">增加</button>
<!-- 使用修饰符.stop -->
<div @click.stop="doSomething">点击这里</div>
<!-- 使用修饰符.prevent -->
<a @click.prevent="doSomething" href="#foo">不要跳转</a>
<!-- 使用修饰符.capture -->
<div @click.capture="doThis">捕获我</div>
<!-- 使用修饰符.self -->
<div @click.self="doThat">点击我</div>
<!-- 使用修饰符.once -->
<button @click.once="doThisOnce">只执行一次</button>
<!-- 使用修饰符.native监听组件的点击事件 -->
<my-component @click.native="handleClick" />
javascript
// 在Vue实例中定义事件处理函数
new Vue({
data: {
counter: 0
},
methods: {
doSomething() {
console.log('Something happened!');
},
doThis() {
console.log('This was triggered at the capture phase!');
},
doThat() {
console.log('This was triggered and the target is the element itself!');
},
doThisOnce() {
console.log('This will only be called once!');
},
handleClick() {
console.log('This was triggered on the component!');
}
}
});
7.Vue计算属性与侦听器
特性 | 描述 | 示例 |
---|---|---|
computed |
计算属性,依赖于响应式数据,并且具有缓存 | computed: { computedValue: (state) => state.someData * 2 } |
watch |
侦听器,用于观察数据的变化,可以执行异步操作或执行较为复杂的逻辑 | watch: { watchedProperty: (newValue, oldValue) => { /* 操作 */ } } |
immediate |
侦听器立即执行 | watch: { watchedProperty: { handler(newValue, oldValue) { /* 操作 */ }, immediate: true } } |
示例代码:
javascript
// 创建Vue实例
new Vue({
data: {
count: 0
},
computed: {
// 计算属性,依赖于count
doubledCount: function () {
return this.count * 2;
}
},
watch: {
// 侦听器,观察count的变化
count: function (newValue, oldValue) {
console.log(`count changed from ${oldValue} to ${newValue}`);
}
}
});
javascript
// 使用计算属性
<div>{{ doubledCount }}</div>
// 使用侦听器
<div v-if="count > 10">Count is above 10</div>
javascript
// 侦听器立即执行
new Vue({
data: {
watchedProperty: ''
},
watch: {
watchedProperty: {
handler(newValue, oldValue) {
// 处理逻辑
},
immediate: true
}
}
});
8.Vue过渡与动画
特性 | 描述 | 示例 |
---|---|---|
transition |
包裹元素或组件,提供过渡效果 | <transition><div>...</div></transition> |
transition-group |
用于列表渲染,提供列表项的过渡效果 | <transition-group><div v-for="item in items" :key="item.id">...</div></transition-group> |
v-show |
切换CSS display 属性,用于简单的显示/隐藏 |
<div v-show="isVisible">Hide or Show</div> |
v-animate |
第三方库,提供更丰富的CSS动画 | <div v-animate="{ y: '+=50' }">Animate me</div> |
transition-mode |
指定过渡效果的模式,如in-out 、out-in |
<transition name="fade" mode="out-in">...</transition> |
transition-hooks |
过渡钩子,如on-enter 、on-leave 等 |
<transition @after-enter="onAfterEnter">...</transition> |
key |
唯一标识符,用于控制组件的切换 | <div v-for="item in items" :key="item.id">...</div> |
示例代码:
javascript
<!-- 使用transition封装元素 -->
<transition name="fade">
<div v-if="show">I fade in and out</div>
</transition>
<!-- 使用transition-group管理列表项的过渡 -->
<transition-group name="slide">
<div v-for="item in items" :key="item.id" class="item">{{ item.text }}</div>
</transition-group>
<!-- 使用v-show切换显示 -->
<div v-show="isVisible">I will show and hide without transitions</div>
<!-- 使用key控制列表项的唯一性 -->
<div v-for="item in items" :key="item.id">{{ item.text }}</div>
javascript
// 定义Vue实例
new Vue({
data: {
show: true,
isVisible: true,
items: [
{ id: 1, text: 'First' },
// ...
]
},
methods: {
onAfterEnter(el) {
// Do something after the enter transition finishes
}
}
});
9.Vue表单输入绑定
指令 | 描述 | 示例 |
---|---|---|
v-model |
表单输入和应用状态的双向绑定 | <input v-model="message" placeholder="Enter message"> |
v-bind |
动态绑定表单控件的值或其他属性 | <input v-bind:value="message" v-bind:placeholder="placeholder"> |
v-on |
监听输入事件或其他事件,并在事件触发时执行表达式或方法 | <input v-on:input="message = $event.target.value"> |
.lazy |
修饰符,输入的值在失去焦点时才更新 | <input v-model.lazy="message"> |
.number |
修饰符,输入的值会被转换为Number 类型 | <input v-model.number="age" type="number"> |
.trim |
修饰符,输入的值会过滤掉首尾的空白字符 | <input v-model.trim="message"> |
v-if 、v-else-if 、v-else |
条件渲染表单控件 | <template v-if="isEditing"><input v-model="item.value"></template> |
示例代码:
javascript
<!-- 使用v-model实现双向绑定 -->
<input v-model="message" placeholder="Enter message">
<!-- 使用v-bind和v-on实现单向绑定 -->
<input v-bind:value="message" v-on:input="message = $event.target.value">
<!-- 使用.lazy修饰符 -->
<input v-model.lazy="message" placeholder="Lazy update">
<!-- 使用.number修饰符 -->
<input v-model.number="age" type="number">
<!-- 使用.trim修饰符 -->
<input v-model.trim="message" placeholder="Trim whitespace">
<!-- 使用条件渲染 -->
<template v-if="isEditing">
<input v-model="item.value">
</template>
javascript
// 定义Vue实例
new Vue({
data: {
message: '',
age: 0,
isEditing: true,
item: { value: 'some value' }
}
});
10.Vue类与样式绑定
指令 | 描述 | 示例 |
---|---|---|
class |
绑定一个或多个CSS类到元素上 | <div :class="{ active: isActive, 'text-danger': hasError }"></div> |
style |
绑定内联样式到元素上 | <div :style="{ color: activeColor, fontSize: fontSize + 'px' }"></div> |
:class |
绑定对象或数组到元素的class属性上 | <div :class="classObject"></div> |
:style |
绑定对象或字符串到元素的style属性上 | <div :style="styleObject"></div> |
.sync |
修饰符,用于创建更新父组件数据的语法糖 | <my-component :my-prop.sync="parentValue"> |
示例代码:
javascript
<!-- 使用三元运算符绑定类 -->
<div :class="isActive ? 'active' : ''"></div>
<!-- 使用对象字面量绑定多个类 -->
<div :class="{ active: isActive, 'text-danger': hasError }"></div>
<!-- 使用数组语法绑定多个类 -->
<div :class="[isActive ? 'active' : '', errorClass]"></div>
<!-- 使用动态样式绑定 -->
<div :style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
<!-- 使用.sync修饰符 -->
<comp :value.sync="parentValue"></comp>
javascript
// 定义Vue实例
new Vue({
data: {
isActive: true,
hasError: false,
errorClass: 'text-error',
activeColor: 'red',
fontSize: 14,
parentValue: 'parent data'
}
});
11.Vue生命周期钩子
生命周期钩子 | 描述 | 使用场景 |
---|---|---|
beforeCreate |
实例被创建之后被调用,在数据观测和事件/侦听器配置之前 | 可以在数据变化之前执行一些操作 |
created |
实例创建后被调用,数据观测和事件/侦听器已经配置 | 数据初始化,执行异步操作 |
beforeMount |
挂载开始前被调用,在$el 被创建和挂载之前 |
配置需要在挂载之前执行的逻辑 |
mounted |
挂载完成后被调用,vm.$el 可用 |
执行依赖于DOM的操作,如使用第三方库 |
beforeUpdate |
数据更新时调用,发生在虚拟DOM重新渲染和打补丁之前 | 访问和修改现有DOM |
updated |
由于数据更改导致的虚拟DOM重新渲染和打补丁后被调用 | 执行依赖于更新后DOM的操作 |
beforeDestroy |
实例销毁前被调用 | 清理工作,如移除自定义的事件监听器 |
destroyed |
实例销毁后被调用 | 进行一些清理操作,如删除定时器 |
activated |
被用在keep-alive 组件中,当组件被激活时调用 |
用于获取数据或重新计算数据 |
deactivated |
被用在keep-alive 组件中,当组件被停用时调用 |
用于取消数据获取或停止定时器 |
示例代码:
javascript
new Vue({
data: {
count: 1
},
beforeCreate() {
console.log('Before Create');
},
created() {
console.log('Created');
},
beforeMount() {
console.log('Before Mount');
},
mounted() {
console.log('Mounted');
},
beforeUpdate() {
console.log('Before Update');
},
updated() {
console.log('Updated');
},
beforeDestroy() {
console.log('Before Destroy');
},
destroyed() {
console.log('Destroyed');
},
activated() {
console.log('Activated');
},
deactivated() {
console.log('Deactivated');
}
});
javascript
<!-- 使用keep-alive缓存组件 -->
<keep-alive>
<component :is="currentComponent"></component>
</keep-alive>
12.Vue混入 (Mixins)
混入选项 | 描述 | 示例 |
---|---|---|
data |
混入对象中可以包含一个data 函数,返回一个对象,该对象将与Vue实例的data 对象合并 |
data() { return { myOption: '' } } |
methods |
混入对象可以包含方法,这些方法将与Vue实例的methods 合并 |
methods: { myMethod() { console.log('Mixin method called') } } |
computed |
混入对象可以包含计算属性,这些计算属性将与Vue实例的computed 合并 |
computed: { myComputed() { return this.myOption.length } } |
watch |
混入对象可以包含观察者,这些观察者将与Vue实例的watch 合并 |
watch: { myOption(newValue) { console.log(newValue) } } |
components |
混入对象可以包含组件定义,这些组件将与Vue实例的components 合并 |
components: { MyComponent } |
directives |
混入对象可以包含自定义指令,这些指令将与Vue实例的directives 合并 |
directives: { myDirective } |
beforeCreate |
混入对象可以包含生命周期钩子,这些钩子将按照混入的顺序执行 | beforeCreate() { console.log('Mixin beforeCreate') } |
示例代码:
javascript
// 定义一个混入对象
const myMixin = {
data() {
return {
mixinData: ''
};
},
created() {
console.log('Mixin created hook called');
},
methods: {
mixinMethod() {
console.log('Mixin method called');
}
}
};
// 创建Vue实例,使用混入
new Vue({
mixins: [myMixin],
data: {
dataProp: 'data property'
},
created() {
console.log('Vue instance created hook called');
}
});
13.Vue自定义指令
钩子函数 | 描述 | 参数 |
---|---|---|
bind |
只调用一次,指令第一次绑定到元素时调用,用这个钩子函数可以定义一个在绑定时执行一次的初始化操作 | el , binding , vnode , oldVnode |
inserted |
被绑定元素的父元素插入到文档中时调用 | el , binding , vnode , oldVnode |
update |
指令所在的组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前,指令的值可能发生了变化,但是不能依赖于 VNode 的子节点 | el , binding , vnode , oldVnode |
componentUpdated |
指令所在组件的 VNode 及其子 VNode 全部更新后调用 | el , binding , vnode , oldVnode |
unbind |
只调用一次,指令与元素解绑时调用 | el , binding , vnode , oldVnode |
示例代码:
javascript
// 定义一个自定义指令 `v-focus`
Vue.directive('focus', {
// 当绑定元素插入到 DOM 中时...
inserted: function (el) {
// 聚焦元素
el.focus();
}
});
javascript
<!-- 使用自定义指令 -->
<input v-focus>
javascript
// 一个更复杂自定义指令的示例,用于设置元素的拖拽能力
Vue.directive('drag', {
bind(el, binding) {
el.style.cursor = 'pointer';
el.draggable = true;
el.addEventListener('dragstart', (e) => {
e.dataTransfer.effectAllowed = 'move';
e.dataTransfer.setData('text/plain', binding.value);
});
},
unbind(el) {
el.draggable = false;
el.style.cursor = '';
el.removeEventListener('dragstart', null);
}
});
javascript
<!-- 使用复杂自定义指令 -->
<div v-drag="dragData">拖拽我</div>
14.Vue过滤器 (Filters)
特性 | 描述 | 示例 |
---|---|---|
文本格式化 | 过滤器可以用在模板中,用于文本格式化 | `{{ message |
可链式调用 | 过滤器可以链接多个,按顺序从左到右执行 | `{{ message |
混入Vue实例 | 过滤器可以定义在Vue实例的filters 选项中 |
filters: { capitalize: (value) => value.toUpperCase() } |
全局过滤器 | 可以使用Vue.filter 注册全局过滤器 |
Vue.filter('reverse', (value) => value.split('').reverse().join('')) |
动态参数 | 过滤器可以接收参数,甚至多个参数 |
示例代码:
javascript
// 定义一个全局过滤器
Vue.filter('capitalize', function (value) {
if (!value) return '';
value = value.toString();
return value.charAt(0).toUpperCase() + value.slice(1);
});
// 在Vue实例中定义过滤器
new Vue({
filters: {
reverse: function (value) {
return value.split('').reverse().join('');
}
}
});
javascript
<!-- 使用全局过滤器 -->
<p>{{ message | capitalize }}</p>
<!-- 使用Vue实例过滤器 -->
<p>{{ message | reverse }}</p>
<!-- 链式使用过滤器 -->
<p>{{ message | capitalize | reverse }}</p>
javascript
// 定义一个接受参数的过滤器
Vue.filter('filterA', function (value, arg1, arg2) {
// 执行一些操作,使用参数arg1和arg2
return value;
});
javascript
<!-- 使用带参数的过滤器 -->
<p>{{ message | filterA('param1', 'param2') }}</p>
15.Vue错误处理
特性 | 描述 | 示例 |
---|---|---|
全局错误处理 | 使用Vue.config.errorHandler 配置项可以全局捕获未捕获的异常 |
Vue.config.errorHandler = function (err, vm, info) { /* 处理错误 */ } |
生命周期钩子错误处理 | 在生命周期钩子中捕获错误,例如created 或mounted |
created() { try { /* 代码 */ } catch (error) { /* 错误处理 */ } } |
事件处理错误处理 | 使用v-on 的error 修饰符捕获事件处理中的错误 |
<button v-on:click="doSomething" v-on:error="handleError">Click me</button> |
Promise错误处理 | 在执行异步操作时,使用catch 捕获Promise中的错误 |
asyncSomeFunction().catch(error => { /* 处理错误 */ }) |
组件方法错误处理 | 在组件的方法中使用try...catch 语句捕获错误 |
methods: { doSomething() { try { /* 代码 */ } catch (error) { /* 错误处理 */ } } } |
示例代码:
javascript
// 全局错误处理
Vue.config.errorHandler = function (err, vm, info) {
console.error('Global error handler:', err, vm, info);
};
javascript
// 生命周期钩子中的错误处理
new Vue({
created() {
try {
// 假设这里是初始化代码
} catch (error) {
console.error('Error in created hook:', error);
}
}
});
javascript
// 事件处理中的错误处理
new Vue({
methods: {
doSomething() {
// 执行一些操作
},
handleError(error) {
console.error('Error in event handling:', error);
}
}
});
javascript
<!-- 使用v-on:error修饰符 -->
<button v-on:click="doSomething" v-on:error="handleError">Click me</button>
javascript
// Promise错误处理
fetchData().then(data => {
// 处理数据
}).catch(error => {
console.error('Error in fetching data:', error);
});
16.Vue单文件组件 (Single File Components)
特性 | 描述 | 示例 |
---|---|---|
结构化 | Vue单文件组件由三个主要部分组成:模板(template )、JavaScript逻辑(script )和样式(style ) |
<template>...</template> <script>...</script> <style>...</style> |
组件复用 | 可以在单文件组件中定义可复用的自定义组件 | <my-component></my-component> |
样式作用域 | 单文件组件的样式默认仅应用于当前组件,但可以配置为全局作用域 | <style scoped> |
导入模块 | 可以在script 标签内导入其他模块或Vue插件 |
import { mapState } from 'vuex'; |
模板语法 | 模板中可以使用Vue的指令和插值表达式 | {``{ message }} , v-if |
计算属性和侦听器 | 可以在script 中定义计算属性和侦听器 |
computed , watch |
混入 | 可以在script 中使用混入来共享可复用的逻辑 |
mixins |
自定义指令 | 可以在script 中定义自定义指令 |
directives |
组件定义 | 使用export default 导出组件选项对象 |
export default { ... } |
示例代码:
javascript
<template>
<div>
<h1>{{ greeting }}</h1>
</div>
</template>
<script>
export default {
data() {
return {
greeting: 'Hello Vue!'
};
}
};
</script>
<style scoped>
h1 {
color: #42b983;
}
</style>
javascript
<!-- 使用计算属性 -->
<template>
<div>
<p>Computed message: {{ reversedMessage }}</p>
</div>
</template>
<script>
export default {
data() {
return {
message: 'Hello from Vue!'
};
},
computed: {
reversedMessage() {
return this.message.split('').reverse().join('');
}
}
};
</script>
javascript
<!-- 使用混入 -->
<template>
<div>
<p>Mixin data: {{ mixinData }}</p>
</div>
</template>
<script>
import myMixin from './myMixin';
export default {
mixins: [myMixin],
data() {
return {
uniqueData: 'I am unique!'
};
}
};
</script>
17.Vue插件
概念 | 描述 | 示例 |
---|---|---|
定义插件 | Vue插件可以提供自定义功能,它是一个可以增强Vue核心功能的JavaScript对象 | function MyPlugin() { ... } |
全局插件 | 通过Vue.use() 使用,可以在Vue应用启动前安装全局插件 |
Vue.use(MyPlugin) |
选项式插件 | 插件可以提供额外的配置选项,这些选项将与Vue实例的选项合并 | Vue.use(MyPlugin, { someOption: true }) |
混入插件 | 插件可以提供一个混入对象,该对象将被应用到每个Vue实例中 | MyPlugin: { directives: { myDirective } } |
函数式插件 | 插件也可以是一个函数,接受Vue作为参数,允许直接在Vue上添加全局功能 | function (Vue, options) { ... } |
自定义指令插件 | 插件可以定义自定义指令,这些指令可以跨组件使用 | Vue.directive('my-directive', { bind: function() { ... } }) |
示例代码:
javascript
// 定义一个Vue插件
function MyPlugin() {
// 插件逻辑
}
// 安装全局插件
Vue.use(MyPlugin);
javascript
// 插件也可以接收选项
Vue.use(MyPlugin, { someOption: true });
javascript
// 插件提供混入
const myMixinPlugin = {
directives: {
myDirective: {
bind(el, binding, vnode) {
// 自定义指令逻辑
}
}
}
};
Vue.use(myMixinPlugin);
javascript
// 函数式插件
const MyFunctionalPlugin = (Vue, options) => {
// 直接添加全局功能
Vue.prototype.$myFeature = function() {
// ...
};
};
Vue.use(MyFunctionalPlugin);
18.Vue响应式系统
概念 | 描述 | 示例 |
---|---|---|
响应式数据 | Vue的数据通过data 属性暴露给模板,当数据变化时,视图将自动更新 |
data: { a: 1 } |
响应式原理 | Vue使用Object.defineProperty (Vue 2.x)或Proxy(Vue 3.x)实现响应式系统 |
- |
依赖收集 | Vue在渲染过程中收集依赖,当依赖项发生变化时,视图将重新渲染 | - |
计算属性 | 计算属性依赖响应式数据,并且只有当依赖项变化时才会重新计算 | computed: { computedValue: (state) => state.a * 2 } |
侦听器 | 侦听器允许在数据变化时执行任何代码,包括异步操作 | watch: { a(newValue) { console.log(newValue); } } |
组件更新 | Vue的响应式系统确保组件在数据变化时高效更新 | <template> <div>{``{ a }}</div> </template> |
不可观测对象 | Vue默认情况下不追踪函数和Symbol类型的属性,也不追踪对象的原型链 | - |
示例代码:
javascript
// 创建Vue实例
new Vue({
el: '#app',
data: {
a: 1
},
computed: {
computedValue() {
return this.a * 2;
}
},
watch: {
a(newValue) {
console.log(`a is now: ${newValue}`);
}
}
});
javascript
<!-- Vue实例的挂载点 -->
<div id="app">
<div>{{ computedValue }}</div>
</div>
19.Vue CLI
特性 | 描述 | 示例 |
---|---|---|
项目脚手架 | Vue CLI是一个官方的Vue项目脚手架工具,可以快速生成Vue项目的基础代码结构 | vue create my-project |
插件生态系统 | Vue CLI支持丰富的插件生态系统,可以扩展Vue CLI的功能 | vue add element |
项目构建 | Vue CLI提供了一套构建系统,可以用于构建Vue应用,优化输出的应用程序以供生产部署 | vue build |
热重载 | 开发过程中,Vue CLI支持热重载,可以在不刷新整个页面的情况下更新组件 | - |
单元测试 | Vue CLI可以配置单元测试,使用Jest、Mocha等测试框架 | vue test:unit |
端到端测试 | Vue CLI支持配置端到端测试,使用Nightwatch、Cypress等工具 | vue test:e2e |
版本控制 | Vue CLI项目通常包含.gitignore 文件,推荐使用Git进行版本控制 |
- |
依赖管理 | Vue CLI使用npm或yarn作为依赖管理工具,管理项目中的包和库 | npm install 或 yarn add |
示例代码:
创建一个新的Vue CLI项目
vue create my-project
添加一个插件到现有项目
vue add element
运行构建命令,输出将用于生产环境
vue build
运行单元测试
vue test:unit
运行端到端测试
vue test:e2e
20. Vue服务器端渲染 (SSR)
特性 | 描述 | 示例 |
---|---|---|
同构渲染 | Vue支持在服务器端渲染Vue组件,生成HTML字符串,然后传送给客户端 | - |
Nuxt.js | 一个基于Vue.js的框架,它使用Vue.js的特点构建更高效,更易于维护的应用 | nuxt generate |
Vue CLI插件 | Vue CLI提供了一个插件来为Vue应用添加服务器端渲染支持 | vue add server |
性能 | 服务器端渲染可以提高首屏加载速度,对SEO优化有帮助 | - |
跨平台 | 可以在Node.js环境中使用任何支持Node.js的平台进行服务器端渲染 | - |
状态转移 | 可以在服务器端和客户端之间转移状态,以保持应用状态的一致性 | context.state = data |
API支持 | 服务器端可以访问Node.js生态系统中的API,如文件系统、数据库等 | - |
示例代码:
javascript
// 使用Vue CLI的SSR插件创建的服务器端渲染应用
const VueSSRServerPlugin = require('vue-server-renderer/server-plugin');
const VueSSRClientPlugin = require('vue-server-renderer/client-plugin');
module.exports = {
// ...
configureWebpack: {
plugins: [
// 为服务器端渲染配置插件
new VueSSRServerPlugin(),
// 为客户端构建配置插件
new VueSSRClientPlugin()
]
}
};
javascript
// 服务器端渲染入口文件
const createApp = require('./src/entry-server')
const server = new VueServerRenderer(createApp)
.listen(3000, () => {
console.log('Server started on port 3000');
});
javascript
// Nuxt.js项目中,可以使用nuxt generate命令来生成静态的预渲染页面
nuxt generate
21.Vue异步组件
特性 | 描述 | 示例 |
---|---|---|
动态导入 | Vue允许以异步方式导入组件,有助于代码分割和按需加载 | const AsyncComponent = () => import('./components/AsyncComponent.vue') |
加载状态 | 当组件被异步加载时,Vue可以显示一个加载状态 | <AsyncComponent loading="Loading..."> |
错误处理 | 如果组件加载失败,Vue可以提供一个错误状态 | <AsyncComponent error="Error loading component"> |
显式加载 | 可以显式地控制组件的加载状态 | asyncComponent().then((resolved) => { /* 使用resolved组件 */ }) |
命名视图 | 异步组件可以与Vue的<router-view> 结合使用,实现路由的异步加载 |
- |
示例代码:
javascript
// 定义异步组件
const AsyncComponent = () => ({
// 需要返回一个Promise,这样Vue就知道如何等待加载完成
component: import('./components/AsyncComponent.vue'),
// 一个额外的加载状态
loading: LoadingComponent,
// 一个额外的错误状态
error: ErrorComponent,
// 延迟时间,超出这个时间如果还没有加载成功的话就显示错误状态
delay: 200
});
javascript
<!-- 使用异步组件 -->
<AsyncComponent loading="Loading..." error="Error!"></AsyncComponent>
javascript
// 显式加载异步组件
const asyncComponent = async () => {
try {
const { default: AsyncComponent } = await import('./components/AsyncComponent.vue');
return AsyncComponent;
} catch (error) {
console.error('Failed to load async component', error);
}
};
22.Vue原型链
概念 | 描述 | 示例 |
---|---|---|
原型继承 | Vue实例继承自Vue.prototype,可以访问Vue添加的方法和属性 | Vue.prototype.$http = axios; |
实例属性 | Vue实例拥有一系列属性,如$el , $data , $options 等,都挂载在Vue.prototype上 |
this.$data |
自定义方法 | 开发者可以在Vue.prototype上定义全局方法,这些方法将可用于所有Vue实例 | Vue.prototype.$myMethod = function() { ... }; |
混入选项 | 通过混入(mixins),可以向Vue原型添加方法、计算属性、数据等 | { methods: { myMixinMethod() { ... } } } |
插件扩展 | 插件也可以向Vue.prototype添加方法 | MyPlugin(Vue, options) { Vue.prototype.$myPluginMethod = function() { ... } } |
示例代码:
javascript
// 在Vue原型上添加一个全局方法
Vue.prototype.$myGlobalMethod = function() {
console.log('This is a global method');
};
// 在Vue实例中使用全局方法
new Vue({
// ...
created() {
this.$myGlobalMethod(); // 输出: This is a global method
}
});
javascript
// 定义一个混入对象,添加到Vue原型上
const myMixin = {
methods: {
myMixinMethod() {
console.log('This method is mixed in');
}
}
};
// 使用混入
new Vue({
mixins: [myMixin],
created() {
this.myMixinMethod(); // 输出: This method is mixed in
}
});
javascript
// 通过插件向Vue原型添加方法
function MyPlugin(Vue, options) {
Vue.prototype.$myPluginMethod = function() {
console.log('This method is added by the plugin');
};
}
// 使用插件
Vue.use(MyPlugin);
new Vue({
created() {
this.$myPluginMethod(); // 输出: This method is added by the plugin
}
});
23.Vue性能优化
策略 | 描述 | 示例 |
---|---|---|
计算属性 | 使用计算属性来描述一个值是如何根据组件中其他数据计算得来的 | computed: { filteredList() { return this.items.filter(item => item.isVisible) } } |
侦听器 | 使用侦听器来观察数据的变化,仅在必要时执行操作 | watch: { user(newValue) { this.fetchUserData(newValue) } } |
事件防抖 | 对输入框的输入事件使用防抖,避免过快的连续触发 | v-on:input="debounceFetchData" |
去抖动函数 | 创建一个去抖动函数,用于限制触发频率 | methods: { debounceFetchData: _.debounce(() => { this.fetchData() }, 500) } |
惰性加载 | 使用惰性加载来按需加载组件,减少初始下载体积 | const MyLargeComponent = () => import('./components/MyLargeComponent.vue') |
代码分割 | 使用Webpack等打包工具的代码分割功能来实现按需加载 | SplitChunksPlugin |
使用v-show /v-if |
根据需要使用v-show 或v-if 来控制元素的渲染 |
<template v-if="show">...</template> |
避免不必要的响应式属性 | 避免将大量数据或复杂对象作为响应式属性,这可能导致性能问题 | - |
使用track-by |
在使用v-for 循环列表时,使用track-by 来优化列表渲染性能 |
<template v-for="item in items" :key="item.id">...</template> |
示例代码:
javascript
// 使用计算属性避免在模板中写复杂的逻辑
computed: {
filteredList() {
return this.items.filter(item => item.isVisible);
}
}
javascript
// 使用防抖函数来限制输入事件的触发频率
methods: {
debounceFetchData: _.debounce(() => {
this.fetchData();
}, 500)
}
javascript
// 使用惰性加载来减少初始下载体积
const MyLargeComponent = () => import('./components/MyLargeComponent.vue');
javascript
<!-- 使用v-for和track-by优化列表渲染 -->
<template v-for="item in items" :key="item.id">
<div>{{ item.text }}</div>
</template>
24.Vue国际化 (i18n)
特性 | 描述 | 示例 |
---|---|---|
国际化插件 | Vue i18n是一个国际化插件,用于Vue应用的多语言支持 | vue i18n |
本地化资源 | 可以定义多语言的本地化资源文件,如JSON格式 | { message: { hello: 'Hello World' } } |
插值表达式 | 在模板中使用插值表达式来输出翻译文本 | {``{ $t('message.hello') }} |
动态关键字 | 可以使用动态关键字来动态选择翻译文本 | {``{ $t( message.${dynamicKey}) }} |
格式化数字和日期 | 可以格式化数字和日期,以符合不同地区的格式要求 | {``{ number_format(123456.789) }} , {``{ date_format(date) }} |
自定义过滤器 | 可以创建自定义过滤器来进行特定的文本转换 | `<template>{{ text |
短语插值 | 可以对翻译短语进行插值,传递变量或表达式 | {``{ $t('message.with_param', { param: 'value' }) }} |
命名视图 | 可以在路由中使用命名视图,以支持不同语言的URL路径 | <router-view name="localized-outlet" :key="locale"/> |
示例代码:
javascript
// 定义本地化资源
const messages = {
en: {
message: {
hello: 'Hello World'
}
},
fr: {
message: {
hello: 'Bonjour le monde'
}
}
};
// Vue i18n实例化
const i18n = new VueI18n({
locale: 'en', // 设置地区
messages, // 设置地区信息
});
// 创建Vue实例
new Vue({
i18n,
// ...
});
javascript
<!-- 使用插值表达式 -->
<p>{{ $t('message.hello') }}</p>
<!-- 使用动态关键字 -->
<p>{{ $t(`message.${dynamicKey}`) }}</p>
<!-- 使用短语插值 -->
<p>{{ $t('message.with_param', { param: 'value' }) }}</p>
javascript
// 格式化过滤器
Vue.filter('capitalize', function (value) {
if (!value) return '';
value = value.toString();
return value.charAt(0).toUpperCase() + value.slice(1);
});
25.Vue单元测试
特性 | 描述 | 示例 |
---|---|---|
测试框架 | Vue应用可以使用如Jest、Mocha等测试框架进行单元测试 | jest 或 mocha |
Vue Test Utils | 官方提供的Vue Test Utils库,包含工具和自定义断言,用于测试Vue组件 | @vue/test-utils |
快照测试 | 快照测试允许你检查组件渲染的输出是否符合预期 | expect(component).toMatchSnapshot() |
模拟数据 | 可以模拟数据来测试组件的行为,而不需要实际的后端服务 | const mockData = { items: [] }; |
组件测试 | 测试Vue组件的行为,包括渲染、生命周期钩子、事件处理等 | mount(Component) |
浅渲染 | 浅渲染只挂载组件本身,不渲染其子组件 | shallowMount(Component) |
模拟浏览器环境 | 在Node.js环境中模拟浏览器API,如DOM操作 | jsdom |
覆盖率 | 测试覆盖率工具帮助了解测试覆盖了代码的哪些部分 | istanbul 或 nyc |
示例代码:
javascript
// 使用Jest和Vue Test Utils进行组件测试
import { mount } from '@vue/test-utils';
import MyComponent from '@/components/MyComponent.vue';
describe('MyComponent', () => {
it('renders correctly', () => {
const wrapper = mount(MyComponent, {
propsData: { /* 模拟props */ }
});
expect(wrapper.element).toMatchSnapshot();
});
});
javascript
// 测试组件事件
import MyComponent from '@/components/MyComponent.vue';
describe('MyComponent', () => {
it('emits an event on button click', async () => {
const wrapper = mount(MyComponent);
await wrapper.find('button').trigger('click');
expect(wrapper.emitted('click')).toBeTruthy();
});
});
javascript
// 使用快照测试
import MyComponent from '@/components/MyComponent.vue';
describe('MyComponent', () => {
it('matches the snapshot', () => {
const wrapper = mount(MyComponent);
expect(wrapper).toMatchSnapshot();
});
});
javascript
// 使用模拟数据
import MyComponent from '@/components/MyComponent.vue';
describe('MyComponent', () => {
it('renders with mock data', () => {
const mockData = { items: ['item1', 'item2'] };
const wrapper = mount(MyComponent, {
propsData: { data: mockData }
});
// 测试逻辑...
});
});
初学Vue者,辅助快速学习及上手使用Vue。