Appearance
持久化存储
借助 vuex-persistedstate 实现自动化存储
bash
npm i vuex-persistedstate
在 vuex 中配置插件
js
// createStore 方法用来创建 store 实例对象
import { createStore } from 'vuex'
import user from './modules/user'
import cart from './modules/cart'
// 导入持久化插件
import createPersistedstate from 'vuex-persistedstate'
export default createStore({
modules: {
user,
cart
},
// 配置插件
plugins: [
// 插件同步机制:只要修改了state(配置需要持久化的模块)中的数据就会自动同步持久化,当刷新时会自动从本地存储里取到数据同步到vuex中
createPersistedstate({
key: 'erabbit-client-pc-store', // 存放数据的 key
paths: ['user', 'cart'] // 写入需要持久化的模块
})
]
})
测试
js
// 配置过持久化插件的模块
const user = {
namespaced: true, // 严格模块化
// state写成函数和组件中 data 写成函数类似,是为了将来这个vuex模块复用做准备
// 在对象外加括号仅仅是为了包裹一下变成表达式就没有语法错误了,类似于自执行函数:(function (){})()
// 下面的写法就相当于 state:()=>{ return {} }
state: () => ({
profile: {
name: 'cp',
id: 1002
}
}),
mutations: {
serProfile(state) {
state.profile.name = 'pink'
}
}
}
export default user
// 改变这个模块的数据
store.commit('user/serProfile')
动态获取屏幕被卷去的距离
可以使用 @vueuse/core 来处理
bash
npm i @vueuse/core # 基于滚动事件,在滚动事件的回调函数中 不断的拿到当前屏幕由于滚动被卷去的距离
借助它可以快速实现导航栏吸顶的功能
使用 vuex
js
// 先在 store 文件写入 mutations、state、actions等
import { fetchCategory } from '@/api/home'
const category = {
namespaced: true, // 严格模块化
state: () => ({
categorylist: []
}),
mutations: {
setCategorylist(state, data) {
state.categorylist = data
}
},
actions: {
async fetchCategory(state) {
const res = await fetchCategory()
state.commit('setCategorylist', res.data.result)
}
}
}
export default category
js
// 在组件中使用 useStore 得到 vuex 实例,写入数据
import { useStore } from 'vuex'
export default {
setup() {
const store = useStore() // 类似于 vue2 中的 this.$store
store.dispatch('category/fetchCategory')
}
}
js
// 在组件中获取数据
import { computed } from 'vue'
import { useStore } from 'vuex'
export default {
setup() {
const store = useStore()
// 用 computed 映射数据
const categoryList = computed(() => {
return store.state.category.categorylist
})
return { categoryList }
}
}
插件注册和指令注册
js
// 写入插件方法
// vue3 中定义插件的写法
const plugin = {
// app 表示使用 use 方法 vue 调用插件内 install 方法传递过来的组件实例对象
install(app) {
// 插件逻辑
console.log(app)
app.directive('lazy', {
mounted(el, binding) {
// el 表示使用该指令的 DOM 元素,binding.value 表示外部组件传递给指令的数据
console.log(el, binding.value)
console.log(123)
}
})
}
}
export default plugin
借助 @vueuse/core 实现图片懒加载
js
// 引入监听是否进入视口
import { useIntersectionObserver } from '@vueuse/core'
// vue3 中定义插件的写法
const plugin = {
// app 表示使用 use 方法 vue 调用插件内 install 方法传递过来的组件实例对象
install(app) {
// 插件逻辑
app.directive('lazy', {
mounted(el, binding) {
const { stop } = useIntersectionObserver(
// 监听目标元素
el,
([{ isIntersecting }], observerElement) => {
// isIntersecting 表示当前元素是否进入可视范围
// 此监听非常精确,可以监听该元素横向纵向是否进入可视范围
console.log(isIntersecting)
if (isIntersecting) {
el.src = binding.value
// 当首次完成加载后停止监听(解绑事件,不需要再对其监听是否到达可视区域)
stop()
}
},
// 刚进入视口区域就立刻执行回调 0 - 1
// 值越大那么要求该元素需要进入可视范围面积更大才执行回调
{ threshold: 1 }
)
}
})
}
}
export default plugin
在 main.js 中注册
js
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import '@/styles/common.less'
import ComponentPlugin from '@/components'
import direactives from '@/direactives' // 引入插件
// vue3 中插件的注册不再是通过 Vue.use进行,而是通过 createApp(App).use(插件)并且vue3中插件注册支持串联执行
createApp(App)
.use(direactives) // 注册插件
.mount('#app')
在组件中使用以插件形式注册的指令
vue
<img v-lazy="item.picture" />
在 setup 中获取路由参数
js
import { ref } from 'vue'
import { useRoute } from 'vue-router'
import { getBanner, findTopCategory } from '@/api/home'
export default {
setup() {
const categroyAllList = ref({})
const route = useRoute() // 获取路由实例
async function TopCategory() {
const res = await findTopCategory(route.params.id) // 通过路由实例获取数据
categroyAllList.value = res.data.result.children
}
TopCategory()
return {
categroyAllList
}
}
}
路由缓存
js
// 默认情况下只要路径(路由参数发生变化不算路径变化)不发生变化对应组件的生命周期钩子也不会重新执行
解决一:不走缓存
vue
<!-- key 除了可以结合 v-for 使用增加 diff 时性能,还能强制替换元素/组件(重新渲染) -->
<!-- 给路由出口加上 key 属性 -->
<!-- fullPath:携带参数的完整路径 -->
<!-- 只要 key 值发生变化 router-view 会强制不走缓存,这样对应组件也会重新渲染 -->
<router-view :key="$route.fullPath"></router-view>
方案二:使用路由钩子
js
import { useRoute, onBeforeRouteUpdate } from 'vue-router'
export function useCategory() {
// 在路由跳转之后更新之前自动执行
onBeforeRouteUpdate(to => {
// to指代的是目标路由对象 to拿到最新的路由参数id
// 使用最新id获取数据
TopCategory(to.params.id)
})
return { categroyAllList }
}
v-model 语法糖
自定义弹框
js
import Message_ from './index.vue'
// Message({type:'success',text:'成功'})
import { createVNode, render } from 'vue'
export function Message({ type, text }) {
// createVNode 方法用于创建一个虚拟 DOM ,第一个参数表示要创建的 DOM 元素(组件),第二个参数表示该节点(组件)
// 的属性(组件为 props属性),第三个参数表示子节点
const VNode = createVNode(Message_, { type, text })
const divContainer = document.createElement('div')
document.body.appendChild(divContainer)
// render 方法用于将虚拟DOM 渲染成真实DOM ,第一个参数表示需要渲染的 Vnode ,第二个参数表示要挂载在哪个节点上
render(VNode, divContainer)
setTimeout(() => {
// 一段时间后清除弹框
document.body.removeChild(divContainer)
}, 1500)
}
// 在组件中使用
//////////////////////////////////////////////////////
import { Message } from '@/components/Message/index.js'
//////////////////////////////////////////////////////
export default {
setup() {
async function doValidate() {
const result = await formTarget.value.validate()
if (result) {
await store.dispatch('user/asyncSetUser', form)
if (route.query.endPath) {
router.push(route.query.endPath)
} else {
router.push('/')
}
//////////////////////////////////////////////////////
Message({ type: 'success', text: '登录成功' })
//////////////////////////////////////////////////////
}
}
return {
form,
mySchema,
formTarget,
doValidate
}
}
}
vuex 问题
js
// 当模板中使用 v-model 直接修改 vuex 中的数据且 vuex 开启了严格模式,会导致报错
export default createStore({
// 开启严格模式,只允许通过 mutations 去修改 state 的数据否则报错
strict: true,
state: {},
mutations: {},
actions: {},
modules: {
user,
cart,
category
}
})
vue
<XtxCheckbox v-model="i.selected" />
传递多个参数
vue
<script>
// 当子组件通过 emit 传递参数时
emit('change', checked.value)
</script>
<!-- 父组件接收数据,但如果在这里再传递一个参数时该怎么办? 就像 @change="selectedval(val,val2)"-->
<!-- 但这种写法只能接收到 val2 原本子组件的数据就拿不到了 -->
<XtxCheckbox @change="selectedval" />
<script>
// 父组件可以拿到对应数据
function selectedval(val) {
console.log(val)
}
</script>
<!-- 使用箭头函数来解决 -->
<XtxCheckbox @change="val => selectedval(val, val2)" />
<script>
// 模板中通过箭头函数的形式返回函数调用并传递参数这种写法,那么就可以同时拿到子组件和模板中传递的数据了
function selectedval(val,val2) {
console.log(val)
console.log(val2)
}
</script>
方便支付修改开发环境地址
js
/*
host文件配置
1. 找到 C:\Windows\System32\drivers\etc 下hosts文件
2. 在文件中加入 127.0.0.1 www.corho.com
3. 保存即可
# 如果提示没有权限
1. 将hosts文件移到桌面,然后进行修改,确认保存
2. 将桌面hosts文件替换c盘文件
*/
/*
vue.config.js配置
# 这个是给webpack-dev-server开启可IP和域名访问权限
chainWebpack: config => {
config.devServer.disableHostCheck(true)
}
配置完之后重启项目
*/