Vue
渐进式 JavaScript 框架
Vue 不支持 IE8 及以下版本,因为 Vue 使用了 IE8 无法模拟的 ECMAScript 5 特性(Object.defineProperty())。
版本:Vue 2.x
创建实例
// mvvm
const vm = new Vue({
el: '#app', // element - View,
data: { // 数据 - Model
message: 'hello'
},
methods: { // 方法
},
computed: { // 计算属性
}
})
说明:在创建 Vue 实例时,会将 data、methods、computed 中定义的数据/方法/计算值直接挂载到 Vue 对象实例下,可以使用 e l 获 取 到 元 素 D O M 节 点 、 el 获取到元素DOM节点、 el获取到元素DOM节点、data 获取到整个的 data 对象。注意:在 Vue 对象实例下,已有很多以 _ 或 $ 开头的属性,在 data 中自定义的数据最好不要以 _ 或 $ 开头,如果定义的 data 数据中有以 _ 或 $ 开头的则不会自动被挂载到 Vue 实例下,如果需要访问到这些属性,使用 $data 去获取对应属性的使用。
模板语法
插值
{{ 文本插值 }}
“Mustache”语法,说明,在 {{ }} 内部所书写的是 JavaScript 的表达式,在标签的属性中不能使用 {{ }} 绑定属性值(如果需要动态绑定属性值,使用 v-bind)
指令
指令 (Directives) 是在标签中带有 v-
前缀的特殊属性,这些属性有特定的含义,能够直接被 Vue 实例所解析。
v-html
渲染 HTML 文本(不建议轻易使用,可能导致 XSS 攻击,除非所渲染的内容是完全可信的)
v-text
渲染纯文本
v-bind
动态绑定属性值,可简写为 :
v-on
绑定事件,可简写为 @
修饰符:
- .prevent ---- 阻止默认行为
- .stop ---- 阻止事件传播
- .enter ---- 回车键
- .ctrl ---- ctrl 控制键,例如:@keydown.ctrl.enter=“sendMessage”
条件渲染指令
v-if
指令属性值表示条件,切换元素显示/隐藏时,操作的是 DOM 树的结构:显示时向 DOM 树中添加节点,隐藏时从 DOM 树中删除节点
v-else-if
v-else
v-else 指令没有属性值
v-show
切换元素显示/隐藏时,操作的是节点的 CSS 样式(display):显示时将 display: none;
删除,隐藏时添加 display: none;
v-if 与 v-show 的区别:
- 操作 DOM 树还是 CSS 样式
- 一般来说,
v-if
有更高的切换开销,而v-show
有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用v-show
较好;如果在运行时条件很少改变,则使用v-if
较好。
使用 key 管理元素
Vue 会尽可能高效地渲染元素,通常会复用已有元素(就地复用策略)而不是从头开始渲染。这么做除了使 Vue 变得非常快之外,还有其它一些好处。这样也不总是符合实际需求,所以 Vue 为你提供了一种方式来表达“这两个元素是完全独立的,不要复用它们”。只需添加一个具有唯一值的 key
attribute 即可
列表渲染指令
v-for
v-for="(item, index) in arrayOrObject" 或 v-for="(item, index) of arrayOrObject"
通常在使用 v-for 实现列表渲染时,需要动态绑定 key 属性,key 值应该唯一,不要使用 index 作为 key 值绑定
通常是使用 v-for 来实现数组的列表渲染
数组变异(变更)方法:
- pop()
- push()
- shift()
- unshift()
- splice(index, howmany, replace)
- sort()
- reverse()
在 Vue 中,调用上述数组的7个方法实现数组更新时,页面也会响应式更新,如果调用了非上述的方法(原数组本身未受影响),那可以使用替换数组的方式来实现页面响应式更新,如:
vm.list = vm.list.filter(item => item.id > 1)
v-once
只渲染元素和组件一次。随后的重新渲染,元素/组件及其所有的子节点将被视为静态内容并跳过。
v-pre
跳过这个元素和它的子元素的编译过程。
v-cloak
和 CSS 规则如 [v-cloak] { display: none }
一起用时,这个指令可以隐藏未编译的 Mustache 标签直到实例准备完毕,(作用:避免出现编译前后页面节点的闪烁效果)
v-model
通常用于表单元素的数据双向绑定
语法糖
v-model
在内部为不同的输入元素使用不同的 property 并抛出不同的事件:
- text 和 textarea 元素使用
value
property 和input
事件; - checkbox 和 radio 使用
checked
property 和change
事件; - select 字段将
value
作为 prop 并将change
作为事件。
v-slot
用于使用插槽
<template v-slot:subtitle>
</template>
计算属性、侦听属性
计算属性
通常是根据已有的数据,计算出新的数据,一般都是使用到计算属性的 getter(很少用到 setter)
new Vue({
data: {
message: 'hello'
},
computed: { // 计算属性
reverseMsg() { // 属性 getter 的简写
return this.message.split('').reverse().join('')
},
reverseMsg2: { // 与 reverseMsg() 书写等价
get() { // getter
return this.message.split('').reverse().join('')
}
}
}
})
计算属性的值是会被缓存的,当依赖项不改变时,会一直使用缓存的数据,依赖项发生改变时,会重新计算 computed 属性的值并继续缓存。
计算属性是基于它们的响应式依赖进行缓存的。只在相关响应式依赖发生改变时它们才会重新求值。
computed vs method
计算属性会被缓存,而方法不会被缓存,通常计算属性效率会比方法更高
侦听属性
watch
监听到数据变化后执行对应的任务
computed vs watch
- computed 有缓存,watch 无缓存
- computed 计算属性中不能执行异步操作,而 watch 中可以执行异步操作
- computed 通常是由一个或多个数据的变化,生成一个新的数据,而 watch 通常是监听一个数据的变化,可能引起一个或多个其它数据的变化
Class 与 Style 绑定
在将 v-bind
用于 class
和 style
时,Vue.js 做了专门的增强。表达式结果的类型除了字符串之外,还可以是对象或数组。
对于 style 的绑定,更推荐使用对象的方式绑定。使用对象时,将 css 属性名的短横线全名规范改为驼峰全名规范来使用。
组件系统
在 Vue 里,一个组件本质上是一个拥有预定义选项的一个 Vue 实例。
组件是可被复用的 Vue 实例
组件定义
选项对象:
{
template: ``, // 布局结构
data() { return {} }, // 数据
methods: {},
computed: {},
watch: {}
}
组件定义时,data 必须是函数的结构,在函数体内部返回一个普通对象。
(面试)data 必须是函数的原因:如果使用普通对象,当组件被复用时,多个组件对象实例引用到同一个数据对象,当其中某一个组件实例对 data 数据作修改时,其它组件实例也会同时受影响,这与实际业务不符。使用函数,每创建一个组件实例时,都返回新的 data 对象数据,多个组件实例间 data 是独立开的,当修改组件实例中的数据时,其它组件实例不受影响,与实际相符。
在 template 中定义布局结构时,必须保存所有的布局使用 单个根元素 包裹起来
组件注册
全局注册
Vue.component('组件名称', 选项对象)
全局注册的组件,在所有的 Vue 实例或其它组件中,都可以使用到
局部注册
{
components: {
组件名称: 选项对象
}
}
在组件或 Vue 实例的选项对象中,添加 components 字段,来局部注册子组件
局部注册的组件,只在注册它的父组件内部可以使用到
组件使用
将组件名称作为自定义标签名称使用。
规范:如果组件名称是使用驼峰命名规范,则在作为自定义标签名使用时,转换为短横线命名规范(各单词之间使用 短横线 分隔,所有单词小写)
插槽
用作于内容分发,在父组件中可以向子组件传递布局结构的内容。
组件通信
父子通信
- 父传子:通过属性的方式传递数据 ---- prop。
- 子传父:使用事件的方式传递数据。在父组件中使用子组件时,绑定一个自定义事件(@customEvent),在子组件中需要传递数据时,触发对应的事件执行(
this.$emit(事件名称, 需要传递的数据)
) 并传递相应数据(相当于传递的数据是携带在 $event 对象中传递给父组件的) 即可。
跨组件通信
- 将组件关系转换为一系列的父子关系(会增加中间组件的处理负担)
- event bus (事件总线):创建一个全局的 Vue() 实例(可以将该 Vue() 实例添加到 Vue.prototype 中,这样就可以在各组件实例中调用到了 ),在需要接收数据的组件中使用
$on()
方法注册一个自定义事件,在需要传递数据的组件中使用$emit()
方法去触发对应事件的执行并传递数据。 - vuex
Prop
父组件向子组件传递数据时,可使用 prop ( 属性 ) 的方式。在组件的选项对象中,使用 props
来定义组件可接收到的属性,props
可取数组和对象的结构。数组中每个元素通常是所能接收属性的属性名称,对象通常是对属性做校验使用。
组件中的属性应该是只读的(不要修改组件接收到的属性值)
响应式原理
底层使用到 Object.defineProperty() 方法,对数据劫持,在各数据的 getter/setter 方法中添加额外的操作,以实现响应式动作。
虚拟 DOM:
<div :title="divTitle" id="title" class="title">
<h1 class="title">
{{ title }}
</h1>
<h2 class="subtitle">
副标题
</h2>
</div>
{
tag: 'div',
props: {
title: data.divTitle,
id: 'title',
className: 'title'
},
children: [
{
tag: 'h1',
props: {
className: 'title'
},
children: [data.title]
},
{
tag: 'h2',
props: {
className: 'subtitle'
},
children: ['副标题']
}
]
}
当数据被修改后,在内存中存在修改前后的两个对象,Vue 会将数据修改前后的两个对象进行比较(diff 算法),找出两个对象不同的部分,将不同部分的内容重新渲染到真实的 DOM 树中。
Vue 推荐在绝大多数情况下使用模板来创建你的 HTML。然而在一些场景中,你真的需要 JavaScript 的完全编程的能力。这时你可以用渲染函数,它比模板更接近编译器。
渲染函数 – render()
function render (createElement) {
return createElement(tag, props, children)
}
createElement() 函数的主要作用是用作于创建 虚拟元素 节点,用于在虚拟 DOM 中的处理。
生命周期
生命周期指的是 Vue 实例或组件从创建到最终销毁所经历的整个过程。
生命周期各阶段中,如果需要执行用户额外添加的操作,Vue 提供了一些 生命周期钩子函数 来执行额外的操作。
create 阶段(创建)
- beforeCreate()
- created() – 一般页面初始化渲染所使用到的数据如果需要从后端接口中获取,则在 created() 方法中发起 ajax 请求去获取数据。
mount 阶段 (挂载)
注意 mounted
不会保证所有的子组件也都一起被挂载。如果你希望等到整个视图都渲染完毕,可以在 mounted
内部使用 vm.$nextTick(callback)
- beforeMount()
- mounted() – 在 mounted() 方法中,可获取到挂载的 DOM 节点
vm.$nextTick(callback) 方法:将 callback 回调函数的执行延迟到下一次 DOM 更新之后执行
update 阶段(更新)
当 data / props 数据发生改变时,进入 update 阶段。注意,在 update 阶段的生命周期钩子函数中不要再次修改数据,否则会导致死循环内存溢出。
- beforeUpdate()
- updated()
destroy 阶段(销毁)
- beforeDestroy()
- destroyed()
过滤器
vue.js 中允许用户自定义过滤器,过滤器主要的作用是文本格式化。它可以用在 {{}}
插值语法和 v-bind
绑定属性的表达式中
全局定义、局部定义:
// 全局
Vue.filter(过滤器名称, 处理函数)
// 局部定义,在组件的选项对象中:
{
filters: {
过滤器名称: 处理函数
}
}
在 {{}} 或是 v-bind 表达式中使用过滤器时,利用 |
管道运算符连接过滤器名称。例如:{{ prod.price | money }},<custom-component v-bind:price="prod.price | money">
Vue CLI
安装
$ npm install -g @vue/cli
# OR
$ yarn global add @vue/cli
安装后测试是否能够看到版本信息:
$ vue --version
如果不能看到版本信息,报告 vue 不是内部外部命令之类的异常,则可能需要重新配置环境变量。
如果是 npm 安装的 @vue/cli,在环境变量中,path 内是否有 C:\Users\<你的用户名>\AppData\Roaming\npm
。
如果是 yarn 安装的 @vue/cli,在环境变量中,path 内是否有 C:\Users\<你的用户名>\AppData\Local\Yarn\bin
。
添加对应的环境变量 path 值后,重启命令行工具,再测试 vue --version
。
单文件组件
文件后缀名为 .vue
,文件内容结构:
<template>
<!-- 组件视图布局 -->
</template>
<script>
// 组件选项对象
export default {
name: 'ComponentName'
}
</script>
<style lang="scss" scoped>
/* 布局结构中使用到的样式 */
</style>
在 VS code 中,如果需要查看单文件组件时,代码有高亮效果,需要安装 vetur
扩展程序
使用 @vue/cli 创建项目
推荐先使用 cmd 命令行工具运行 vue 命令
$ vue create <project-name>
创建项目时,先选择项目中需要添加的特性。然后创建项目目录,安装依赖。
项目创建完毕后,进入项目目录,运行:
$ npm run serve
# OR
$ yarn serve
package.json
npm scripts
{
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
}
}
serve – 是开发环境使用到的任务:npm run serve
,启动任务后,会在本地启动一个 web server (webpack-dev-server)。
build – 构建,是生产环境使用到的任务。运行 npm run build
后,默认会在项目根目录下生成 dist
目录,dist 目录中放置的就是用于部署(发布上线)的代码。
lint – lint 工具,检测语法规范
别名
@ - 代表 src 目录
SPA - 单页面应用程序
模块化
AMD - require.js define() / require()
CMD - sea.js
CommonJS - NodeJS module.exports / require
ES6 Module - import/export
AJAX
原生 ajax
- 创建 XMLHttpRequest 对象
- 初始化,xhr.open(method, url, async)
- 发送请求,xhr.send(querystring),如果要像表单一样 POST 数据,则需要在 send() 调用前去调用 xhr.setRequestHeader(‘Content-Type: application/x-www-form-urlencoded’) 设置请求头
- 监听,处理响应 xhr.onreadystatechange = function() {}
- xhr.readyState – 就绪状态码(当前请求到达哪个阶段),4 – 请求处理完毕,响应就绪
- xhr.status – HTTP 状态码,2xx
- xhr.responseText – 响应文本 JSON
Promise
它允许你为异步操作的成功和失败分别绑定相应的处理方法(handlers)。 这让异步方法可以像同步方法那样返回值,但并不是立即返回最终执行结果,而是一个能代表未来出现的结果的promise对象
三种状态:
- pending - 初始化、等待
- fulfilled - 成功
- rejected - 失败
使用:
new Promise((resolve, reject) => {
setTimeout(() => {
if (Math.random() > 0.5) {
resolve('success') // 将状态修改为 fulfilled 状态
} else {
reject('fail') // 将状态修改为 rejected 状态
}
}, 1000)
})
.then((successData) => {
console.log(successData)
})
.catch((err) => {
console.log(err)
})
.finally()
async / await (ES7)
await 等待的是一个 Promise 对象返回的异步结果。await 只能用在 async 所修改的 function 中。
await 表达式会暂停当前 async function
的执行,等待 Promise 处理完成。若 Promise 正常处理(fulfilled),其回调的resolve函数参数作为 await 表达式的值,继续执行 async function
。
Fetch API
Fetch API 提供了一个获取资源的接口(包括跨域请求)。
发送请求或者获取资源,需要使用 fetch() 方法。
fetch()
必须接受一个参数 url ——资源的路径。无论请求成功与否,它都返回一个 Promise 对象,resolve 对应请求的 Response 响应对象,还需要借助 Response 对象的 json() 方法来获取响应流中的数据。
axios
Vue-Router
Vue Router 是 Vue.js 官方的路由管理器。它和 Vue.js 的核心深度集成,让构建单页面应用变得易如反掌。
前端路由
hash 模式
通过地址 URL 中 #hash 值的变化监测来实现页面的切换效果。在 URL 地址中当 hash 值改变时,会触发 window.onhashchange 事件的执行,在事件处理程序中,可以实现组件切换。在 hash 模式中,URL 中会有一个 # 号标识
history 模式
利用 H5 中 history 对象新增的 pushState() 、replaceState() 方法来实现向历史记录中添加访问历史(这种添加访问历史的操作也不会向服务器发起新的请求),当添加/删除访问历史时,会触发 window.onpopstate 事件的执行,在事件处理程序中可以实现组件切换操作。在 history 模式中,URL 和请求服务器端的资源 URL 是一致的(没有多余的 #)。但 history 要用好,通常还需要服务器端 webserver 中配合做一些配置。
使用
安装
$ npm install vue-router --save
# 或
$ yarn add vue-router
创建 VueRouter 实例
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from './views/home'
// 使用插件,全局注册了 RouterLink 与 RouterView 两个组件
Vue.use(VueRouter)
// 创建 VueRouter 对象
const router = new VueRouter({
mode: 'hash', // hash / history
routes: [ // 路由表配置
{
path: '/home',
component: Home
}
]
})
// 导出
export default router
关联 Vue 实例
import Vue from 'vue'
import router from './router'
new Vue({
router,
render: h => h(App)
}).$mount()
这步操作是在 main.js 中完成
两个组件
<router-link>
超级链接,<router-link to="">
<router-view>
路由视图,用于渲染页面组件(其实相当于是占位符,当URL访问地址改变时,会在 <router-view>
位置渲染出对应的页面组件)
路由重定向
new VueRouter({
routes: [
{
path: '/',
redirect: '/home' // 重定向
}
]
})
路由元信息
在路由定义时,添加 meta
的属性来定义路由元信息。
meta
作用:携带在开发过程中需要使用到的额外数据(和路由有关)
组件注入
在 Vue 根实例中注入 router 后,每个子组件中都被注入了 $router 与 $route 属性
- $router 代表的是 VueRouter 的实例
- $route 代表当前激活的路由(现在正在访问的路由)
命名视图
一个页面中可以使用多个 <router-view />
组件,在使用多个该组件时,通常需要给各组件取 name 属性(命名视图),在一个路由中,不同的命名视图中渲染不同的路由组件,可以:
{
path: '/home',
name: 'home',
components: {
header: SearchBar,
footer: Tabbar,
default: Home
}
}
嵌套路由
动态路由匹配
动态路径参数:是在路由路径后使用 :
定义的参数结构,如:/category/sub/:id
。
在组件中获取到路由中传递的动态路径参数值:$route 属性。在 $route 的 params
中保存了动态路径参数值
编程式导航
除了使用 <router-link>
创建 a 标签来定义导航链接,我们还可以借助 router 的实例方法,通过编写代码来实现。
-
r
o
u
t
e
r
.
p
u
s
h
(
u
r
l
)
−
−
点
击
‘
<
r
o
u
t
e
r
−
l
i
n
k
:
t
o
=
"
"
>
‘
等
同
于
调
用
‘
router.push(url) -- 点击 `<router-link :to="">` 等同于调用 `
router.push(url)−−点击‘<router−link:to="">‘等同于调用‘router.push(…)`
- 说明:url 可以是字符串,也可以是对象。当是对象结构时,对象中可取的属性有:
{path: '路径字符串'}
、{path: '路径', query: {查询字符串表示的对象}}
、{name: '命名路由名称', params: {动态路径参数表示的对象}}
、{name: '', query: {}}
- 通过路由进行参数传递时,有动态路径参数与查询字符串参数两种方式。动态路径参数(/:id/:user)与
params
相关,而查询字符串参数(?key=value&key=value&key=value)与query
相关 - 如果提供了
path
,params
会被忽略
- 说明:url 可以是字符串,也可以是对象。当是对象结构时,对象中可取的属性有:
导航守卫
就是在路由切换过程中提供了一些钩子函数,供我们在切换过程中执行额外的业务逻辑。
全局
- beforeEach() – 全局前置守卫,可以在全局前置守卫中判断用户的登录、权限逻辑
const router = new VueRouter({ ... })
router.beforeEach((to, from, next) => {
// ...
// to:去哪儿,要切换跳转到的路由
// from:从哪儿来,是在切换跳转前的路由
// next:函数,下一步
// 注意,在导航守卫中通常都需要调用 next() 函数进入下一步解析执行。
// 如果没有调用 next() 则中断路由解析过程。但最好每次都显式调用 next()
// next() 在调用时:
// next() -- 表示继续下一步正常的解析流程
// next(false) -- 中断路由解析
// next(urlString|urlObject) -- 下一步跳转到另一个导航中
// next(error) -- error 是 Error 对象,终止导航,error 错误信息会被传递到 router.onError()
// 对于 next() 函数的调用,确保在任何给定的导航守卫中都被严格调用一次,如果被调用了多次,则要么不执行,要么报错
})
- beforeResolve() – 全局解析守卫
- afterEach() – 全局后置钩子:钩子不会接受
next
函数也不会改变导航本身
路由独享
- beforeEnter() – 在路由配置上直接定义
组件
- beforeRouteEnter()
- beforeRouteUpdate()
- beforeRouteLeave()
const Foo = {
template: `...`,
beforeRouteEnter (to, from, next) {
// 在渲染该组件的对应路由被 confirm 前调用
// 不!能!获取组件实例 `this`
// 因为当守卫执行前,组件实例还没被创建
},
beforeRouteUpdate (to, from, next) {
// 在当前路由改变,但是该组件被复用时调用
// 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
// 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
// 可以访问组件实例 `this`
},
beforeRouteLeave (to, from, next) {
// 导航离开该组件的对应路由时调用
// 可以访问组件实例 `this`
}
}
Vuex
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
这种方式也是解决组件通信时所用到的一种方式。
全局的用户状态数据管理、全局语言选择、全局主题设置、换肤、购物车等功能可以使用 vuex 来实现管理。
概念
store – 仓库,采用集中式存储
state – 用于存储状态的对象(统一的将需要管理的所有组件的状态存放到 state 中)
mutation – 方法,用于同步更新状态(修改数据)。mutation 是唯一可以更新状态的地方。不能包含异步更新状态的动作。mutation 方法的调用不能直接调用,而是需要使用 store.commit(type, payload) 来提交 mutation(相当于就是调用 mutation 方法)。type 表示的是 mutation 类型(就是mutation方法名称),payload 表示有效载荷,就是在调用 mutation 方法时需要传递的额外数据。
action – 方法,用于更新状态(可同步,也可以异步),但在 action 中不能直接更新状态,而是需要通过提交 mutation 来更新状态的。
getter – 是 store 中关于 state 的派生数据,相当于就是组件中的 计算属性
module – 模块,可以将所有组件的状态管理分类,形成一个个独立的小的模块,然后组合成完整的功能模块。每个模块中都有自己的 state、getter、mutation、action,甚至于还可以有自己的子模块。
使用
安装
$ npm i vuex --save
# 或
$ yarn add vuex
创建 Store 对象实例
// 引入 Vue
import Vue from 'vue'
// 引入 vuex
import Vuex from 'vuex'
// 使用
Vue.use(Vuex)
// 创建 Store 对象实例
const store = new Vuex.Store({
state: { // 状态、数据
todos: []
},
mutations: {
// 添加新待办事项
addTodoItem(state, title) {
state.todos.unshift({
id: Math.random(),
title,
completed: false
})
}
}
})
// 导出
export default store
关联 Vue 实例
import Vue from 'vue'
import store from './store'
new Vue({
store,
render: h => h(App)
}).$mount()
命名空间
默认情况下,所有 module 下定义的 action/mutation/getter都注册在全局命名空间下,当维护的模块较多时,可能会出现 action/mutation/getter 中命名冲突的问题,我们可以使用 namespace 命名空间(名字空间)来解决。
{
modules: {
user: {
namespaced: true, // 启用命名空间
state: {},
getters: {}, // getters中的各属性就需要添加 'user' 命名空间前缀访问
mutations: {}, // mutations中的各属性就需要添加 'user' 命名空间前缀访问
actions:{ login(){} }
}
}
}
例如在组件中使用到 action 中的 login() 时:
// 1.
{
created() {
this.$store.dispatch('user/login')
}
}
// 2.
import { mapActions } from 'vuex'
{
careated() {
this['user/login']()
},
methods: {
...mapActions(['user/login'])
}
}
// 3.
import { mapActions } from 'vuex'
{
careated() {
this.login()
},
methods: {
...mapActions('user', ['login'])
}
}
// 4.
import { createNamespacedHelpers } from 'vuex'
const { mapActions } = createNamespacedHelpers('user')
{
careated() {
this.login()
},
methods: {
...mapActions(['login'])
}
}
课堂项目案例
电商–移动端
首页
分类
列表
详情
购物车
我的
登录
注册
UI组件库
PC端:Element-UI、iview
使用
安装
$ npm i vant -S
# 或
$ yarn add vant
按需引入
$ npm i babel-plugin-import -D
安装 babel 插件:babel-plugin-import 。安装好插件后,修改 babel 的配置文件:
// babel.config.js 文件
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
],
plugins: [
['import', {
libraryName: 'vant',
libraryDirectory: 'es',
style: true
}, 'vant']
]
}
安装好 babel-plugin-import 后,一定要修改配置文件。
登录权限业务
用户登录状态信息是利用 vuex 来实现管理
登录流程:
- 进入登录页面,填写用户名密码信息,提交登录
- 由于登录通常是异步任务(发 ajax 请求后端 api 接口),分发 store 的 action 方法来实现登录,并保存登录状态信息到 store 中(在 action 中 commit mutation 来实现保存)。在 action 中将用户登录成功或失败的信息返回登录页面
- 在登录页面中,根据用户登录成功或失败的信息,跳转页面
权限控制:
结合 vue-router 的导航守卫来实现,用到了全局前置守卫: router.beforeEach((to, from, next) => {})。
判断流程:
- 判断要切换到的路由是否需要登录权限
- 如果需要登录的权限
- 判断用户是否已登录
- 如果已登录,则继续下一步解析
- 如果用户未登录,则跳转到登录页面,完成登录流程
- 如果不需要登录的权限,则继续下一步解析