记一次基于vue的spa多页签实践经验

媒介

近来收到一个如许的需求,请求做一个基于 vue 和 element-ui 的通用背景框架页,细致请求以下:

  1. 请求通用性高,须要在后期四十多个子项目中运用,所以大部分处所都做成可设置的.
  2. 请求做成脚手架的情势.能够 npm 装置
  3. 请求完成多页签,而且能够经由过程浏览器 url 回显多页签.而且页签内要保护一个历史记录,能够退却
  4. 组件请求异步加载,削减首屏加载时刻.

很明显,这就是一个 类 ERP 的运用. 做过 JSP 等背景的同砚,对多页签应当都很熟习吧.

那接下来我们就来谈谈完成.

通用性高

这点实在没啥难点,不过就是贫苦了点,把一切的数据,都提取出来,放在一个 config 文件内里.然后在框架页内里引入,而且绑定到响应的位置上去. 这边有个比较难以弃取的题目,就是假如把一溜的数据悉数绑定到 vue 的 data 上面,因为数据量比较多,会致使机能题目,假如离开,又会使设置文件看起来相对庞杂,增添后期运用职员的进修本钱。这块要看细致的项目需求,因为我这边临时对前端的机能请求没那末高,所以临时用悉数绑定到 data 的计划

做成脚手架情势

早先产物对这个的需求使做成组件的情势,然后宣布 npm 包,轻易后期更新的时刻,只需更新一下 npm 就可以够了,无需每一个项目去复制粘贴替代,然则基于这是一个框架页,而且可设置项异常多,还要完成 tab 多页签等多方面的斟酌,终究挑选了脚手架的计划,即使如许后期升级会轻微贫苦一点(早先的计划是框架页放在一个文件夹里,到时刻直接替代该文件夹),但相对于组件来讲,照样更好保护的,何况后期能够再写一个更新的脚手架,毕竟如今宣布一个 npm 东西的本钱实在是太低了。

第一次开辟脚手架,看了许多社区的帖子,发明现在大部分脚手架,平常都基于2种情势,一种基于文件复制的情势,另一种基于 git-clone 的情势,经由对照,我以为文件复制的有点庞杂了,我实在只是须要一个能一键装置的东西罢了,所以 git-clone 的情势照样比较合适我。

以下就是脚手架的代码,虽然只是简朴的五六十行代码,不过查资料+趟坑,也花了我一个上午的时刻。

#!/usr/bin/env node
const shell = require('shelljs');
const program = require('commander');
const inquirer = require('inquirer');
const ora = require('ora');
const fs = require('fs');
const path = require('path');
const spinner = ora();
const gitClone = require('git-clone')
const chalk = require('chalk')


program
    .version('1.0.0', '-v, --version')
    .parse(process.argv);

const questions = [{
  type: 'input',
  name: 'name',
  message: '请输入项目名称',
  default: 'my-project',
  validate: (name)=>{
    if(/^[a-z]+/.test(name)){
      return true;
    }else{
      return '项目名称必需以小写字母开首';
    }
  }
}]

inquirer.prompt(questions).then((dir)=>{
  downloadTemplate(dir.name);
})

function downloadTemplate(dir){

  //  推断目次是不是已存在
  let isHasDir = fs.existsSync(path.resolve(dir));
  if(isHasDir){
    spinner.fail('当前目次已存在!');
    return false;
  }
  spinner.start(`您挑选的目次是: ${chalk.red(dir)}, 数据加载中,请稍后...`);

  // 克隆 模板文件
  gitClone(`https://github.com/noahlam/vue-multi-tab.git`, dir , null, function(err) {
    // 移除无用的文件
    shell.rm('-rf', `${dir}/.git`)
      spinner.succeed('项目初始化胜利!')
    // 运转常用命令
    shell.cd(dir)
      spinner.start(`正在帮您装置依靠...`);
    shell.exec('npm i')
      spinner.succeed('依靠装置胜利!')
    shell.exec('npm run dev')
  })
}

假如你这个脚手架有疑问或许兴致,能够直接接见 github 上的代码 tab-cli

完成多页签

要想完成多页签,那末 vue-router 基础算是废了,为何? vue-router 是依据 url 来切换单个组件的,而页签则须要再组件内部同时存在多个子组件的,所以路由没法胜任(最少我是这么以为的,假如你有更好的计划,恳请不吝赐教)。

多个页签的显现,实在不难, element 有现成的 tab 组件,因而老汉写代码就是一把梭,撸起袖子就是干,噼里啪啦一顿写,写完一测,没有任何题目,实在是不要太简朴,丢给产物预览:

  1. 复制浏览器地点到别的处所粘贴,tab 不能准确回显
  2. tab 内须要完成跳转,而且要能返回。

第一个题目比较简朴,本身手写一个基于 hash 的 伪路由 把当前 tab 的 id 放到 url 上去,然后回显的时刻,依据 url 翻开对应的 tab.

tip: 关于怎样完成路由,请看我别的一篇博客
本身着手完成一个前端路由

第二个题目,也许就是本文的重点了,这里细致申明一下需求,每一个 tab 都能够在 tab 内部 跳转 ,这里的跳转,要做的跟 vue-router 的有大体上差不多,要能 push, replace, back,还能带参数。

那末怎样完成呢? 起首保护一个翻开的 tab 列表,然后每一个列表内里再保护一个用过的组件列表(包括参数),如许也许就可以完成了吗?固然不是,组件的跳转,参数的通报,不可能让运用者本身去完成这些要领吧,我挑选把封装一个大众对象,然后挂载在 vue.prototype上。然后相似 vue.$router.xxxx 一样(我的定名是 vue.$tab)能够在页面的任何处所运用,假如你对细致的完成要领有兴致,迎接点击本文末端的链接,去我的Github堆栈上检察。

组件异步加载

之前只用过基于 vue-router 的异步加载要领,但是这个项目内里并没有运用 vue-router,怎样异步呢? 翻了一下 vue 的官方文档是这么写的:

Vue.component(
  'async-webpack-example',
  // 这个 `import` 函数会返回一个 `Promise` 对象。
  () => import('./my-async-component')
)

但是我试了一下,发明报错了,import 不能在这里运用,换了 require 也不可,不晓得上我那里没弄好,假如你恰好晓得又恰好有空,请告诉我,感谢!背面在 segmentfault 上 看到 这一篇, 运用 webpack 的 require.ensure 能够完成

// 第一个字符串是 组件名,第二个是 组件途径,第三个是 chunkName (假如不指定则以1.js,2.js....n.js定名)
vue.component('home', (resolve) => {require.ensure([], ()=>resolve(require('@/Views/index.vue')), 'home')})

趁便还要在 webpack 内里的 output 下面设置一下 chunkFilename: '[name].js',, 固然文件名花样能够按你项目标需求来,我这边就按最简朴的

结束语

起首,固然上献上该项目标 github地点

其次是本文的的地点 个人手艺帖合集

以上项目 迎接随便 starfollow, 和不随便的 issue

    原文作者:noahlam
    原文地址: https://segmentfault.com/a/1190000016035719
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞