Vue3(四)從jQuery 轉到 Vue工程化 的捷徑


不會 webpack 還想學 vue 工程化開發 的福音

熟悉jQuery開發的,學習vue的簡單使用是沒用啥問題的,但是學習vue的工程化開發方式,往往會遇到各種問題,比如:

webpack、node、npm、cnpm、yarn、腳手架、開發環境、測試環境、生產環境、各種安裝、各種創建。
好在 vue3 不容易報錯了,想當初 vue2.x 的時候各種報錯,看到錯誤就只能干瞪眼,這都是啥?好像是webpack的報錯。
當初學 vue2 就卡在了建立項目上,各種嘗試居然一個項目都沒跑起來。

如果能像jQuery那樣,直接開魯那多好呀!

各種陰差陽錯+機緣巧合的情況下,弄出來了這種在 CND 模式下仿工程化開發的方式。一開始只是想方便我做在線演示,后來各種完善,發現還是應該有點搞頭了。再加上大神在弄vite,似乎也是對webpack比較頭疼。。。

好了不墨跡了,開始說我的做法。

vue全家桶和UI庫的加載方式

這個很傳統了,官方也支持。

  <script src="https://unpkg.com/vue@3.0.5/dist/vue.global.js"></script>
  <script src="https://unpkg.com/vue-router@4.0.3/dist/vue-router.global.js"></script>
  <script src="https://unpkg.com/vuex@4.0.0-rc.2/dist/vuex.global.js"></script>
  <link href="https://unpkg.com/element-plus@1.0.2-beta.30/lib/theme-chalk/index.css" rel="stylesheet">
  <script src="https://unpkg.com/element-plus@1.0.2-beta.30/lib/index.full.js"></script>
  <script src="https://unpkg.com/axios/dist/axios.min.js"></script>

瀏覽器會對js文件做緩存,第一次有點慢,后緩存后就快了。
001下載js.png

某網站有時候會卡一下,不卡的話還是很快的。

js代碼的加載方式

<script type="module" src="src/main.js?v=4"></script>

聽說vite也是這么加載的。好吧就是從vite建立的項目里copy來的。
要加上 type="module" 否則加載不了。

文件夾結構和代碼編寫風格

文件夾當然是把工程化的拿過來之間用了,挺簡潔明了的。
因為瀏覽器也支持 import 的方式加載js,那么也就是說,CDN方式下也可以用import加載。那么js代碼方面也不會有太大的差別。
我們來對比一下:
002文件夾對比.png

左面是CND的項目,右面是工程化的項目。

  • 文件夾結構完全一致,
  • js文件都能對應上
  • vue文件拆分成 html + js 兩個文件(app.vue除外)

main.js

/*
import store from './store/index.js?v=1'
import router from './router/index.js?v=1'
import App from './app.js?v=1'

// 創建vue3的實例
const app = Vue.createApp(App)
  .use(store) 
  .use(router)
  .use(ElementPlus)
  .mount('#app')
*/

const ver = window.__ver || ''
Promise.all([
  import('./store/index.js' + ver),
  import('./router/index.js' + ver),
  import('./app.js' + ver),
]).then((res) => {
  // 創建vue3的實例
  const app = Vue.createApp(res[2].default)
    .use(res[0].default) // 掛載vuex
    .use(res[1].default) // 掛載路由
    .use(ElementPlus) // 加載ElementPlus
    .mount('#app') // 掛載Vue的app實例
})

注釋掉的代碼,和工程化里的代碼是一致的,只是這種方式只支持常量,所以想把版本加在url地址上面就比較麻煩。
所以改為了這種異步的方式,這樣可以把版本號給拼接上去。這樣更新瀏覽器的js緩存就方便多了。

app.js

export default {
  name: 'app',
  setup() {
    do something...
  
    return {
    }
  }
}

工程化項目里面是App.vue,對應的是網頁里 id=“app” 的div。
這里改成純js文件的形式,因為模板就是index.html的div。
好吧,其實是main.js里面的加載方式不知道要怎么改。。。

router


const routes = [
  {
    path: '/',
    name: 'Home',
    component: () => myImport('views/home')
  },
  {
    path: '/About',
    name: 'About',
    component: () => myImport('views/About')
  },
  {
    path: '/component',
    name: 'component',
    component: () => myImport('views/component')
  },
  {
    path: '/store',
    name: 'store',
    component: () => myImport('views/store')
  }
]

const router = VueRouter.createRouter({
  history: VueRouter.createWebHistory(),
  routes
})

export default router
  • 動態路由
    這里采用動態路由的方式,另外換成了我自己封裝的函數,可以加載html和js文件,然后變成動態組件的方式,這樣組件就可以被路由加載了。

  • 路徑設置問題
    本來想把html和js文件放在一個文件夾里面,就可以用同一個url加載了,結果和我想的不一樣。
    由於加載 html 和加載 js 的路徑規則不太一樣,再加上路由導航的原因,
    所以只好用 src 作為分隔標識,統一從src開始計算路徑。

myImport

// 直接放在Window里面好了。。。
window.myImport = (url) => {
  return new Promise((resolve, reject) => {
    const ver = window.__ver || ''
    const baseUrl = window.__basrUrl || '/src/'
    // 先加載js
    import(baseUrl + url + '.js' + ver).then((resjs) => {
      const js = resjs.default
      if (js.template === '') {
        // 如果模板是空的,表示需要加載html作為模板
        axios.get(baseUrl + url + '.html' + ver).then((resHTML) => {
          js.template = resHTML.data
          resolve(js)
        })
      } else {
        // 否則直接使用js注冊組件
        resolve(js)
      }
    })
  })
}

一開始還想做個插件掛到vue上面,后來試了半天沒成功。
然后覺得自己挺傻的,cnd環境,一個靜態函數,直接掛在Window上面不就行了嗎。

  • 加載 js 和 html
    先用 import 異步加載 js,目的是便於拼接url,然后判斷是否有template。
    如果有的話,就不加載html了。
    如果沒有的話,在用axios加載html,然后設置給template,這樣就變成了一個標准的js組件。

  • 是否會重復加載?
    組件自帶緩存機制,第一次會加載,以后就不會重復加載了。

store

import { Set_Count } from './mutation-types.js'

export default Vuex.createStore({
  state: {
    count: 0,
    myObject: {
      time: '現在的時間:'
    },
    myArray: [1,2,2,3,4]
  },
  getters: {
    getAddCount: (state) => {
      return state.count + 1
    } 
  },
  mutations: {
    // 計數器
    setCount(state, num = 1) {
      state.count += num
    },
    [Set_Count](state, num = 1) {
      state.count += num
    }
  },
  actions: {
  },
  modules: {
  }
})

基本上沒啥區別。

如何方便的寫模板

直接看圖,更清晰一些。
003組件.png
一邊寫js代碼,另一邊寫模板。這樣也是很方便的。

一開始想在瀏覽器里面直接加載vue文件,然后處理成js組件。
想了半天,理論上應該可以,但是我這水平估計夠嗆,所以采用了這種折中的方式。

組件里面加載組件

004組件加組件.png

  • defineAsyncComponent
    這個是Vue提供的異步組件,如果在工程化里面,可以直接加載vue文件。
    我在cnd里面試了一下,沒成功。所以只好用純js組件的方式。

動態路由不需要套這個,但是異步組件就要套上,否則沒有效果。

搭一個梯子

這樣做項目和 jQuery 的風格挺像的,文件copy過來,建立個網站就可以開魯了。

同時代碼編寫方式又采用工程化的方式,熟悉之后可以方便的切換的工程化的開發方式。

就好像在 jQuery 與 vue 的工程化直接搭了一個梯子,應該大概可以方便我們翻過去吧。

便於調試

  • 設置斷點看狀態。
    005斷點.png

  • 看成員
    006看看都有啥.png

  • 進到內部了,好吧其實我都看不懂。。。
    007內部.png

js文件的緩存問題

緩存是個好東東,避免我們重復加載js文件,加快頁面顯示速度,但是如果我們的js改了,瀏覽器卻還是在用緩存怎么辦?

我們可以設置一個版本號,加載文件后面就可以。當更新的時候,改一下版本號,就可以重新加載了。

源碼

https://github.com/naturefwvue/nf-vue-cnd/tree/main/cnd/project-template

在線演示

https://naturefwvue.github.io/nf-vue-cnd/cnd/project-template/
一開始可能會有的卡,第一次點導航會加載文件,所以會慢一點,以后就好了。好像應該加一個加載中的狀態。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM