「本文已参与好文召集令活动,点击查看:后端、大前端双赛道投稿,2万元奖池等你挑战!」
使用vue也一年多了,这是对之前的一次复盘,内容没有官方文档详细,对于vue大概也只是停留在使用的阶段,对于源码也没有过多的关注(这也是之后需要提升的),本文的内容可能存在很多的不足之处,希望大佬们可以帮忙指正,让我可以完善一下。真的是提笔容易下笔难,复盘感觉也没有那么清晰,但是也算是一次小总结吧
数据处理
指令
vue中有哪几种指令?
v-html v-text v-if v-else v-else-if v-show v-for v-on v-bind v-model v-slot v-pre v-cloak v-once
复制代码
v-text 和 v-html
相同点两者都可以渲染数据,但是v-html可以解析标签
<span v-text="msg"></span>
<span v-html="htmlMsg"></span>
data(){return{
msg:'我是一个span标签'
htmlMsg:'<strong>我是一个span标签</strong>'
}}
复制代码
v-if和v-for不推荐在同一元素上连用
当它们处于同一节点,v-for 的优先级比 v-if 更高,这意味着 v-if 将分别重复运行于每个 v-for 循环中。
v-if vs v-show
v-show是通过css display去控制dom节点的显示或隐藏,v-if则是控制dom节点是否存在,频繁使用v-show,否则使用v-if
v-for与key
给dom节点增加唯一标识符,可以高效的更新虚拟dom
v-model
本质上是语法糖,会根据标签的不同生成不同的事件和属性
<input v-model="currentValue">等同于下面的
<input v-bind:value="currentValue" v-on:input="currentValue = $event.target.value">
复制代码
v-cloak
防止在页面加载时先出现变量名闪烁的情况
生命周期
概述
vue中有哪几个生命周期?
beforeCreate 实例初始化之后
created 完成了data数据的初始化
beforeMount 相关的render函数呗调用,当还未挂载html到页面上
mounted 挂载完成
beforeUpdate 数据更新前
updated 数据更新后
beforeDestroy 实例销毁前调用,重置操作,清除定时器和监听操作
destroyed 销毁后
复制代码
在组件外部监听内部的生命周期
之前我们想监听组件内部的生命周期,可能会选择在对应的生命钩子内emit,然后外部监听,其实我们可以通过hook事件直接监听到对应的生命周期
<base-button @hook:created="createBtn" label="主要按钮"></base-button>
复制代码
mounted和created谁更适合ajax请求
之前一直没在意过这个,直到有次看到关于这个的问题,建议放在mounted里使用,顿感是我一直放错了地方吗?
通过一些资料,感觉差异性不大,为了避免闪屏和一致性(ssr)放在created,需要操作dom放在mounted中。
created中操作dom
可以使用$nextTick,将回调延迟到下次DOM更新循环之后执行
this.$nextTick(()=>{...})
复制代码
nextTick
Promise.then、MutationObserver 和 setImmediate都不支持的情况下使用setTimeout,前两个是微任务后两个是宏任务,vue通过判断原生环境是否支持,并且不断降级最后使用setTimeout完成
样式绑定
对我们可以通过对象的形式以及数组的形式,通过条件来显示相应的样式
对象语法
<div class="base-button-container" :class="[{'disabled':disabled}]" :style="{'margin':margin}">
data(){return{
margin:'15px',
disabled:false
}}
数组语法
<div class="base-button-container" :class="[disabled]" :style="[baseStyle]">
data(){return{
baseStyle:{
color:'red'
},
disabled:'disabled'
}}
使用三目运算符,控制样式
<div class="base-button-container" :style="{'margin':isBorder?'0':'15px'}">
data(){return{
isBorder:false
}}
复制代码
vue-router
beforeEach
处理身份验证(查看是否存在token)
根据用户的权限过滤路由表
来源于vue-element-admin
router.beforeEach(async(to, from, next) => {
// start progress bar
NProgress.start()
// set page title
document.title = getPageTitle(to.meta.title)
// determine whether the user has logged in
const hasToken = getToken()
if (hasToken) {
if (to.path === '/login') {
// if is logged in, redirect to the home page
next({ path: '/' })
NProgress.done() // hack: https://github.com/PanJiaChen/vue-element-admin/pull/2939
} else {
// determine whether the user has obtained his permission roles through getInfo
const hasRoles = store.getters.roles && store.getters.roles.length > 0
if (hasRoles) {
next()
} else {
try {
// get user info
// note: roles must be a object array! such as: ['admin'] or ,['developer','editor']
const { roles } = await store.dispatch('user/getInfo')
// generate accessible routes map based on roles
const accessRoutes = await store.dispatch('permission/generateRoutes', roles)
// dynamically add accessible routes
router.addRoutes(accessRoutes)
// hack method to ensure that addRoutes is complete
// set the replace: true, so the navigation will not leave a history record
next({ ...to, replace: true })
} catch (error) {
// remove token and go to login page to re-login
await store.dispatch('user/resetToken')
Message.error(error || 'Has Error')
next(`/login?redirect=${to.path}`)
NProgress.done()
}
}
}
} else {
/* has no token*/
if (whiteList.indexOf(to.path) !== -1) {
// in the free login whitelist, go directly
next()
} else {
// other pages that do not have permission to access are redirected to the login page.
next(`/login?redirect=${to.path}`)
NProgress.done()
}
}
})
复制代码
hash和history模式的区别
最直观的区别就是hash模式下url中带了’#’,history模式下需要前端的URL和后端发起请求的URL一致,默认是hash模式
路由传值
场景:路由跳转显示商品详情
页面刷新时,数据不会丢失
$router.push({query:{}})
组件内部获取值
$route.query.X
使用$router.push({params:{}})刷新页面携带的数据会丢失
复制代码
vueX
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式
使用场景:
多个视图依赖于同一状态。
来自不同视图的行为需要变更同一状态。
五个核心属性?
state、getters、mutations、actions、modules 。
复制代码
vuex在界面刷新的时候会初始化导致数据重置,这时候需要将数据存放在localStorage或者sessionStorage中
初始化的时候优先使用sessionStorage内的数据
const state = {
state1: JSON.parse(sessionStorage.getItem('state1')) || null,
}
mutations中去更新sessionStorage内的数据
SET_STATE1: (state, keyData) => {
sessionStorage.setItem('state1', JSON.stringify(keyData))
state.state1 = keyData
},
复制代码
组件内使用
this.$store.state.xx
this.$store.getters.xx //类似于计算属性
复制代码
修改
显示的commit(提交)mutation或者dispatch action来修改state中的数据
this.$store.commit('SET_STATE1', keyData) //SET_STATE1为mutations定义的
this.$store.dispatch('SET_STATE1', null) //SET_STATE1为actions定义的
复制代码
axios
params传参
传递数组的时候,需要a=1&a=2&a=3
qs.stringify 将对象序列化成URL的形式
qs.stringify({ a: ['1', '2', '3'] }, { indices: false });
复制代码
封装
return request({
url: '',
method: 'get',
params
})
request.js
创建一个axios请求,并且在request的时候添加token,reponse中处理请求返回的内容,下面内容来自于vue-element-admin用这个的话都是现成的
const service = axios.create({
baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
// withCredentials: true, // send cookies when cross-domain requests
timeout: 5000 // request timeout
})
复制代码
组件化
组件传值的几种方式?
父子间 props和emit 实例$parent,$children[节制地使用]
跨组件 Event Bus
vuex 状态管理实现通信
复制代码
attrs和listeners
在项目中,难免要去二次封装element组件,如果所有的属性都需要通过props传递给内部的element组件,会显得很繁杂,利用listeners就可以跨层级的传递和监听了
<div class="base-table-container">
<el-table :data="list" v-on="$listeners" v-bind="$attrs" >
<slot></slot>
</el-table>
</div>
复制代码
结语
还是再次推荐文档的阅读,对于理念上和一些细节的认知都会更加清晰,这次复盘写文章好像遗落了蛮多东西的,争取之后完善起来。