目录
2.函数调用,要传递的参数是一个异步函数,并且此函数还要传参:
1.编程式导航,避免到当前位置的冗余导航:
简单来说就是重复触发了同一个路由
错误提示:
NavigationDuplicated: Avoided redundant navigation to current location:
解决:在router/index.js中的vue.use后面插入
const originalPush = VueRouter.prototype.push
VueRouter.prototype.push = function push(location) {
return originalPush.call(this, location).catch(err => err)
}
2.函数调用,要传递的参数是一个异步函数,并且此函数还要传参:
错误写法:
const brand = useLazyData(target, findBrand(10))
正确写法:应该写成箭头函数,否则函数立即执行返回promise对象
const brand = useLazyData(target, () => findBrand(10))
3.组合式api概念:
vue2中的Options API就是选项API,vue3则用的是组合API.
在一个 vue 文件内,会有 data、methods、mounted、computed、watch 等等用来定义属性和方法,共同来处理页面逻辑,我们把这种方式称为 Options API。
把所有的功能都写在一个模块中(写在setup()中),就是组合API(Composition API)。
4.watch相关:
当watch监听的是proxy对象的某个属性时,要用函数返回的形式。
即:监听proxy数据的某个属性需要将监听值写成函数返回形式,vue3无法直接监听对象的某个属性变化
(id变化时路由不会重新加载,所以此时要监听id变化,重新发请求)
错误写法:
watch(
route.params.id,
() => {
findTopcategory(route.params.id).then(
(data) => {
subList.value = data.result.children
},
{ immediate: true }
)
}
)
正确写法:
watch(
() => route.params.id,// 箭头函数
() => {
findTopcategory(route.params.id).then(
(data) => {
subList.value = data.result.children
},
{ immediate: true }
)
}
)
5.图片懒加载指令:
vue2:
import defaultImg from '@/assets/images/200.png'
// 图片懒加载指令
Vue.directive('lazy', {
inserted(el, binding) {
const observer = new IntersectionObserver(
([{ isIntersecting }]) => {
if (isIntersecting) {
observer.unobserve(el)
el.onerror = () => {
el.src = defaultImg
}
el.src = binding.value
}
},
{
threshold: 0.01
}
)
// 使用:
//<img v-lazy="item.picUrl" alt="" />
vue3:
import defaultImg from '@/assets/images/200.png'
app.directive('lazy', {
mounted (el, binding) {
const observer = new IntersectionObserver(([{ isIntersecting }]) => {
if (isIntersecting) {
observer.unobserve(el)
el.onerror = () => {
el.src = defaultImg
}
el.src = binding.value
}
}, {
threshold: 0.01
})
observer.observe(el)
}
})
// 使用:
//<img v-lazy="item.picUrl" alt="" />
区别主要是:vue2是inserted,vue3是mounted
6.自定义属性传值相关:
如果要使用自定义属性给子组件传值,且这个值是异步请求而来的,那么不可以如下操作,因为这样返回的是空数组,数据还未请求成功,就已经传给了子组件
<template>
<XtxCarousel :sliders="sliders"></XtxCarousel>
</template>
<script>
export default {
setup() {
const sliders = ref([])
findRelGoods(id).then((data) => {
sliders.value = data.result })
return {sliders}
}
}
</script>
而是应该先定义一个返回目标数据的函数,然后让要return出去的常量调用此函数
<template>
<XtxCarousel :sliders="sliders"></XtxCarousel>
</template>
<script>
// 在export default外面定义一个函数
const useRelGoodsData = (id) => {
const sliders = ref([])
findRelGoods(id).then((data) => {
sliders.value = data.result
})
return sliders
}
export default {
setup(props) {
// 在此处调取函数
const sliders = useRelGoodsData(props.goodsId)
// 此处返回给自定义组件使用
return {
sliders
}
}
}
</script>
7.axios相关:
如果request的url传完整地址如:
export const findCommentInfoByGoods = (id) => {
return request(`https://mock.boxuegu.com/mock/1175/goods/${id}/evaluate
`,'get')
}
那么此时我们的baseURL不会生效
8. vee-validate 表单校验基本步骤(vee-validate@4.0.3)
1.安装vee-validate插件:npm i vee-validate@4.0.3
2.导入Form Field 组件 :
import { Form, Field } from 'vee-validate'
3.将form标签 和 input标签 进行替换:form替换成Form,input替换成Field
4.Form标签上的属性:
1) :validation-schema="schema" :接受定义好的校验规则,是一个对象,包含方法
2)v-slot="{ errors }" : 作用域插槽,解构出错误对象
3)autocomplete="off" : 自动补全,这里关闭
5.Field标签上属性:
1)name="account" : 用来指定将来的校验规则函数
2)v-model="form.account" :双向数据绑定的属性,统一写在form对象上,字段名称最好和后台接口需要的一致
3)type="text" :类型,与<input>标签一致
4):class="{ error: errors.account }" : 校验规则函数不成功就会触发errors.account
<Form class="form" :validation-schema="schema" v-slot="{ errors }" autocomplete="off">
<Field name="account" v-model="form.account" type="text" placeholder="请输入用户名或
手机号" :class="{ error: errors.account }" />
</Form>
<!-- 用户名错误提示 -->
<div v-if="errors.account">{{ errors.account }}</div>
6.表单信息对象,用于双向数据绑定(v-model):
const form = reactive({
account: null,
})
7.表单校验规则,schema对应Form中的属性:validation-schema="schema";account对应field中的属性name="account"
const schema = {
// 用户名校验
account(value) {
// 为空
if (!value) return '请输入用户名'
// 不符合正则
if (!/^[a-zA-Z]\w{5,19}$/.test(value)) return '字母开头且6-20个字符'
// 格式正确
return true
},
}
8.自定义组件需要校验必须支持v-model,然后Field使用as指定组件名称:
<Field as="XtxCheckbox" name="isAgree" v-model="form.isAgree" />
9.点击登录的时候对整体表单进行校验:
<Form ref="formCom" class="form" :validation-schema="schema" v-slot="{errors}"
<a @click="login()" href="javascript:;" class="btn">登 录</a>
const login = async () => {
// Form组件提供了一个 validate 函数作为整体表单校验,当是返回的是一个promise
//成功时为true,否则false
const valid = await formCom.value.validate()
console.log(valid)
}
9.vue中禁止、恢复页面滚动
禁止时调用:preScroll()
恢复时调用:reScroll ()
// 阻止默认事件函数
const scrollEvent = (e) => {
e.preventDefault()
}
// 禁止页面滚动
const preScroll = () => {
document.body.addEventListener('touchmove', scrollEvent, { passive: false })
document.body.addEventListener('wheel', scrollEvent, { passive: false })
}
// 恢复滚动
const reScroll = () => {
document.body.removeEventListener('touchmove', scrollEvent, { passive: false })
document.body.removeEventListener('wheel', scrollEvent, { passive: false })
}
10.vuex数据持久化
需要安装一个vuex的插件vuex-persistedstate
来支持vuex的状态持久化。
npm i vuex-persistedstate
store/modules文件夹下新建模块userInfo.js:
export default {
namespaced: true,
state() {
return {
beginName: '',
user: {
token: '',
id: '',
email: '',
nickname: '',
account: '',
sex: '',
description: '',
portrait: '',
phone: '',
level: ''
}
}
},
mutations: {
setBeginName(state, newName) {
state.beginName = newName
},
setUser(state, val) {
state.user = val
}
}
}
store文件夹下新建index.js:
import { createStore } from 'vuex'
import createPersistedState from 'vuex-persistedstate'
import userInfo from '@/store/modules/userInfo.js'
export default createStore({
modules: {
userInfo
},
plugins: [
createPersistedState({
key: 'glfy-blog',
paths: ['userInfo']
})
]
})
完成!