vConsole

A lightweight, extendable front-end developer tool for mobile web page.
一个轻量级、可扩展的移动网页前端开发工具
是腾讯的一个开源工具。

功能:

查看控制台日志

查看网络请求

查看文件元素

查看Cookies、LocalStorage和SessionStorage。

手动执行JS命令

自定义插件

使用方法:

npm install vconsole

or

<script src="path/to/vconsole.min.js"></script>
<script>// init vConsolevar vConsole = new VConsole();console.log('Hello world');
</script>

打印的类型有5种+2种

5 types of log method are supported, with different styles:console.log('foo');   // black word, white bakcground
console.info('bar');  // purple word, white background
console.debug('oh');  // orange word, white background
console.warn('foo');  // orange word, yellow background
console.error('bar'); // red word, pink background
Supported console methods:console.time('foo');    // start a timer named "foo"
console.timeEnd('foo'); // stop "foo" timer and print the elapsed time

公共属性和方法:

属性:

vConsole.version
Readonly
Type: string
vConsole.version // => "3.4.1"
vConsole.option
Writable
Type: object
// get
vConsole.option // => {...}
// set
vConsole.setOption('maxLogNumber', 5000);
// or:
vConsole.setOption({maxLogNumber: 5000});
vConsole.activedTab //The actived tab's plugin id.
Readonly
Type: string
Default: "default"
vConsole.activedTab // => "system"
vConsole.tabList
A list of installed tabs' plugin id.Readonly
Type: array(string)
Example:vConsole.tabList // => ["default", "system"]
vConsole.$dom
vConsole's HTML element.Type: HTMLDivElement

方法:

vConsole.setOption(keyOrObj[, value])
vConsole.setOption('maxLogNumber', 5000);
// or:
vConsole.setOption({maxLogNumber: 5000});
vConsole.setSwitchPosition(x, y)
Update the position of switch button.
vConsole.setSwitchPosition(20, 20);
vConsole.destroy()
Destroy an vConsole instance object and remove vConsole panel from document.
var vConsole = new VConsole();
// ... do something
vConsole.destroy();
vConsole.addPlugin(plugin)
Add a new plugin to vConsole. Duplicate plugin will be ignored.
var myPlugin = new VConsolePlugin('my_plugin', 'My Plugin');
vConsole.addPlugin(myPlugin);
vConsole.removePlugin(pluginID)
vConsole.showTab(pluginID)
Activating a tab according to its plugin id.Plugin event hide will be triggered for previous actived tab, and show for current actived tab.
vConsole.showTab("system"); // show System tab
vConsole.show()
Show vConsole panel. This method will trigger plugin event showConsole.
vConsole.hide()
Hide vConsole panel. This method will trigger plugin event hideConsole.
vConsole.showSwitch()
Show vConsole switch button.
vConsole.hideSwitch()
Hide vConsole switch button.

可以看到vconsole有很多属性和方法,我们是可以改造,增加插件等自己做很多事情的。
同时,它还提供了很大辅助功能,我们可以操作dom元素,增加,删除,修改,渲染等。
存储,监听事件等。
列举几个重要的:

vConsole.$.render(tpl, data, toString)
Compile a template into an element object or a HTML string with given data.
将一个模板编译成一个元素对象或一个HTML字符串。
var tpl = '<ul>' +'{{for (var i = 0; i < list.length; i++)}}' +'<li>' + '{{list[i]}}' + '</li>' +'{{/for}}' +
'</ul>';
var data = {list: ['Red', 'Blue', 'Yellow']
};var html = vConsole.$.render(tpl, data, true);
document.body.innerHTML += html;
vConsole.$.bind(elements, eventType, fn, useCapture)
将一个事件绑定到元素上。
var $btn = vConsole.$.one('#submit');
vConsole.$.bind($btn, 'click', function(event) {event.preventDefault();alert('submit!');
});
vConsole.$.addClass(elements, className)
Add the specified class(es) to element(s).将指定的类添加到元素
var $items = vConsole.$.all('.item');
vConsole.$.addClass($items, 'selected');
vConsole.$.all(selectors, baseElement)
返回文档或baseElement中符合指定选择器组的元素列表。

更多详情请看这

增加插件

三部曲:

  1. 创建一个vConsole插件对象
  2. 将插件事件绑定到该对象
  3. 将此对象添加到vConsole
var myPlugin = new VConsole.VConsolePlugin('my_plugin', 'My Plugin');myPlugin.on('init', function() {console.log('My plugin init');
});
myPlugin.on('renderTab', function(callback) {var html = '<div>Click the tool button below!</div>';callback(html);
});
myPlugin.on('addTool', function(callback) {var button = {name: 'Reload',onClick: function(event) {location.reload();}};callback([button]);
});vConsole.addPlugin(myPlugin);

console-webpack-plugin

webpack plugin for vConsole

帮助开发者在移动端进行调试,本插件是在 vConsole 的基础上封装的 webpack 插件,通过 webpack 配置即可自动添加 vConsole 调试功能,方便实用。

安装

npm install vconsole-webpack-plugin --save-dev

使用
webpack.conf.js 文件配置里增加以下插件配置即可

// 引入插件

var vConsolePlugin = require('vconsole-webpack-plugin'); module.exports = {...plugins: [new vConsolePlugin({filter: [],  // 需要过滤的入口文件enable: true // 发布代码前记得改回 false}),...]...
}

vConsole 作为一个调试模块,注定了需要在发布前把它去掉,为了避免人为操作失误而影响线上功能,这里建议配置如下:

package.json 文件配置:

scripts: {"dev": "webpack -w --debug","prod": "webpack -p"
}

webpack.conf.js 配置:

// 引入插件

var vConsolePlugin = require('vconsole-webpack-plugin');

// 接收运行参数

const argv = require('yargs').describe('debug', 'debug 环境') // use 'webpack --debug'.argv;module.exports = {...plugins: [new vConsolePlugin({enable: !!argv.debug}),...]...
}

这样,在开发的时候运行 npm run dev,发布的时候运行 npm run prod 即可。

webpack-dev-server 的配套用法:

用法其实跟上面一样,只是别忘记在启动脚本的时候增加 --debug 即可。如下:

  // package.json"scripts": {..."start:dev": "webpack-dev-server --debug",...},

vconsole-stats-plugin

一个vConsole插件,可以在前端显示统计信息。

基于统计https://github.com/mrdoob/stats.js

import VConsole from 'vconsole';
import VConsoleStatsPlugin from 'vconsole-stats-plugin';
const vConsole = new VConsole();
const plugin = new VConsoleStatsPlugin(vConsole);

JavaScript性能监控

该类提供了一个简单的信息框,可以帮助你监控你的代码性能。

FPS 在最后一秒渲染的帧数。数字越高越好。

MS 渲染一帧所需的毫秒数。数值越低越好。

MB 分配的内存字节数。(使用–enable-precise-memory-info运行Chrome浏览器)

CUSTOM 用户自定义面板支持。
简单放几张图:


有了上面的基础,就开始撸源码吧:
nice!

// Vconsole类
class VConsole {constructor(opt) {if (!!$.one(VCONSOLE_ID)) {console.debug('vConsole is already exists.');return;}let that = this;this.version = pkg.version;this.$dom = null;this.isInited = false;// 面板展示的内容'system', 'network', 'element', 'storage'this.option = {defaultPlugins: ['system', 'network', 'element', 'storage']};this.activedTab = '';// 激活的tabthis.tabList = [];this.pluginList = {};this.switchPos = {hasMoved: false, // exclude click eventx: 0, // righty: 0, // bottomstartX: 0,startY: 0,endX: 0,endY: 0};// export helper functions to publicthis.tool = tool;this.$ = $;// merge optionsif (tool.isObject(opt)) {for (let key in opt) {this.option[key] = opt[key];}}// add built-in pluginsthis._addBuiltInPlugins();// try to initlet _onload = function() {if (that.isInited) {return;}that._render();that._mockTap();that._bindEvent();that._autoRun();};if (document !== undefined) {if (document.readyState === 'loading') {$.bind(window, 'DOMContentLoaded', _onload);} else {_onload();}} else {// if document does not exist, wait for itlet _timer;let _pollingDocument = function() {if (!!document && document.readyState == 'complete') {_timer && clearTimeout(_timer);_onload();} else {_timer = setTimeout(_pollingDocument, 1);}};_timer = setTimeout(_pollingDocument, 1);}}
  /*** add built-in plugins*/_addBuiltInPlugins() {// add default log pluginthis.addPlugin(new VConsoleDefaultPlugin('default', 'Log'));// add other built-in plugins according to user's configconst list = this.option.defaultPlugins;const plugins = {'system': {proto: VConsoleSystemPlugin, name: 'System'},'network': {proto: VConsoleNetworkPlugin, name: 'Network'},'element': {proto: VConsoleElementPlugin, name: 'Element'},'storage': {proto: VConsoleStoragePlugin, name: 'Storage'}};if (!!list && tool.isArray(list)) {for (let i=0; i<list.length; i++) {let tab = plugins[list[i]];if (!!tab) {this.addPlugin(new tab.proto(list[i], tab.name));} else {console.debug('Unrecognized default plugin ID:', list[i]);}}}}
 /*** render panel DOM* @private*/_render() {if (! $.one(VCONSOLE_ID)) {const e = document.createElement('div');e.innerHTML = tpl;document.documentElement.insertAdjacentElement('beforeend', e.children[0]);}this.$dom = $.one(VCONSOLE_ID);// reposition switch buttonconst $switch = $.one('.vc-switch', this.$dom);let switchX = tool.getStorage('switch_x') * 1,switchY = tool.getStorage('switch_y') * 1;this.setSwitchPosition(switchX, switchY);// modify font-sizeconst dpr = window.devicePixelRatio || 1;const viewportEl = document.querySelector('[name="viewport"]');if (viewportEl && viewportEl.content) {const initialScale = viewportEl.content.match(/initial\-scale\=\d+(\.\d+)?/);const scale = initialScale ? parseFloat(initialScale[0].split('=')[1]) : 1;if (scale < 1) {this.$dom.style.fontSize = 13 * dpr + 'px';}}// remove from less to present transition effect$.one('.vc-mask', this.$dom).style.display = 'none';// set themethis._updateTheme();}
 /*** auto run after initialization* @private*/_autoRun() {this.isInited = true;// init pluginsfor (let id in this.pluginList) {this._initPlugin(this.pluginList[id]);}// show first tabif (this.tabList.length > 0) {this.showTab(this.tabList[0]);}this.triggerEvent('ready');}
 /*** trigger a vConsole.option event* @protect*/triggerEvent(eventName, param) {eventName = 'on' + eventName.charAt(0).toUpperCase() + eventName.slice(1);if (tool.isFunction(this.option[eventName])) {this.option[eventName].apply(this, param);}}
 /*** init a plugin* @private*/_initPlugin(plugin) {let that = this;plugin.vConsole = this;// start initplugin.trigger('init');// render tab (if it is a tab plugin then it should has tab-related events)plugin.trigger('renderTab', function(tabboxHTML) {// add to tabListthat.tabList.push(plugin.id);// render tabbarlet $tabbar = $.render(tplTabbar, {id: plugin.id, name: plugin.name});$.one('.vc-tabbar', that.$dom).insertAdjacentElement('beforeend', $tabbar);// render tabboxlet $tabbox = $.render(tplTabbox, {id: plugin.id});if (!!tabboxHTML) {if (tool.isString(tabboxHTML)) {$tabbox.innerHTML += tabboxHTML;} else if (tool.isFunction(tabboxHTML.appendTo)) {tabboxHTML.appendTo($tabbox);} else if (tool.isElement(tabboxHTML)) {$tabbox.insertAdjacentElement('beforeend', tabboxHTML);}}$.one('.vc-content', that.$dom).insertAdjacentElement('beforeend', $tabbox);});// render top barplugin.trigger('addTopBar', function(btnList) {if (!btnList) {return;}let $topbar = $.one('.vc-topbar', that.$dom);for (let i=0; i<btnList.length; i++) {let item = btnList[i];let $item = $.render(tplTopBarItem, {name: item.name || 'Undefined',className: item.className || '',pluginID: plugin.id});if (item.data) {for (let k in item.data) {$item.dataset[k] = item.data[k];}}if (tool.isFunction(item.onClick)) {$.bind($item, 'click', function(e) {let enable = item.onClick.call($item);if (enable === false) {// do nothing} else {$.removeClass($.all('.vc-topbar-' + plugin.id), 'vc-actived');$.addClass($item, 'vc-actived');}});}$topbar.insertAdjacentElement('beforeend', $item);}});// render tool barplugin.trigger('addTool', function(toolList) {if (!toolList) {return;}let $defaultBtn = $.one('.vc-tool-last', that.$dom);for (let i=0; i<toolList.length; i++) {let item = toolList[i];let $item = $.render(tplToolItem, {name: item.name || 'Undefined',pluginID: plugin.id});if (item.global == true) {$.addClass($item, 'vc-global-tool');}if (tool.isFunction(item.onClick)) {$.bind($item, 'click', function(e) {item.onClick.call($item);});}$defaultBtn.parentNode.insertBefore($item, $defaultBtn);}});// end initplugin.isReady = true;plugin.trigger('ready');}
 /*** show console panel* @public*/show() {if (!this.isInited) {return;}let that = this;// before show console panel,// trigger a transitionstart event to make panel's property 'display' change from 'none' to 'block'let $panel = $.one('.vc-panel', this.$dom);$panel.style.display = 'block';// set 10ms delay to fix confict between display and transitionsetTimeout(function() {$.addClass(that.$dom, 'vc-toggle');that._triggerPluginsEvent('showConsole');let $mask = $.one('.vc-mask', that.$dom);$mask.style.display = 'block';}, 10);}

这是一些关键步骤的代码,其实看代码还是可以看懂的,就不多解释了。
思考:

  const RenderFunction = {// escape HTML to texttext: (str) => {if (typeof str !== 'string' && typeof str !== 'number') { return str; }return String(str).replace(/[<>&" ]/g, (c) => {return { '<': '&lt;', '>': '&gt;', '&': '&amp;', '"': '&quot;', ' ': '&nbsp;' }[c];});},};

在代码中做了XSS攻击预防。
为什么使用slice而不是Array.from?

看看兼容性吧:


是不是slice更加兼容呢。

移动端开发的vconsole插件相关推荐

  1. 移动端项目中vConsole插件的安装和使用

    前端人在做移动端项目的时候,是最痛苦的,我们需要重复的发版,利用超多的console.log("123")来定位bug的位置.直到碰到了vconsole插件,这才让移动端的问题迎刃 ...

  2. 适用于Android端调试必备神器:vConsole插件

    总览 一.代码块 二.效果图 三.拓展 四.其他 使用场景: 1)在我们开发app时,pc端开发时候好好的,到手机端却不起作用: 2)手机端APP不能调试,那该怎么办?于是就需要手机端调试工具: 3) ...

  3. Rosin-移动端页面开发调试Fiddler插件

    前言 随着移动互联网大潮流的到来,移动端H5开发需求也愈加强烈.而移动端页面的调试对开发效率起着重要作用,都有什么调试方法呢? 对于Android设备,可通过设备连接Chrome浏览器进行调试(chr ...

  4. uni-app卖座电影多端开发纪实(五):使用插件

    @关于插件 插件是uni-app极为强大的一个生态扩展功能: 里面有用户写好的各种开源组件.插件.模块.项目模板.甚至完整工程: 高质量Star多的插件导入即用,大大提高了跨端开发的效率! DClou ...

  5. 第13章 Kotlin 集成 SpringBoot 服务端开发(1)

    第13章 Kotlin 集成 SpringBoot 服务端开发 本章介绍Kotlin服务端开发的相关内容.首先,我们简单介绍一下Spring Boot服务端开发框架,快速给出一个 Restful He ...

  6. 移动端开发 rem 单位使用问题

    前言 PC 端页面开发与移动端页面开发: PC 端页面开发需要考虑更多的兼容性问题,ie.谷歌.火狐等浏览器各自内核不同(ie 的天下). 移动端页面开发基本不用考虑这种浏览器间的兼容问题,手机上的浏 ...

  7. 01-移动端开发教程-CSS3新特性(上)

    1. 移动端开发课程概述 移动互联网的兴起,让移动端的开发迅速蹿红.对于前端开发者来说,移动端的开发已经占据了他们大部分工作时间.接下来老马带大家一起学习移动端开发的相关前端开发技术. 这边课程内容包 ...

  8. 手机1像素线粗_关于移动端开发 1px 线的一些理解和解决办法

    (给前端大全加星标,提升前端技能) 作者: 大转转FE/李兴瑞 1px线变粗的原因 在做移动端项目时,常常是根据设计图设置元素节点的大小和样式,但是有时候根据设计图写出来的样式还是不如人意,虽然表面上 ...

  9. auto.js id为参数滑动_【Autojs教程】02Autojs PC端开发调试环境搭建

    [Autojs教程]02-Autojs PC端开发调试环境搭建 写在前面 本篇教程算是保姆级教程了,希望以此能吸引更多感兴趣的同学学习Autojs,也希望大家能因此碰撞出更多的奇思妙想 关注微信公众号 ...

最新文章

  1. 涂抹mysql 完整_涂抹mysql笔记-管理mysql服务
  2. 4.14 | 学习笔记
  3. find the OPP in your life
  4. 画瀑布图_常见的招财风水画之含义
  5. 轨道运营管理专业自荐书_轨道运营管理专业自荐信x
  6. linux exfat分区格式化,技术|如何在 Linux 上将 USB 盘格式化为 exFAT
  7. scala:Scala class的构造方法与继承
  8. 面向对象一些概念简述
  9. 中国抗衰老护肤品市场趋势报告、技术动态创新及市场预测
  10. Go语言:数组练习—冒泡排序
  11. 'gbk' codec can't encode character解决方法
  12. 客户端发现响应内容类型为“text/html”,但应该是“text/xml”
  13. 华为手机连不上adb解决方法
  14. androidhelper python api_python apihelper
  15. MySQL函数大全及用法
  16. 查看U盘是USB2.0还是USB3.0
  17. 分享Canvas画横断面图的vue源码
  18. uview ui与element ui的区别和用法
  19. 给自己定个一年后的终极目标!
  20. Android市场变化令微软很受伤 专利授权收入锐减26%

热门文章

  1. JavaScript DOM操作Select下拉框
  2. 操作系统-第四章存储器管理 计算题:已知逻辑地址求物理地址
  3. 弱电施工流程及规范(一)
  4. leetcode 416. 分割等和子集
  5. HMM Tutorial 隐马尔科夫模型
  6. MacM1,M2芯片安装正版CAD2023,MAC激活正版CAD安装教程
  7. faceswap-GAN
  8. 中华万年历CTO杭建:Java后端技术概览
  9. 酷柚易汛进销存-商品的多单位如何设置?
  10. word(03)中MathType失效问题统一解决方案