面试官:给你一个网站,你如何判断当前网站是否为VUE框架开发的?
我:额。。。项目经过打包构建代码都打乱了无法判断用到的框架
面试官:哦,回去等消息吧
我:
怎样识别一个网站用到了哪些技术? 是作为一个初级前端的最最基本的基础技能。
拿到一个网站第一反应肯定是确认一下这个网站是啥技术创建的,然后分析一下这个网站的,想看看网站用了啥技术,如果是vue,开发者用了多少组件?然后分析当前组件编译后源码,才能有效的学习和进步。
常规的方式是装个浏览器插件判断.但这种方式展示的消息不是很多,细节没有,无法定位到源码,又没成就感。
问:如何识别当前网站是否是vue开发
一般技术框架都会在window下挂上一些私有变量,变量以两个下划线开头 vue 也不例外,当我们在控制台输入 __ 时控制台会自动模糊匹配提示出window下有的值。
看到没? VUE 出来了!!!
明显了, __VUE__
可以用来判断是否是 vue 开发
问:获取网页上的vue实例
vue的页面有个特征会有个全局的app对象 window.app 储存的是 root 节点, 里面隐藏这一些属性
注意: 这个不能百分百获取成功,但只能保 99%, 默认是 window.app 可以改的
可以用 console.dir(window.app) 查看这个
里面的 __vue_app__
就是实例了
看到没 window.app.__vue_app__
这里面包含了当前网页用到的vue版本和vue上下文
注意: 有些网站没有实例比如 https://cn.vuejs.org/
问:用了多少组件分别是哪些?
如何判断用了多少组件? 首先想到的方案是获取到 root 节点然后向下遍历
如何获取 root 节点呢?当我们运行 console.dir(window.app)
后有两个下划线开头的变量
其中一个叫 vnode 很明显了,就是 root 节点
我们获取到的是 VNode 与组件不一样,VNode节点包含组件 component
获取子组件需要到里面去获取
层关系是 VNode=> component
=> subTree(下一个VNode)
如果 VNode 下面有有时会出现 children
字段 值是个数组包含下一层的 VNode,如果不是数组而是各个对象则改为读取 component
递归一下就能获取到所有组件了
问:开发环境下如何获取组件与源码关系
注意: 只在开发环境下有效
看下图
VNode 里 type 中有个 __file 字段保存的是源码位置 获取即可
完整代码
(function getAllFilePath (){
const filePath = {}
const cmpList = {}
const noNameCmp = []
let num = 0
function cmpCallback(cmp){
num += 0
console.log('cmpCallback:',cmp)
const { subTree, type, component, children } = cmp
if(type){
// 有name的组件
if(type.name){
if(!cmpList[type.name]){
cmpList[type.name] = []
}
cmpList[type.name].push(cmp)
}
// 无name的组件
if(type.render && !type.name){
noNameCmp.push(cmp)
}
// 开发模式下,获取组件对应的源码文件位置
if(type.__file) {
const obj = {
file: type.__file,
hmrId: type.__hmrId,
scopeId: type.__scopeId,
VNode: cmp
}
// hmrId 应该会有的吧,防止没有加个默认值
const key = obj.hmrId || `noHmrId_${num}`
if(!filePath[key]){
filePath[key] = []
}
filePath[key].push(obj)
};
};
if(children && Array.isArray(children)){
children.forEach(o=>{
cmpCallback(o)
})
}
const newCmp = component;
if(newCmp){
cmpCallback(newCmp)
return
}
// 文本组件没有 subTree 值
subTree && cmpCallback(subTree)
}
// 判断三方是vue页面
if(!window.__VUE__){
throw new Error('当前页面非Vue开发')
}
cmpCallback(app._vnode)
console.log('当前页面有name的组件有:', cmpList);
console.log('当前页面无name的组件有:', noNameCmp);
console.log('当前页面开发环境下组件与源码文件对应关系:', filePath);
return {
filePath,
cmpList
}
})()
直接复制代码到控制台运行即可,效果如下:
总结:
-
判断有元素 id为 app (成功率:30%,react也可能是app)
-
判断元素属性是否有 data-v-xxx 这种格式 (成功率:80%)
-
判断window.__VUE__ === true (成功率:100%)
-
打印 console.dir(window.app) (成功率:100%,可获得vue版本)