前言

最近收到一个这样的需求,要求做一个基于 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地址 咯

其次是本文的的地址 个人技术帖合集

以上项目 欢迎随意 star 和 follow, 和不随意的 issue

本文转载于:猿2048canvas菜鸟基于小程序实现图案在线定制功能

canvas菜鸟基于小程序实现图案在线定制功能的更多相关文章

  1. 微信小程序添加悬浮在线客服会话按钮

    微信为小程序提供客服消息能力,小程序用户可以方便快捷地与小程序服务提供方进行沟通,并且已经做成了组件的形式,直接就可以调用.客服会话按钮,用于在页面上显示一个客服会话按钮,用户点击该按钮后会进入客服会 ...

  2. 基于微信小程序的用户列表点赞功能

    代码地址如下:http://www.demodashi.com/demo/13997.html 一.前言 (1).适合人群 1.微信小程序开发者 2.前端工程师 3.想入门学习小程序开发的人员 4.想 ...

  3. 基于小程序请求接口 wx.request 封装的类 axios 请求

    基于小程序请求接口 wx.request 封装的类 axios 请求 Introduction wx.request 的配置.axios 的调用方式 源码戳我 feature 支持 wx.reques ...

  4. 基于小程序云Serverless开发微信小程序

    本文主要以使用小程序云Serverless服务开发一个记事本微信小程序为例介绍如何使用小程序云Serverless开发微信小程序.记事本小程序的开发涉及到云函数调用.云数据库存储.图片存储等功能,较好 ...

  5. 记录使用微信小程序的NFC和蓝牙功能读取15693芯片的开发历程

    开发目标: (1) 对于Android手机,直接通过微信小程序调用手机的NFC功能,对15693协议的芯片进行读写操作: (2)对于苹果手机(及没有NFC模块的手机),通过微信小程序的蓝牙功能连接到蓝 ...

  6. 微信小程序实现即时通信聊天功能的实例代码

    项目背景:小程序中实现实时聊天功能 一.服务器域名配置 配置流程 配置参考URL:https://developers.weixin.qq.com/miniprogram/dev/api/api-ne ...

  7. h5内嵌微信小程序,调用微信支付功能

    在小程序中不能使用之前在浏览器中配置的支付功能,只能调用小程序专属的api进行支付. 因为需要在现在实现的基础上,再添加在小程序中调用微信支付功能,所以我的思路是这样的 1.在点击支付按钮时,判断是不 ...

  8. 【微信小程序canvas】实现小程序手写板用户签名(附代码)

    工作中公司业务需要的微信小程序用户签字功能 先看效果图: wxml: <view class="wrapper"> <view class="handB ...

  9. 基于vs2015 SignalR开发的微信小程序使用websocket实现聊天功能

    一)前言 在微信小程上实现聊天功能,大致有三种方式:1)小程序云开发 2)购买第三方IM服务 3)使用自己的服务器自己开发. 这里重要讲使用自己的服务器自己开发,并且是基于vs的开发. 网上提供的解决 ...

随机推荐

  1. WinRar:你需要从上一压缩卷启动解压命令以便解压

    大文件被分解成许多个小的RAR文件,并按顺序排列好,解压时只需解压第一个RAR文件即可顺利解压所有文件,如果不按顺序解压就会出现上述问题,导致解压完一个子文件候无法解压剩下的文件

  2. Python:GUI库tkinter(三)

    这一章是对前两章的总结: Python:GUI库tkinter(一) Python:GUI库tkinter(二) 前两章是对控件的介绍,第一章可以知道各控件使用时的具体参数,第二章以具体的例子展示了每 ...

  3. 网络爬虫深究-初识HTTP和https常识

    网络爬虫专题--HTTP基本原理 URI和URL.URN的关系 超文本 HTTP和HTTPS URI和URL 首先,我们来了解一下URI和URL,URI,即统一资源标志符,URL,即统一资源定位符. ...

  4. npm cnpm yarn 安装

    安装node.js,其中已经集成了npm,可以将npm切换到国内镜像 $ npm config set registry https://registry.npm.taobao.org -- 配置后可 ...

  5. JAVA的对象和封装及static与final的用法(详解)

    一:软件出现的目的 1:用计算机的语言描述现实世界 2:用计算机解决现实世界的问题 编程思维:  使用面向对象的思想(描述)面向对象的世界     (符合人类的思维习惯) 二:面向对象设计和开发程序的 ...

  6. LeetCode-019-删除链表的倒数第 N 个结点

    删除链表的倒数第 N 个结点 题目描述:给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点. 进阶:你能尝试使用一趟扫描实现吗? 示例说明请见LeetCode官网. 来源:力扣(Leet ...

  7. 在SpringBoot项目中添加SpringMVC拦截器

    1.认识拦截器 SpringMVC的拦截器(Interceptor)不是Filer,同样可以实现请求的预处理.后处理.使用拦截器仅需要两个步骤 实现拦截器 注册拦截器 1.1实现拦截器 实现拦截器可以 ...

  8. PHP 的网站主要攻击方式有哪些?

    1.命令注入(Command Injection)2.eval 注入(Eval Injection)3.客户端脚本攻击(Script Insertion)4.跨网站脚本攻击(Cross Site Sc ...

  9. 深度学习(一)之MNIST数据集分类

    任务目标 对MNIST手写数字数据集进行训练和评估,最终使得模型能够在测试集上达到\(98\%\)的正确率.(最终本文达到了\(99.36\%\)) 使用的库的版本: python:3.8.12 py ...

  10. Source Code Reading for Vue 3: How does `hasChanged` work?

    Hey, guys! The next generation of Vue has released already. There are not only the brand new composi ...