Vite2+vue3+ts 使用 router,layout 搭建页面框架,并做页面自适应

Vite2+vue3+ts 使用 router,layout 搭建页面框架,并做页面自适应

vue3 对应使用的是 vue-router@4 版本, 有新的用,但是向下兼容
本文档源码:Lzq811/vite-vue-ts-eslint at vite2+vue3+ts使用vue-router搭建页面框架 (github.com)

1. 安装使用 vue-router@4

  1. install

    yarn add vue-router@4 # 一定要@4哦,不然会安装3版本导致不兼容vue3
    
  2. src 下新建 pages 文件夹,并添加 login/index.vuehome/index.vue 文件,并随便初始化一下组件内容。

  3. src 下新建 routes 文件夹,并添加 index.tsxroutesNames.tsx 文件

// index.tsx
import { createRouter, createWebHistory } from 'vue-router'
import * as RouteNames from './routesname'

interface RoutesItem {
  path: string
  component: any
  name?: string
  redirect?: string
}

const routes: Array<RoutesItem> = [
  {
    path: '/',
    redirect: '/home',
    component: () => import('@pages/home/index.vue'),
  },
  {
    path: '/default',
    name: RouteNames.HOME,
    component: () => import('@pages/home/index.vue'),
  },
  {
    path: '/home',
    name: RouteNames.HOME,
    component: () => import('@pages/home/index.vue'),
  },
  {
    path: '/login',
    name: RouteNames.LOGIN,
    component: () => import('@pages/login/index.vue'),
  },
]

// 配置路由
const router = createRouter({
  history: createWebHistory(),
  routes,
})

router.beforeEach((to, from) => {
  const { path: toPath } = to
  const { path: fromPath } = from
  if (toPath === fromPath) {
    return false
  }
})

export default router
// routesNames.tsx
// 管理所有路由名称
export const LOGIN: string = 'LOGIN'
export const HOME: string = 'HOME'
  1. Login 组件中 点击 跳转到 Home 页面

    // Login.vue
    import { useRouter } from 'vue-router'
    
    const router = useRouter()
    
    const jumpTohome: any = (): void => {
      router.replace('/home')
    }
    // 执行jumpTohome方法就能跳转到home页面了
    

2. Home 页面布局

  1. src/components 文件夹下创建文件 src/components/common/aside/index.vuesrc/components/common/head/index.vue
// head.vue
<template>
  <div>
    <el-dropdown>
      <el-icon style="margin-right: 15px"><setting /></el-icon>
      <template #dropdown>
        <el-dropdown-menu>
          <el-dropdown-item>View</el-dropdown-item>
          <el-dropdown-item>Add</el-dropdown-item>
          <el-dropdown-item>Delete</el-dropdown-item>
        </el-dropdown-menu>
      </template>
    </el-dropdown>
    <span>Tom</span>
  </div>
</template>

<script lang="ts" setup></script>

<style lang="less" scoped></style>
// asise.vue
<template>
  <el-aside :width="asidewidth" class="aside-com">
    <div class="logo-box">LOGO</div>
    <el-button
      type="primary"
      @click="showCollapse"
      :icon="isCollapse ? Fold : Expand"
    ></el-button>
    <el-menu
      class="menus-box"
      active-text-color="#00A2D8"
      text-color="#fff"
      background-color="rgba(0,0,0,0)"
      :default-openeds="['1', '3']"
      :collapse="isCollapse"
    >
      <el-sub-menu v-for="item in Menus" :key="item.order" :index="item.order">
        <template #title>
          <el-icon :size="24" color="#fff">
            <component :is="item.icon"></component>
          </el-icon>
          <span>{{ item.title }}</span>
        </template>
        <el-menu-item
          v-for="menu in item.children"
          :key="menu.index"
          :index="menu.index"
          >{{ menu.name }}</el-menu-item
        >
      </el-sub-menu>
    </el-menu>
  </el-aside>
</template>

<script lang="ts" setup>
  import { Location, Fold, Expand } from '@element-plus/icons'
  import { onMounted, ref } from 'vue'

  const Menus = ref([
    {
      title: '基础配置',
      order: 'base',
      icon: Location,
      children: [
        { name: '二级菜单1', index: '1-1' },
        { name: '二级菜单2', index: '1-2' },
      ],
    },
    {
      title: '收发货管理',
      order: 'manage',
      icon: Location,
      children: [
        { name: '二级菜单1', index: '2-1' },
        { name: '二级菜单2', index: '2-2' },
      ],
    },
    {
      title: '运营监控',
      order: 'control',
      icon: Location,
      children: [
        { name: '二级菜单1', index: '2-1' },
        { name: '二级菜单2', index: '2-2' },
      ],
    },
  ])
  const isCollapse = ref(false)
  const asidewidth = ref('180px')

  onMounted(() => {})

  const handleOpen = (key: any, keyPath: any): void => {
    console.log(key, keyPath)
  }
  const handleClose = (key: any, keyPath: any): void => {
    console.log(key, keyPath)
  }
  const showCollapse = (): void => {
    isCollapse.value = !isCollapse.value
    asidewidth.value = !isCollapse.value ? '180px' : '60px'
  }
</script>

<style lang="less">
  .aside-com {
    height: 100%;
    box-sizing: border-box;
    overflow: hidden;
    transition: all 0.25s linear;
    background-color: #1f2f48;
    .logo-box {
      width: 100%;
      height: 60px;
      background-color: rgba(255, 255, 255, 0.4);
      text-align: center;
      line-height: 60px;
    }
    .menus-box {
      border: none;
      transition: all 0.2s linear;
    }
  }
</style>
  1. 修改 home/index.vue
<template>
  <el-container class="home-page">
    <aside></aside>
    <el-container>
      <el-header class="head-com"><head></head></el-header>
      <el-main> 主体内容 </el-main>
    </el-container>
  </el-container>
</template>
<script lang="ts" setup>
  import Aside from '@components/common/aside/index.vue'
  import Head from '@components/common/head/index.vue'
</script>

<style lang="less" scoped>
  .home-page {
    height: 100%;
  }
  .head-com {
    width: 100%;
    background-color: #1f2f48;
  }
</style>
  1. 其中 __dirname找不到的解决办法

    yarn add @types/node --save-dev
    
  2. 配置 alias 路径别名

    // vite.config.ts
    resolve: {
        alias: {
          // 如何 __dirname 找不到 需要 yarn add @types/node --save-dev
          '@': path.resolve(__dirname, 'src'),
          '@api': path.resolve(__dirname, 'src/api'),
          '@pages': path.resolve(__dirname, 'src/pages'),
          '@routes': path.resolve(__dirname, 'src/routes'),
          '@components': path.resolve(__dirname, 'src/components')
        }
      },
    

3. 页面自适应

  1. 安装
yarn add postcss-plugin-px2rem
yarn add amfe-flexible
  1. 修改配置

    // main.ts
    import 'amfe-flexible'
    
    // vite.config.ts  一定要注意 postcss 的位置,不要写在了 preprocessorOptions 对象里面
    css: {
        preprocessorOptions: {
          less: {
            javascriptEnabled: true,
            // 这样就能全局使用 src/assets/styles/base.less 定义的 变量
            additionalData: `@import "${path.resolve(__dirname, 'src/assets/styles/reset.less')}";`
          }
        },
        postcss: {
          plugins: [
            require('postcss-plugin-px2rem')({
              rootValue: 192, //换算基数, 默认100  ,这样的话把根标签的字体规定为1rem为50px,这样就可以从设计稿上量出多少个px直接在代码中写多上px了。
              // unitPrecision: 5, //允许REM单位增长到的十进制数字。
              //propWhiteList: [],  //默认值是一个空数组,这意味着禁用白名单并启用所有属性。
              // propBlackList: [], //黑名单
              exclude: /(node_module)/, //默认false,可以(reg)利用正则表达式排除某些文件夹的方法,例如/(node_module)/ 。如果想把前端UI框架内的px也转换成rem,请把此属性设为默认值
              // selectorBlackList: [], //要忽略并保留为px的选择器
              // ignoreIdentifier: false,  //(boolean/string)忽略单个属性的方法,启用ignoreidentifier后,replace将自动设置为true。
              // replace: true, // (布尔值)替换包含REM的规则,而不是添加回退。
              mediaQuery: false, //(布尔值)允许在媒体查询中转换px。
              minPixelValue: 3 //设置要替换的最小像素值(3px会被转rem)。 默认 0
            })
          ]
        }
      }
    
  2. 查看页面的文字或者盒子大小是否已经从 px 单位 变成了 rem 单位。

本文的对应源码地址: Lzq811/vite-vue-ts-eslint at vite2+vue3+ts使用vue-router搭建页面框架 (github.com)

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容