Vue 原型链"注入", 修改掘金字体颜色

1,703 阅读1分钟

之前看react能去除知乎div, 就想着vue应该也能有类似的玩法, 就试了一下... 讲道理, 这种做法应该是可以拿到更多东西的, 甚至可以获取表达输入, 原理就这样, 懒得继续搞了

效果如下

原理是通过vue暴露给cli工具的实例, 拿到原型链, 然后修改原型链上的方法

实现原理

代码比较简单, 核心检测代码来自vue cli 拿到Vue后, 修改原型链上的方法即可, 主要注意this的指向问题

const all = document.querySelectorAll("*")
let el
for (let i = 0; i < all.length; i++) {
  if (all[i].__vue__) {
    el = all[i]
    break
  }
}
let Vue
if (el) {
  Vue = Object.getPrototypeOf(el.__vue__).constructor
  while (Vue.super) {
    Vue = Vue.super
  }
}

const nuxtDetected = Boolean(window.__NUXT__ || window.$nuxt)

if (nuxtDetected) {
  if (window.$nuxt) {
    Vue = window.$nuxt.$root.constructor
  }
}

const _render = Vue.prototype._render

function r(...args) {
  const self = this
  console.log("r", ...args, self)
  console.log("el", self, self.$el)

  // el的挂载是异步的, 直接获取是不可以的
  // 用nextTick在渲染完毕后设置颜色
  Vue.prototype.$nextTick(() => {
    console.log("el2", self, self.$el)
    if (self.$el && self.$el.style) {
      self.$el.style.color = "red"
    }
  })

  const _createElement = self.createElement
  function c(...args) {
    console.log("c", ...args)
    // 这个函数暂时没有用到...
    return _createElement(...args)
  }
  self.createElement = c
  return _render.call(self, ...args)
}
Vue.prototype._render = r