一:Vue 初阶
1.1 组件自定义事件
在 Vue 中,组件间通过自定义事件进行通信是一种常见的模式。自定义事件允许子组件向父组件发送消息,也可以在组件内部进行事件的绑定、触发和解绑。让我们详细讲解这些知识点。
1.1.1 组件自定义事件
在 Vue 中,自定义事件是指子组件通过 $emit
方法触发,父组件通过 v-on
监听并响应的一种事件机制,一种组件间通信的方式,适用于:子组件 ===> 父组件
1.1.1.1触发自定义事件
在子组件中,使用 $emit
方法来触发自定义事件。例如,Student 组件中的 sendStudentlName
方法通过 $emit
触发了一个名为 atguigu
的自定义事件,并传递了一些参数。
sendStudentlName(){this.$emit('atguigu', this.name, 666, 888, 900)
}
1.1.1.2. 监听自定义事件
在父组件中,通过 v-on
或简写 @
来监听子组件触发的自定义事件。例如,假设 App 父组件包含了一个 <Student>
子组件,并监听了子组的 atguigu
事件。
<template><div><Student @atguigu="handleAtguiguEvent" />//触发了名为 "atguigu" 的自定义事件时,父组件将调用名为 "handleAtguiguEvent" 的方法来处理该事件。</div>
</template<script>
export default {methods: {handleAtguiguEvent(name, num1, num2, num3) {console.log('Received event from Student component:', name, num1, num2, num3);}}
}
</script>
组件上也可以绑定原生DOM事件,需要使用native
修饰符
1.1.1.3. 解绑自定义事件
Vue 提供了 $off
方法用于解绑自定义事件。
-
解绑特定的事件
在子组件中可以使用
this.$off('event-name')
解绑特定的事件。unbind(){this.$off('atguigu'); // 解绑单个事件 }
-
解绑多个事件
可以同时解绑多个事件。
unbind(){this.$off(['atguigu', 'demo']); // 解绑多个事件 }
-
解绑所有事件
如果不传入参数,则会解绑所有自定义事件。
unbind(){this.$off(); // 解绑所有的自定义事件 }
1.1.2 组件销毁与事件失效
Vue 组件销毁时,其所有自定义事件也会失效。在 Student
组件中,使用 this.$destroy()
方法可以销毁当前组件实例,这将导致该组件的所有自定义事件失效,即无法再触发和响应。
death(){this.$destroy(); // 销毁当前Student组件的实例,销毁后所有自定义事件失效。
}
完整代码示例
下面是整合了这些知识点的完整示例:
<template><div><Student @atguigu="handleAtguiguEvent" /><School :getSchoolName="handleSchoolName" /></div>
</template><script>
import Student from './Student.vue';
import School from './School.vue';export default {components: {Student,School},methods: {handleAtguiguEvent(name, num1, num2, num3) {console.log('Received event from Student component:', name, num1, num2, num3);},handleSchoolName(schoolName) {console.log('Received school name from School component:', schoolName);}}
}
</script>
在这个示例中,<App>
父组件中引入了 <Student>
和 <School>
子组件,分别监听了它们触发的自定义事件。当子组件触发对应的事件时,父组件中的方法会被调用,实现了组件间的通信。
1.2 全局事件总线
全局事件总线是 一种组件间通信的方式,适用于任意组件间通信
在Vue中,事件总线是一种通信机制,允许不同组件之间进行通信。Vue实例提供了一个事件系统,可以通过$on
方法监听事件,通过$emit
方法触发事件,通过$off
方法解绑事件监听器。
首先,在Vue实例上创建一个事件总线:
const bus = new Vue();// 将事件总线挂载到Vue原型上,这样所有组件都可以访问到它
Vue.prototype.$bus = bus;
然后,在任何组件中,你可以通过$bus.$on
来监听事件,通过$bus.$emit
来触发事件:
// 在组件A中监听事件
this.$bus.$on('my-event', (data) => {console.log('Received data:', data);
});// 在组件B中触发事件
this.$bus.$emit('my-event', { message: 'Hello world!' });
在以上示例中,组件A监听了my-event
事件,组件B触发了my-event
事件,并传递了一个包含消息的对象。当事件被触发时,组件A中的回调函数会被调用,打印出接收到的数据。
要解绑事件监听器,可以使用$off
方法。在组件销毁或不需要监听事件时,最好手动解绑事件,以避免内存泄漏。
// 在组件销毁时解绑事件监听器
beforeDestroy() {this.$bus.$off('my-event');
}
通过以上方式,你可以在Vue中实现事件总线的功能,并且可以确保在不需要时正确地解绑事件监听器。
1.3 消息订阅与发布
消息订阅与发布(Publish/Subscribe,Pub/Sub)是一种常用的软件架构模式,用于组件间通信
在消息订阅与发布模式中,有以下几个重要的角色和概念:
- 发布者(Publisher):负责发送消息。
- 订阅者(Subscriber):接收和处理特定类型的消息。
- 主题(Topic):用于定义消息的类型或名称,订阅者可以根据主题进行订阅。
- 消息(Message):发布者发送的数据或事件。
1.3.1 详细步骤
-
安装 pubsub-js
首先,通过
npm i pubsub-js
安装 PubSub.js,这是一个常用的 JavaScript 发布/订阅库。 -
引入并使用
在需要使用的文件中,通过
import pubsub from 'pubsub-js'
导入 PubSub.js。 -
消息订阅
订阅者(例如组件 A)可以通过
pubsub.subscribe('topicName', callback)
来订阅特定的主题(topic)。当发布者发布与该主题相关的消息时,订阅者的回调函数(callback)将被调用并接收到消息。示例代码:
methods: {demo(data) {// 处理接收到的数据console.log('Received data:', data);} }, mounted() {// 订阅主题 'xxx',并指定回调函数为 this.demothis.pid = pubsub.subscribe('xxx', this.demo); }
-
消息发布
发布者可以通过
pubsub.publish('topicName', data)
来发布特定主题的消息,并将数据(data)传递给所有订阅了该主题的订阅者。示例代码:
// 在某处发布名为 'xxx' 的主题,并发送数据 pubsub.publish('xxx', { message: 'Hello!' });
-
取消订阅
为了避免内存泄漏或意外的消息处理,建议在组件销毁前取消订阅。通过
pubsub.unsubscribe(pid)
取消之前设置的订阅。示例代码:
beforeDestroy() {// 在组件销毁前取消订阅pubsub.unsubscribe(this.pid); }
示例解释
以上示例展示了如何在 Vue.js 组件中使用 PubSub.js 实现消息订阅与发布:
- 当组件 A 的
mounted
钩子函数执行时,它订阅了名为 ‘xxx’ 的主题,并指定了this.demo
作为回调函数。 - 在其他任何地方(可能是另一个组件或模块),通过
pubsub.publish('xxx', data)
发布 ‘xxx’ 主题的消息,并传递数据data
。 - 一旦消息发布,订阅者(即组件 A)的
demo
方法将被调用,接收并处理消息中的数据。 - 在组件 A 销毁之前,通过
beforeDestroy
钩子取消订阅,以确保在组件销毁后不再接收或处理来自该主题的消息。
这种模式的优势在于,它使不同模块之间的通信更加松散耦合,模块间不直接依赖于彼此,而是通过订阅和发布消息进行通信,从而提高了系统的可扩展性和灵活性。
1.4 nextTick
在 Vue.js 中,this.$nextTick
是一个异步方法,它接收一个回调函数作为参数。它的作用是在下一次 DOM 更新周期结束后执行指定的回调函数。
通常情况下,Vue 在更新 DOM 时是异步执行的,也就是说当你修改了数据后,Vue 并不会立即更新 DOM,而是将更新放入一个队列中,在适当的时机统一进行 DOM 的更新。而this.$nextTick
就提供了一种方式,让你能够在 Vue 完成 DOM 更新后执行一些操作。
举个例子,在你修改了某个数据后,可能需要获取到更新后的 DOM 元素的一些信息或者一些 DOM 操作,但是直接在数据修改后获取可能会得到更新前的 DOM 状态,这时候就可以利用this.$nextTick
来确保你的操作在下一次 DOM 更新后执行。
下面是一个示例代码:
// 在某个方法中修改数据
changeData() {this.message = 'Updated message'; // 修改数据this.$nextTick(() => {// 在下一次 DOM 更新后执行的操作const element = document.getElementById('someElement');console.log('Updated DOM:', element.innerText);});
}
在上面的代码中,changeData
方法中先修改了 message
的值,然后在this.$nextTick
方法中传入了一个回调函数。这个回调函数会在下一次 DOM 更新后被调用,在这个时候,你可以放心地获取到更新后的 DOM 状态。
需要注意的是,this.$nextTick
方法是异步执行的,所以不能保证回调函数的执行顺序。如果需要确保多个回调函数的执行顺序,可以在每个回调函数中再次使用 this.$nextTick
。
1.5 Vue封装的过度与动画
过渡与动画的作用是让元素在插入、更新或移除时,能够以平滑的动画效果呈现出来,增强用户体验。通过 Vue 提供的 <transition>
组件,你可以轻松地实现元素的渡效果和动画效果。
1.5.1 详细步骤
-
准备样式
首先,你需要准备好过渡或动画效果所需的样式,其中包括:
- 元素进入时的样式类名:
v-enter
:表示元素进入时的起点状态。v-enter-active
:表示元素进入过程中的状态。v-enter-to
:表示元素进入时的终点状态。
- 元素离开时的样式类名:
v-leave
:表示元素离开时的起点状态。v-leave-active
:表示元素离开过程中的状态。v-leave-to
:表示元素离开时的终点状态。
- 元素进入时的样式类名:
-
使用
<transition>
将需要过渡或动画的元素使用
<transition>
包裹起来,并配置name
属性来指定样式类名的前缀。<transition name="hello"><h1 v-show="isShow">你好啊!</h1> </transition>
在上面的例子中,
name="hello"
表示过渡或动画效果所需的样式类名的前缀为hello
。 -
备注
- 如果需要对多个元素同时进行过渡或动画,可以使用
<transition-group>
,并为每个元素指定唯一的key
值。 - 每个过渡或动画效果都会在适当的时机自动添加和移除对应的样式类名,从而实现动态的过渡效果。
- 如果需要对多个元素同时进行过渡或动画,可以使用
示例代码
假设我们要实现一个元素在显示和隐藏时的淡入淡出效果:
<template><div><button @click="toggle">切换显示</button><transition name="fade"><h1 v-show="isShow">你好啊!</h1></transition></div>
</template><script>
export default {data() {return {isShow: false};},methods: {toggle() {this.isShow = !this.isShow;}}
};
</script><style>
.fade-enter-active, .fade-leave-active {transition: opacity 0.5s;
}
.fade-enter, .fade-leave-to {opacity: 0;
}
</style>
在上面的例子中,当点击按钮时,isShow
的值会切换,从而触发元素的显示和隐藏。同时,<transition>
标签中的 name="fade"
属性表示使用了名为 fade
的样式类名前缀。在样式部分,定义了 .fade-enter-active
、.fade-leave-active
、.fade-enter
和 .fade-leave-to
这几个类,来实现淡入淡出的过渡效果。
1.6 插槽
在 Vue 中,插槽是一种组件间通信的机制,允许父组件向子组件传递 HTML 结构或数据,并在子组件中进行展示或处理。Vue 中的插槽分为默认插槽、具名插槽和作用域插槽三种类型,用于不同的场景。
- 默认插槽:
默认插槽是最简单的一种插槽形式。父组件可以在子组件的标签中插入 HTML 结构或文内容,而子组件通过 <slot>
标签定义插槽的位置,用来展示父组件传递过来的内容。
示例代码:
<!-- 父组件 -->
<Category><div>HTML 结构1</div>
</Category><!-- 子组件 -->
<template><div><slot>插槽默认内容...</slot></div>
</template>
- 具名插槽:
具名插槽允许父组件将内容传递给子组件的指定位置,可以同时存在多个具名插槽。在父组件中,通过 slot
属性指定插槽的名称;在子组件中,通过 <slot>
标签的 name
属性匹配对应的插槽名称。
示例代码:
<!-- 父组件 -->
<Category><template slot="center"><div>HTML 结构1</div></template><template v-slot:footer><div>HTML 结构2</div></template>
</Category><!-- 子组件 -->
<template><div><slot name="center">插槽默认内容...</slot><slot name="footer">插槽默认内容...</slot></div>
</template>
- 作用域插槽:
作用域插槽允许父组件向子组件传递数据,但根据数据生成的结构由子组件的使用者(父组件)决定。在父组件中,通过 <template>
标签的 scope
或 slot-scope
属性声明作用域变量;在子组件中,通过 <slot>
标签的 name
属性接收作用域变量,并根据数据结构进行渲染。
示例代码:
<!-- 父组件 -->
<Category><template scope="scopeData"><ul><li v-for="g in scopeData.games" :key="g">{{ g }}</li></ul></template>
</Category><!-- 子组件 -->
<template><div><slot :games="games"></slot></div>
</template><script>
export default {name: 'Category',data() {return {games: ['红色警戒', '穿越火线', '劲舞团', '超级玛丽']}},
}
</script>
通过插槽机制,父组件和子组件之间可以实现更灵活的交互,使得组件的复用性和扩展性得到了增强。
二: Vuex
在 Vue 中,Vuex 是一种集中式状态管理工具,用于管理应用中的共享状态。它适用于需要多个组件共享数据的场景,可以让组件之间更方便地进行通信和状态管理。
2.1 Vuex 基础
Vuex 将应用的共享状态抽取出来,以一个全局单例模式管理。它包含了以下几个核心概念:
-
State(状态):即应用中需要共享的数据,存储在 Vuex 的状态树中,可以通过
$store.state
访问。 -
Getters(获取器):用于从状态树中派生出一些状态,类似于计算属性,可以通过
$store.getters
访问。 -
Mutations(变更):提交 mutation 是唯一改变状态的方式,每个 mutation 都有一个字符串类型的事件类型和一个回调函数,通过
$store.commit
提交。 -
Actions(动作):类似于 mutations,但是可以提交异步操作,通过
$store.dispatch
分发。 -
Modules(模块):允许将 store 分割成模块,每个模块拥有自己的 state、getters、mutations、actions。
何时使用?
当应用中存在多个组件需要共享状态时,可以考虑使用 Vuex。它可以帮助管理这些共享状态,使得组件之间的通信更加简单明了。
搭建 Vuex 环境
-
创建文件:
src/store/index.js
// 引入 Vue 核心库 import Vue from 'vue' // 引入 Vuex import Vuex from 'vuex' // 应用 Vuex 插件 Vue.use(Vuex)// 准备 actions 对象——响应组件中用户的动作 const actions = {} // 准备 mutations 对象——修改 state 中的数据 const mutations = {} // 准备 state 对象——保存具体的数据 const state = {}// 创建并暴露 store export default new Vuex.Store({actions,mutations,state })
-
在
main.js
中创建 Vue 实例时传入store
配置项// 引入 store import store from './store'// 创建 Vue 实例 new Vue({el: '#app',render: h => h(App),store })
基本使用
-
初始化数据、配置
actions
、配置mutations
,操作文件store.js
// 引入 Vue 核心库 import Vue from 'vue' // 引入 Vuex import Vuex from 'vuex' // 引用 Vuex Vue.use(Vuex)const actions = {// 响应组件中加的动作jia(context, value) {context.commit('JIA', value)}, }const mutations = {// 执行加JIA(state, value) {state.sum += value} }// 初始化数据 const state = {sum: 0 }// 创建并暴露 store export default new Vuex.Store({actions,mutations,state, })
-
组件中读取 Vuex 中的数据:
$store.state.sum
-
组件中修改 Vuex 中的数据:
$store.dispatch('action中的方法名', 数据)
或$store.commit('mutations中的方法名', 数据)
备注:若没有网络请求或其他业务逻辑,组件中也可以越过 actions,即不写
dispatch
,直接编写commit
。
2.2 Getter 和 4 个 Map方法
2.2.1 Getter 方法
在 Vuex 中,Getter 方法用于从 store 中获取状态,并可以对获取的进行一些加工处理。Getter 方法可以看作 store 的计算属性,当需要从 store 中派生出一些状态时,可以使用 Getter。
使用方式
在 Vuex 的 store 中,通过配置 getters 对象来定义 Getter 方法。Getter 方法收 state 作为第一个参数,可以通过 $store.getters
访问。
示例代码:
// store.jsimport Vue from 'vue'
import Vuex from 'vuex'Vue.use(Vuex)const state = {sum: 0
}const getters = {// Getter 方法:计算 sum 的十倍bigSum(state) {return state.sum * 10}
}export default new Vuex.Store({state,getters
})
在组件中,可以通过 $store.getters.bigSum
来获取并使用这个 Getter 方法返回的值。
<!-- MyComponent.vue --><template><div><p>Sum: {{ $store.state.sum }}</p><p>Big Sum: {{ $store.getters.bigSum }}</p></div>
</template><script>
export {// ...
}
</script>
2.2.2 mapState、mapGetters、mapActions、mapMutations 方法
这些方法是 Vuex 提供的辅助函数,可以简化在组件中与 Vuex 进行交互的代码。它们可以帮助将 Vuex 中的 state、getters、actions 和 mutations 映射到组件的计算属性或方法中。
2.2.2.1 mapState 方法
用于帮助我们将 Vuex 中的 state 映射为组件的计算属性。
import { mapState } from 'vuex'export default {computed: {// 将 state 中的 sum 映射为计算属性 sum...mapState(['sum'])}
}
2.2.2.2 mapGetters 方法
用于帮助我们将 Vuex 中的 getters 映射为组件的计算属性。
import { mapGetters } from 'vuex'export default {computed: {// 将 getters 中的 bigSum 映射为计算属性 bigSum...mapGetters(['bigSum'])}
}
2.2.2.3 mapActions 方法
用于帮助我们将 Vuex 中的 actions 映射为组件的方法。
import { mapActions } from 'vuex'export default {methods: {// 将 actions 中的 increment 映射为组件的方法 increment...mapActions(['increment'])}
}
2.2.2.4 mapMutations 方法
用于帮助我们将 Vuex 中的 mutations 映射为组件的方法。
import { mapMutations } from 'vuex'export default {methods: {// 将 mutations 中的 increment 映射为组件的方法 increment...mapMutations(['increment'])}
}
这些辅助函数使得在组件中使用 Vuex 更加简洁和便捷,可以直接通过映射后的计算属性或方法访问 Vuex 中的状态和操作。
2.3 模块化+命名空间
在 Vue 中,模块化和命名空间是为了更好地组织和管理 Vuex 中的状态、操作和数据而引入的概念。
2.3.1 模块化
模块化是指将 Vuex 的 store 拆为多个模块,每个模块可以包含自己的 state、getters、mutations 和 actions。这样做的目的是将大型的 Vuex 应用拆分为更小、更易于维护的模块,每个模块可以专注于处理特定领域的状态和操作,提高代码的可读性和可维护性。
在 Vuex 中,可以通过在 store 的 modules 选项中注册模块来实现模块化示例代码:
const moduleA = {state: { ... },mutations: { ... },actions: { ... },getters: { ... }
}const moduleB = {state: { ... },mutations: { ... },actions: { ... },getters: { ... }
}const store = new Vuex.Store({modules: {moduleA,moduleB}
})
在组件中使用模化后的 Vuex,需要在读取 state、getters、dispatch actions 和 commit mutations 时指定所属的模块。
2.3.2 命名空间
命名空间是模块化之后的一个概念,它用于区分不同模块中的 state、getters、mutations 和 actions,避免命名冲突。在使用命名空间之前,Vuex 中的所有模块都是在全局命名空间下的,容易造成命名冲突和混乱。
开启命名空间后,每个模块的 state、getters、mutations 和 actions 将只能在自己的命名空间下访问,需要通过模块名来访问。
在 Vuex 中,可以通过在模块配置中设置 namespaced: true
来开启命名空间。
示例代码:
const moduleA = {namespaced: true,state: { ... },mutations: { ... },actions: { ... },getters: { ... }
}const store = new Vuex.Store({modules: {moduleA}
})
在组件中访问命名空间模块的 state、getters、dispatch actions 和 commit mutations 时,需要在调用时指定所属的模块。
// 访问 state
this.$store.state.moduleA.stateName// 访问 getters
this.$store.getters['moduleA/getterName']// 调用 actions
this.$store.dispatch('moduleA/actionName', payload)// 提交 mutations
this.$store.commit('moduleA/mutationName', payload)
通过模块化和命名空间,可以更好地组织和管理 Vuex 中的状态和操作,提高代码的可维护性和可读性,同时避免了命名冲突和混乱。
2.4 路由
在Vue中,路由(route)是指将不同的路径映射到相应的组件上的一种机制。它的作用是实现单页应用(SPA)的页面跳转和管理,使得在页面切换时不需要重新加载整个页面,而是通过动态加载组件来实现页面的更新。
2.4.1 基本使用
- 安装vue-router:首先需要安装 Vue Router 插件,可以通过 npm 命令进行安装:
npm install vue-router
- 应用插件:在 Vue 项目中,需要在入口文件(通常是 main.js)中使用 Vue.use() 来应用 Vue Router 插件:
import Vue from 'vue'
import VueRouter from 'vue-router'Vue.use(VueRouter)
- 编写路由配置项:创建一个Router 实例,并配置路由规则,其中每个路由规则由路径(path)和对应组件(component)组成:
import VueRouter from 'vue-router'
import About from '../components/About'
import Home from '../components/Home'const router = new VueRouter({routes: [{path: '/about',component: About},{path: '/home',component: Home}]
})export default router
- 实现页面切换:在页面中使用
<router-link>
组件来实现页面切换,其中to
属性指定目标路径:
<div><router-link to="/about">About</router-link><router-link to="/home">Home</router-link></div>
</template>
- 指定展示位置:使用
<router-view>
组件来指定路由组件渲染的位置:
<template><div><router-view></router-view></div>
</template>
注意点
- 组件存放位置:通常将路由组件存放在
pages
文件夹,一般组件存放在components
文件夹。 - 路由组件销毁:通过页面切换隐藏的路由组件默认是被销毁的,需要时再挂载。
- ** r o u t e 属性 ∗ ∗ :每个组件都有自己的 ‘ route 属性**:每个组件都有自己的 ` route属性∗∗:每个组件都有自己的‘route` 属性,存储着自己的路由信息。
- ** r o u t e r 属性 ∗ ∗ :整个应用只有一个 r o u t e r ,可以通过组件的 ‘ router 属性**:整个应用只有一个 router,可以通过组件的 ` router属性∗∗:整个应用只有一个router,可以通过组件的‘router` 属性获取到。
2.4.2 多级路由
- 配置多级路由规则:使用
children
配置项来实现多级路由:
const router = new VueRouter({routes: [{path: '/home',component: Home,children: [{path: 'news',component: News},{path: 'message',component: Message}]}]
})
- 跳转:在
<router-link>
中指定完整路径进行跳转:
<router-link to="/home/news">News</router-link>
2.4.3 路由的 query 参数
- 传递参数:通过
<router-link>
的to
属性传递参数,可以使用字符串或对象写法:
<router-link :to="/home/message/detail?id=666&title=你好">跳转</router-link>
- 接收参数:在目标组件中通过
$route.query
获取传递的参数:
$route.query.id
$route.query.title
2.4.4 命名路由(Named Routes):
通过给路由命名,可以在路由跳转时使用这个名字来简化跳转路径。具体来说,就是在路由配置中给每个路由项添加一个名字(name),然后在跳转时可以直接使用这个名字来指定跳转目标。
{name: 'hello',path: '/welcome',component: Hello
}
2.4.5 路由的params参数:
路由的params参数允许在路由之间传递数据,通常用于传递动态的路径参数。我们可以在路由配置中使用占位符来声明接收params参数,然后在跳转时传递参数。
{name: 'xiangqing',path: 'detail/:id/:title',component: Detail
}
2.4.6 路由的props配置:
路由的props配置用于让路由组件更方便地接收参数。我们可以通过props配置项,将路由收到的params参数传递给组件,以便组件直接使用,而无需在组件中通过$route来获取。
{name: 'xiangqing',path: 'detail/:id',component: Detail,props: true // 将路由收到的所有params参数传递给Detail组件
}
2.4.7 <router-link>的replace属性:
<router-link>是Vue Router提供的用于生成路由链接的组件,它可以方便地生成带有正确路径的链接。replace属性用于控制路由跳转时操作浏览器历史记录的模式,可以选择替换当前记录而不是追加历史记录。
<router-link replace to="/news">News</router-link>
2.4.8 编程式路由导航:
除了通过<router-link>实现路由跳转外,还可以使用编程式路由导航来实现,这样可以在代码中更灵活地控制路由的跳转。
// 使用 $router.push() 方法进行路由跳转
this.$router.push({name: 'xiangqing',params: {id: xxx,title: xxx}
})
2.4.9 缓存路由组件:
有时候我们希望某些路由组件在切换时不被销毁,而是保持挂载状态,以便在切换回来时能够保留之前的状态。这时可以使用<keep-alive>组件来包裹<router-view>,并通过include属性指定需要缓存的组件。
<keep-alive include="News"><router-view></router-view>
</keep-alive>
通过以上路由的用法,我们可以更灵活地管理应用的页面跳转和参数传递,实现更加丰富的单页面应用功能。
2.4.10 路由两个新的生命周期钩子
在Vue Router中,有两个新的生命周期钩子,别是activated
和deactivated
。它们是路由组件所独有的钩子,用于捕获路由组件的激活状态。
-
activated
: 当路由组件被激活时触发。你可以在这个钩子中执行特定的操作,例如数据加载或组件初始化。 -
deactivated
: 当路由组件失活时触发。你可以在这个钩子中执行清理操作或者取消订阅。
export default {() {// 路由组件被激活时执行的操作},deactivated() {// 路由组件失活时执行的清理操作}
}
2.4.11 路由守卫
路由守卫用于对路由进行权限控制和导航控制。在Vue Router中,路由守卫分为全局守卫、独享守卫和组件内守卫。
-
全局守卫:
-
全局前置守卫 (
beforeEach
):在每次路由切换前执行的操作,用于进行全局的权限控制或导航控制。 -
全局后置守卫 (
afterEach
):在每次路由切换后执行的操作,通常用于修改页面的标题或执行一些全局的清理操作。
-
router.beforeEach((to, from, next) => {// 在路由切换前执行的权限控制或导航控制
});router.afterEach((to, from) => {// 在路由切换后执行的操作,例如修改页面标题
});
-
独享守卫
独享守卫是直接在路由配置中定义的守卫,针对特定的路由进行权限控制或导航控制。
const router = new VueRouter({routes: [{path: '/profile',component: Profile,beforeEnter(to, from, next) {// 在进入特定路由前执行的权限控制或导航控制}}]
});
-
组件内守卫:
组件内守卫是直接在组件内部定义的守卫,用于特定组件的进入和离开时执行的操作。
export default {beforeRouteEnter(to, from, next) {// 在进入组件前执行的操作},beforeRouteLeave(to, from, next) {// 在离开组件前执行的操作}
}
2.4.12 路由器的两种工作模式
在Vue Router中,有两种常见的路由器工作模式:hash模式和history模式。
-
hash模式:
- 地址中永远带着
#
号,不够美观。 - 不会将hash值包含在HTTP请求中,因此不会影响到服务器端。
- 兼容性较好,但在某些第三方应用中可能会被标记为不合法。
- 地址中永远带着
const router = new VueRouter({mode: 'hash',routes: [...]
});
-
history模式:
- 地址干净美观,不含
#
号。 - 需要后端服务器支持,以解决刷新页面服务端404的问题。
- 兼容性较hash模式略差,但在现代浏览器中已得到广泛支持。
- 地址干净美观,不含
const router = new VueRouter({mode: 'history',routes: [...]
});
这些路由概念和功能在Vue.js应用中起着重要作用,可以帮助你管理应用的导航、权限控制和页面展示。
三 : Vue UI 组件库
Vue UI 组件库是为了方便开发者在Vue.js项目中使用的一套UI组件集合,包括Element UI和Vant。这些组件库提供了丰富的UI组件,可以帮助开发者快速搭建用户界面,提升开发效率。
3.1 Element UI ( PC端 )
Element UI是一个基于Vue.js 2.0的组件库,提供了一系列的UI组件,包括按钮、表单、弹窗、导航等等,覆盖了大部分常用的UI组件。使用Element UI可以快速搭建出美观、易用的用户界面。
基本使用
- 安装Element UI:可以通过npm或者yarn进行安装。
npm install element-ui
或者
yarn add element-ui
- 在项目中使用Element UI:在Vue项目的入口文件(如main.js)中引入Element UI的样式和组件。
import Vue from 'vue';import ElementUI from 'element-ui';import 'element-ui/lib/theme-chalk/index.css';Vue.use(ElementUI);
- 在Vue组件中使用Element UI组件:直接在组件的模板中使用Element UI提供的组件即可。
<template><el-button>按钮</el-button></template><script>export default {name: 'MyComponent'};</script>
按需引入
如果你只想使用部分Element UI组件而不是全部引入,可以使用babel-plugin-component这个babel插件来按需引入。
- 安装babel-plugin-component:
npm install babel-plugin-component -D
- 修改.babelrc文件,在plugins中添加babel-plugin-component配置:
{"plugins": [["component", {"libraryName": "element-ui","styleLibraryName": "theme-chalk"}]]}
- 在组件中按需引入需要的Element UI组件:
import { Button } from 'element-ui';export default {components: {'el-button': Button}};
3.2 Vant ( 移动端 )
Vant是有赞开源的一个移动端Vue组件库,提供了一系列的移动端UI组件,包括按钮、表单、弹窗、导航等等,能够帮助开发者快速搭建移动端应用。
基本使用
- 安装Vant:可以通过npm或者yarn进行安装。
npm install vant
或者
yarn add vant
- 在项目中使用Vant:在Vue项目的入口文件(如main.js)中引入Vant的样式和组件。
import Vue from 'vue';import Vant from 'vant';import 'vant/lib/index.css';Vue.use(Vant);
- 在Vue组件中使用Vant组件:直接在组件的模板中使用Vant提供的组件即可。
<template><van-button>按钮</van-button></template><script>export default {name: 'MyComponent'};</script>
按需引入
如果你只想使用部分Vant组件而不是全部引入,可以使用babel-plugin-import这个babel插件来按需引入。
- 安装babel-plugin-import:
npm install babel-plugin-import -D
- 修改.babelrc文件,在plugins中添加babel-plugin-import配置:
{"plugins": [["import", {"libraryName": "vant","libraryDirectory": "es","style": true}]]}
- 在组件中按需引入需要的Vant组件:
import { Button } from 'vant';export default {components: {'van-button': Button}};