中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何獲取vue單文件自身源碼路徑

發布時間:2020-09-05 11:24:10 來源:腳本之家 閱讀:281 作者:CNine 欄目:web開發

這個問題要從一個想法說起。

D2Admin 是一個開源的,前端中后臺集成方案,原先是基于 vue-cli2,大概是向 vue-cli3 過渡時,
作者老李,想在頁面右下角加個 Toggle 點擊,跳到當前頁面源碼對應的 github 頁面。

確實很實用的功能,D2Admin 的 Demo 頁面太多了,想看某個頁面的源碼,對于不熟悉項目目錄結構的新手很不友好。
這些頁面統一為 .vue 組件,那么轉換一下:如何獲取 vue 單文件自身源碼路徑?

目前經歷了三個方案,最終目標是把自身路徑賦值到 this.$options.__source 上。目前方案 3 是最新的。

方案 1 :node + __filename

直接使用 node 中的 __filename 變量:

<template>
 <h2>{{ $options.__source }}</h2>
</template>

<script>
export default {
 mounted() {
  this.$options.__source = __filename
 }
}
</script>

因為 webpack 編譯時,會把源碼文件在內部轉為 node 模塊,.vue 文件中的 script 內容也被轉換了,
其中的 __filename 在編譯時被運行,直接得到當前文件自身路徑。

使用這個變量還需要在 webpack 配置中啟用 node.__filename:

/* vue.config.js */
module.exports = {
 // ...
 chainWebpack: config => {
  // ...
  config.node
   .set('__dirname', true) // 同理
   .set('__filename', true)
 }
};

缺點

  1. 要在每個組件里手動賦值,還不能用 mixin
  2. __filename 得到的路徑在部分 .vue 文件下并不準確,路徑可能還會帶附帶 querystring

一開始,堅強的老李用這個方式,給上百個組件手動掛上了路徑,但總比手動寫死每個路徑要好

方案 2 :vue-loader + exposeFilename

在 loader 層面,其實 vue-loader 提供了一個 exposeFilename 選項,只要啟用,
就會給每個 .vue 組件帶上 this.$options.__file,上面有準確的路徑。
這樣只需要改 loader 配置:

/* vue.config.js */
module.exports = {
 // ...
 chainWebpack: config => {
  // ...
  config.module
   .rule('vue')
   .use('vue-loader')
    .loader('vue-loader')
    .tap(options => {
     options.exposeFilename = true
     return options
    })
 }
};

開發環境默認是開啟 exposeFilename 的。

此時組件內應該直接取 this.$options.__file,內容大致為 src/foo/bar.vue。

缺點

為了安全,vue-loader 在生產環境將 __file 賦值為文件名,非路徑名,詳見文檔

后來得知這個方法,老李就第一時間改代碼,刪了方案 1 中的所有附加代碼,結果發現生產環境結果不一致,翻車了orz

方案 3 :loader + Custom Block

既然方案 2 不讓在生產環境用,那就自己寫 loader 去加上這個源碼路徑,這里采用了Custom Block。

這個方法是慢慢調試自定義的 loader 摸索出來的,先在 vue-loader 之前加自定義的 loader A,

去注入 Custom Block 代碼,再在全局加入一個針對該 Custom Block 的 loader B。

這里將方案封裝,在 chainWebpack 中調用即可:

/* vue.config.js */
const VueFilenameInjector = require('./path/to/vue-filename-injector')

module.exports = {
 chainWebpack: config => {
  VueFilenameInjector(config, {
   propName: '__source' // default
  })
 }
}

源碼參考:@d2-projects/d2-advance/tools/vue-filename-injector

.
└── vue-filename-injector
  ├── README.md
  ├── index.js
  └── src
    ├── index.js
    └── lib
      ├── config.js
      ├── injector.js
      └── loader.js

vue-filename-injector/index.js:

const { blockName } = require('./lib/config.js')

// for chainWebpack
module.exports = function(config, options) {
 // 注入
 config.module
  .rule('vue')
  .use('vue-filename-injector')
  .loader(require.resolve('./lib/injector.js'))
  .options(options)
  .after('vue-loader') // 不知為何 .before() 不是預期的結果,這里就繞了一下
  .end()
 // 解析
 config.module
  .rule('')
  .resourceQuery(new RegExp(`blockType=${blockName}`))
  .use('vue-filename-injector-loader')
  .loader(require.resolve('./lib/loader.js'))
  .end()
}

vue-filename-injector/lib/config.js:

const defaultPropName = '__source'
const blockName = 'vue-filename-injector'

module.exports = {
 defaultPropName,
 blockName
}

vue-filename-injector/lib/injector.js,源碼部分來自 vue-loader:

const path = require('path')
const loaderUtils = require('loader-utils')

const { blockName, defaultPropName } = require('./config.js')

module.exports = function (content /*, map, meta */) {
 const loaderContext = this

 const {
  rootContext,
  resourcePath
 } = loaderContext

 const context = rootContext || process.cwd()
 const options = loaderUtils.getOptions(loaderContext) || {}
 const rawShortFilePath = path
  .relative(context, resourcePath)
  .replace(/^(\.\.[\/\\])+/, '')

 const propName = options.propName || defaultPropName

 content += `
<${blockName}>
export default function (Component) {
 Component.options.${propName} = ${JSON.stringify(rawShortFilePath.replace(/\\/g, '/'))}
}
</${blockName}>
`
 return content
}

vue-filename-injector/lib/loader.js:

module.exports = function(source, map) {
 this.callback(null, source, map)
}

相關倉庫

可進入預覽頁面查看效果,在右下角有 Toggle

github.com/d2-projects… (可能還在翻車中)

github.com/d2-projects…

總結

目前看來,用自定義 loader 去注入代碼是最便捷的方案,不用在每個組件中手寫重復的代碼。

由于 vue-cli3 采用 chainWebpack,加上個人對 webpack 的理解更是不深,暫時采用方案 3。

以上所述是小編給大家介紹的如何獲取vue單文件自身源碼路徑詳解整合,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對億速云網站的支持!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

宜昌市| 四子王旗| 泾川县| 岢岚县| 柞水县| 平果县| 五莲县| 辽阳市| 原阳县| 岫岩| 杨浦区| 南投市| 乐平市| 略阳县| 多伦县| 广丰县| 华蓥市| 陇西县| 三河市| 黄浦区| 太仆寺旗| 八宿县| 华亭县| 比如县| 永平县| 手游| 个旧市| 和平县| 东平县| 饶阳县| 筠连县| 上栗县| 格尔木市| 澄迈县| 永靖县| 莱西市| 平山县| 新宁县| 萍乡市| 长寿区| 忻州市|