硅谷甄选前端Vue3+TS学习笔记

vue3+ts

水平一般,还在学习阶段,主要是记录一些自己使用不怎么熟练的,欢迎指导与讨论。

nextTick

使用场景:layout中main组件,进行刷新时重新获取路由发送请求,策略为销毁路由再重新创建,不使用定时器时因为不能明确路由何时被销毁。

<template>
  <!-- 路由组件出口的位置-->
    <router-view v-slot="{ Component }">
        <transition name="fade">
            <!-- 渲染layout一级路由的子路由 -->
            <component :is="Component" v-if="mainFLag"></component>
        </transition>
    </router-view>
</template>

<script setup lang="ts">
import useLayoutSettingStore from "@/store/modules/setting.ts";
import {watch, ref, nextTick} from "vue";

let useLayoutStore = useLayoutSettingStore()

let mainFLag = ref(true)
watch(() => useLayoutStore.refresh, () => {
    // 先销毁路由组件的dom
    mainFLag.value = false
    // 使用nextTick保证路由组件销毁后再创建而不是延时器
    nextTick(() => {
        mainFLag.value = true
    })
})
</script>

暗黑模式与主题颜色的切换

看element-plus官方文档即可,main.ts引入相应样式文件,获取根节点元素添加dark属性即可。

对于暗黑模式,如果有设置颜色的样式应该是不起作用的。(所以如果出现部分黑色但其他未发生拜年话的情况,可以检查一下是否已设置color属性)

const changeColor = () => {
    const html = document.documentElement
    html.style.setProperty('--el-color-primary',color.value)
}

// 暗黑模式开关
let dark = ref(false)

const changeDark = () => {
    // 获取根节点,加上一个dark属性即可
    let html = document.documentElement
    dark.value ? html.className = 'dark' : html.className = ''
}

数据大屏

重点是屏幕大小的适配

两种解决思路:第一种:vw,vh;第二种:scale

对于第一种需要进行相应数值的计算,例如父组件100vh对应1920px,如果子组件设计稿高度为192px,那么应该设置为10vh。

第二种无需计算,但是要注意scale的缩放是以最近一层父组件的中心位置进行缩放,所以要注意嵌套的关系来确定缩放的中心;需要解决留白问题

一些组件使用

el-tree:一定注意是    :props  组件label一直没渲染出来,找了好久的bug

<el-tree
                    ref="menuTree"
                    :data="menuArr"
                    show-checkbox
                    node-key="id"
                    :default-checked-keys="selectPermissionArr"
                    :props="defaultProps"
            />
// 递归将所选数据存入数组
const filterSelectArr = (allData: any, initArr: any) => {
    allData.forEach((item: any) => {
        if (item.select && item.level === 4) {
            initArr.push(item.id)
        }
        if (item.children && item.children.length > 0 && item.select ) {
            filterSelectArr(item.children, initArr)
        }
    })
    return initArr
}

路由的使用(配置注意数组还是对象的形式)

this.menuRoutes = [...constantRoutes, ...userAsyncRoute, ...anyRoute]解析代码:

这行代码是在定义一个名为menuRoutes的变量,并将其赋值为一个由三个数组合并而成的新数组。这三个数组分别是constantRoutesuserAsyncRouteanyRoute

constantRoutesuserAsyncRouteanyRoute是预先定义好的数组,它们可能包含一些路由配置对象。通过使用[...]语法,这些数组的元素会被展开并合并到一个新数组中。

最终,menuRoutes将成为一个包含了三个数组中所有元素的新数组。

this.menuRoutes = [...constantRoutes, ...userAsyncRoute, anyRoute解析代码:

这行代码有一个细微的差别,最后一个数组anyRoute没有使用展开操作符[...]。因此,anyRoute将被当作一个单独的元素添加到menuRoutes数组中。

所以,menuRoutes将会包含constantRoutesuserAsyncRoute数组中的元素,以及anyRoute作为一个单独的元素。最终,menuRoutes将成为一个新数组,包含了这些元素。

异步路由加载白屏

本项目采用的路由首先存储管理常量路由,每个用户分配的异步路由是动态追加的,因此可能出现的问题是:在异步路由处刷新,虽然可能获取到用户信息,但异步路由还没有加载完毕即出现空白效果.。

解决方案:保证路由加载完成再放行。

 await userStore.userInfo()
 next({ ...to })

自定义指令

指令可以做哪些事情

  • 操作渲染dom,比如vFocus、vMyHtml、数据格式转换
  • 图片懒加载
  • 上拉加载更多
  • 下拉刷新
  • ......

本项目中有一个控制按钮权限(按钮dom渲染)的实例:

入口文件注册:

// 引入自定义指令
import {isHasButton} from "@/directives/has.ts";
isHasButton(app)

app.mount('#app')

编写指令:

import pinia from '@/store'
import useUserStore from "@/store/modules/user.ts";

let useStore = useUserStore(pinia)

export const isHasButton = (app:any) => {
    // 获取对应的用户仓库
    app.directive('has', {
        //使用这个指令的dom组件在挂载完毕时会执行一次
        mounted(el:any, binding:any) {
            // 若用户信息中没有buttons就会禁用
            console.log(binding.value)
            if(!useStore.buttons.includes(binding.value)){
                el.parentNode.removeChild(el)
            }
        }
    } )
}

使用:

 <el-button @click="addDialog" v-has="`has`">新增用户</el-button>

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值