加載 vue 遠(yuǎn)程代碼的組件實(shí)例詳解
在我們的 vue 項(xiàng)目中(特別是后臺(tái)系統(tǒng)),總會(huì)出現(xiàn)一些需要多業(yè)務(wù)線共同開發(fā)同一個(gè)項(xiàng)目的場(chǎng)景,如果各業(yè)務(wù)團(tuán)隊(duì)向框架中提供一些私有的展示組件,但是這些組件并不能和框架一起打包,因?yàn)榭蚣懿荒芤驗(yàn)槟硞€(gè)私有模塊的頻繁變更而重復(fù)構(gòu)建發(fā)布。在這種場(chǎng)景下我們需要一個(gè)加載遠(yuǎn)程異步代碼的組件來完成將這些組件加載到框架中。
vue-cli 作為 Vue 官方推薦的項(xiàng)目構(gòu)建腳手架,它提供了開發(fā)過程中常用的,熱重載,構(gòu)建,調(diào)試,單元測(cè)試,代碼檢測(cè)等功能。我們本次的異步遠(yuǎn)端組件將基于 vue-cli 開發(fā)。
需求分析
- 如何加載遠(yuǎn)端的代碼?
- 如何注冊(cè)加載后的代碼到框架中。
- 父組件如何和遠(yuǎn)端引入的組件通信。
- 遠(yuǎn)端代碼如何復(fù)用框架中已引入的庫。
- 避免因遠(yuǎn)端代碼被類似 v-for 多次調(diào)用導(dǎo)致的不必要請(qǐng)求。
加載遠(yuǎn)端代碼
遠(yuǎn)端代碼應(yīng)該存儲(chǔ)在一個(gè)可訪問的 URL 上,這樣我們通過 Axios 類似的 HTTP client 請(qǐng)求這個(gè)鏈接拿到源碼。
import Axios from 'axios'; export default { name: 'SyncComponent', props: { // 父組件提供請(qǐng)求地址 url: { type: String, default: '' } }, data() { return { resData: '' }; }, async mounted() { if (!this.url) return; const res = await Axios.get(this.url); // 我們?cè)诮M件掛載完成時(shí),請(qǐng)求遠(yuǎn)端代碼并存儲(chǔ)結(jié)果。 this.resData = res.data; } };
以上是基礎(chǔ)代碼 為了方便 一下例子中 我將省略重復(fù)的代碼部分。
注冊(cè)代碼到框架中
這部分有些繁瑣,涉及到多個(gè)問題:
瀏覽器并不支持 .vue 模板 或 ES.next 語法,模塊需要編譯后才可以使用。
處理這部分比較簡單,我們自己定義一個(gè)webpack配置文件來打包這些模板。
// 在 build 目錄下新建 webpack.sync-components.prod.conf.js 文件 const webpack = require('webpack'); const path = require('path'); const utils = require('./utils'); const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin') function resolve(dir) { return path.join(__dirname, '..', dir) } module.exports = { // 此處引入要打包的組件 entry: { componentA: resolve('/src/views/component-a.vue') }, // 輸出到靜態(tài)目錄下 output: { path: resolve('/static/'), filename: '[name].js', }, resolve: { extensions: ['.js', '.vue', '.json'], alias: { 'vue$': 'vue/dist/vue.esm.js', '@': resolve('src'), } }, module: { rules: [ { test: /\.vue$/, loader: 'vue-loader', options: { esModule: false, // ****** vue-loader v13 更新 默認(rèn)值為 true v12及之前版本為 false, 此項(xiàng)配置影響 vue 自身異步組件寫法以及 webpack 打包結(jié)果 loaders: utils.cssLoaders({ sourceMap: true, extract: false // css 不做提取 }), transformToRequire: { video: 'src', source: 'src', img: 'src', image: 'xlink:href' } } }, { test: /\.js$/, loader: 'babel-loader', include: [resolve('src'), resolve('test')] }, { test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, loader: 'url-loader', options: { limit: 10000, name: utils.assetsPath('img/[name].[hash:7].[ext]') } }, { test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/, loader: 'url-loader', options: { limit: 10000, name: utils.assetsPath('media/[name].[hash:7].[ext]') } }, { test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, loader: 'url-loader', options: { limit: 10000, name: utils.assetsPath('fonts/[name].[hash:7].[ext]') } } ] }, plugins: [ new webpack.DefinePlugin({ 'process.env.NODE_ENV': '"production"' }), // 壓縮JS new webpack.optimize.UglifyJsPlugin({ compress: false, sourceMap: true }), // 壓縮CSS 注意不做提取 new OptimizeCSSPlugin({ cssProcessorOptions: { safe: true } }) ] };
至此我們的模塊已經(jīng)被編譯成框架可以識(shí)別的文件。
1.如何將字符串轉(zhuǎn)換成js對(duì)象。
new Function。 async mounted() { if (!this.url) return; const res = await Axios.get(this.url); let Fn = Function; this.mode = new Fn(`return ${res.data}`)(); }
1.轉(zhuǎn)換后的js對(duì)象并不能被vue識(shí)別。
有兩種可能會(huì)導(dǎo)致這個(gè)問題:
// vue-loader v13 esModule 更新 默認(rèn)值為 true, v12及之前版本為 false, 此項(xiàng)配置影響 vue 自身異步組件寫法以及 webpack 打包結(jié)果 { test: /\.vue$/, loader: 'vue-loader', options: { esModule: false ... 以下省略千軍萬碼 } } // UglifyJs 需要取消變量名替換配置,此配置并不會(huì)極大影響壓縮率 new webpack.optimize.UglifyJsPlugin({ compress: false, sourceMap: true })
至此 遠(yuǎn)程組件就被引入到框架中了。
父組件如何和遠(yuǎn)端引入的組件通信
這里有一個(gè)問題,從 view組件 到 遠(yuǎn)程異步加載組件 再到 實(shí)際業(yè)務(wù)組件 通信一共三層,中間層 遠(yuǎn)程異步組件 作為公共組件不可被修改,需要 view組件 直接向 實(shí)際業(yè)務(wù)組件 通信。vuex 和 eventBus 方案都過于繁瑣,這里我們采用 $attrs 和 $listeners(vue v2.4+), 來實(shí)現(xiàn) “fallthrough”(vue組件跨層級(jí)通信)。
// 修改 sync-component.vue 組件 // 新增 v-bind="$attrs" v-on="$listeners" <component :is="mode" v-bind="$attrs" v-on="$listeners"> </component> // inheritAttrs: true export default { name: 'SyncComponent', props: { // 父組件提供請(qǐng)求地址 url: { type: String, default: '' } }, inheritAttrs: true ... 以下省略千軍萬碼 }
遠(yuǎn)端代碼如何復(fù)用框架中已引入的庫
我們不希望看到遠(yuǎn)端組件和框架中存在較大庫或插件的重復(fù)的引入,這部分內(nèi)容尚處在實(shí)踐階段,主要思路是把公共庫掛載到Vue原型鏈上實(shí)現(xiàn)組件公共復(fù)用 Vue.prototype.$xxx。
// 全局添加 axios 對(duì)象 import axios from 'axios'; Vue.prototype.$http = axios;
引入的遠(yuǎn)程組件可以訪問到框架中的公共包了,這時(shí)候還需要配置 webpack 使遠(yuǎn)程組件打包時(shí)不要包含公共包的代碼。
// webpack.sync-components.prod.conf.js 添加 externals: { vue: 'vue', 'element-ui': 'element-ui', axios: 'axios' }
避免因遠(yuǎn)端代碼被類似 v-for 多次調(diào)用導(dǎo)致的不必要請(qǐng)求。
這部分我們直接用一個(gè)全局變量做字典,存儲(chǔ) 以 請(qǐng)求地址:數(shù)據(jù) 為子項(xiàng)的數(shù)組。
async mounted() { if (!this.url) return; // Cache 緩存 根據(jù) url 參數(shù) if (!window.SyncComponentCache) { window.SyncComponentCache = {}; } let res; if (!window.SyncComponentCache[this.url]) { window.SyncComponentCache[this.url] = Axios.get(this.url); res = await window.SyncComponentCache[this.url]; } else { res = await window.SyncComponentCache[this.url]; } let Fn = Function; this.mode = new Fn(`return ${res.data}`)(); console.log(this.mode); }
至此,異步遠(yuǎn)程組件就可以加載并和框架進(jìn)行通信了。
本文中的源碼請(qǐng)?jiān)L問 github 獲取,組件已經(jīng)發(fā)布到NPM 上,可以直接安裝。
總結(jié)
以上所述是小編給大家介紹的加載 vue 遠(yuǎn)程代碼的組件,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
相關(guān)文章
vue 路由懶加載中給 Webpack Chunks 命名的方法
這篇文章主要介紹了在 vue 路由懶加載中給 Webpack Chunks 命名的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-04-04vuex中this.$store.commit和this.$store.dispatch的基本用法實(shí)例
在vue的項(xiàng)目里常常會(huì)遇到父子組件間需要進(jìn)行數(shù)據(jù)傳遞的情況,下面這篇文章主要給大家介紹了關(guān)于vuex中this.$store.commit和this.$store.dispatch的基本用法的相關(guān)資料,需要的朋友可以參考下2023-01-01vue2.0+koa2+mongodb實(shí)現(xiàn)注冊(cè)登錄
這篇文章主要介紹了vue2.0+koa2+mongodb實(shí)現(xiàn)注冊(cè)登錄功能,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2018-04-04簡單實(shí)現(xiàn)Vue的observer和watcher
這篇文章主要教大家如何簡單實(shí)現(xiàn)Vue的observer和watcher,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-12-12Vue入門之?dāng)?shù)量加減運(yùn)算操作示例
這篇文章主要介紹了Vue入門之?dāng)?shù)量加減運(yùn)算操作,結(jié)合實(shí)例形式分析了vue.js基本數(shù)值運(yùn)算相關(guān)操作技巧,需要的朋友可以參考下2018-12-12詳解vuejs中執(zhí)行npm run dev出現(xiàn)頁面cannot GET/問題
這篇文章主要介紹了詳解vuejs中執(zhí)行npm run dev出現(xiàn)頁面cannot GET/問題,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-04-04vue3?+?async-validator實(shí)現(xiàn)表單驗(yàn)證的示例代碼
表單驗(yàn)證可以有效的過濾不合格的數(shù)據(jù),減少服務(wù)器的開銷,并提升用戶的使用體驗(yàn),今天我們使用?vue3?來做一個(gè)表單驗(yàn)證的例子,需要的朋友跟隨小編一起學(xué)習(xí)下吧2022-06-06