突發奇想
這幾天整理了一下vue的幾種使用方式,對比之後發現有很多相似之處,那麼是不是可以混合使用呢?比如這樣:
- vue的全家桶和UI庫,採用傳統的方式加載(CND、script)。
- 自己寫的js代碼,採用ES6的 import 方式加載。
- 目錄結構採用vuecli建立的項目的目錄結構。
- 入口頁面用vite項目的 index.html。
- 不用babel做轉義(因爲還不會用)。
- 不用webpack(因爲總是報錯,頭痛...)。
這種結合會怎麼樣?我們來看看具體情況。
心急的可以先看看在線演示:https://naturefwvue.github.io/nf-vue-cnd/cnd/project/
項目結構
目錄結構完全按照cli(腳手架)建立的項目的文件夾來設定,只是把.vue文件改成了.js文件。
如圖:
好吧,這裏用src不太準確,因爲這些都是可以直接在瀏覽器裏面運行的代碼。
文件介紹
沒有.vue文件,而是用.js文件取代,因爲原生js不支持.vue文件,看官網說明,似乎需要Babel + webpack才能支持,而這兩個我又都不會。所以暫時不用.vue文件了。
入口頁面 index.html
這個index.html是從vite裏面拷貝出來的,用vite建立項目的時候,還以爲不需要webpack了呢,後來發現自己太天真了,不過這個頁面倒是可以拿來用用。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="icon" href="public/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>一種怪異的方式</title>
<script src="https://unpkg.com/[email protected]/dist/vue.global.js"></script>
<script src="https://unpkg.com/[email protected]/dist/vue-router.global.js"></script>
<script src="https://unpkg.com/[email protected]/dist/vuex.global.js"></script>
<link rel="stylesheet" href="https://unpkg.com/[email protected]/lib/theme-chalk/index.css">
<script src="https://unpkg.com/[email protected]/lib/index.full.js"></script>
</head>
<body>
<div>
這是一個嘗試...
</div>
<div id="app">
<div id="nav">
<p>
<router-link :to="{name:'Home'}">首頁</router-link>
<router-link :to="{name:'state'}">查看狀態管理</router-link>
<router-link :to="{name:'component'}">查看組件加載</router-link>
</p>
<router-view></router-view>
</div>
<hr>
vuex狀態演示<br>
$store - count:{{$store.state.count}}<br>
<el-button type="primary" @click="setCount">vuex的 計數</el-button><br>
<hr>
<script type="module" src="src/main.js?v=9"></script>
</body>
</html>
-
全家桶
這個用傳統的script來引入,沒嘗試import的方式。 -
路由導航
正常設置就可以。 -
import 方式引用 js代碼
使用下面的方式。
<script type="module" src="src/main.js?v=2"></script>
type 要寫 "module",否則會報錯。
後面加v=2,目的是爲了可以更新緩存。
main.js
import store from './store/index.js?v=6'
import router from './router/index.js?v=8'
import App from './app.js?v=6'
// 創建vue3的實例
const app = Vue.createApp(App)
.use(store) // 掛載vuex
.use(router) // 掛載路由
.use(ElementPlus) // 加載ElementPlus
.mount('#app') // 掛載Vue的app實例
這個看着是不是很眼熟,和 vuecli 建立的項目基本沒啥區別,您沒看錯,確實可以這麼寫。
至於爲啥要加個 v=8 ?還不是因爲緩存不更新的問題嘛。只是import只支持常量,不支持變量,想把版本號做個參數,都做不了。
App.js
const App = {
setup() { // 傳說中的setup
const store = Vuex.useStore()
// 狀態的控制事件
const setCount = () =>{
store.commit('setCount')
}
return { // 返回給模板,否則模板訪問不到。
setCount
}
}
}
export default App
- template
沒有設置模板的話,div內容會被保留,否則會被覆蓋。
簡單的狀態的演示,其他的各種方法也都是可以用,不寫那麼多了。
離模板有點遠,所以寫的時候容易蒙,所以要把功能分散到其他頁面(組件)裏面,這裏主要是一個入口功能。
home
const testManage = () => {
const hello = Vue.ref('你好,世界')
const clickMe = () => {
hello.value = '好的,收到' + new Date().valueOf()
}
return {
hello,
clickMe
}
}
// vue3的對象
const home = {
template: `
<h2>這是home</h2>
<div>
我是{{value.name}}。<br>
老規矩:{{hello}}<br>
<input type="button" value="快點我" @click="clickMe"/><br><br>
本項目採用“混合”模式開發,<br>
vue全家桶和UI庫用script標籤加載。<br>
代碼用import方式加載。<br>
目錄結構參考了cli建立的項目。<br>
支持組件、路由、狀態管理等功能。<br>
狀態計數:{{$store.state.count}}
</div>
`,
setup() {
// 使用外面的定義,分解setup內部的代碼
const { hello, clickMe } = testManage()
const value = Vue.reactive({
name: 'jyk'
})
return {
value,
hello,
clickMe
}
}
}
export default home
這麼寫模板,真的很麻煩,編輯器一點忙都不給幫,累死寶寶了。
這裏區別就有點大了,首先模板只能用 template 的方式來寫,
另外不能直接寫css,如果還是想寫的話,目前想到的方法只能用vue的那種了。
加載組件的方法
// 引入組件
import test from '../component/test.js?v=7'
const demo = {
template: `
<h2>這是組件演示</h2>
<test str="傳入的參數"></test>
`,
components: {
test
},
setup() {
return {
}
}
}
export default demo
還是可以用import的方式加載組件,只是不能直接加.vue的文件,而是要變成.js的文件。
組件
const test = {
template: `
這是 組件測試<br>
參數:{{str1}}<br>
`,
model: {
prop: ['str']
},
props: {
str: String
},
setup(props) {
// 在setup裏面獲取參數值
const str1 = Vue.ref(props.str)
return {
str1
}
}
}
export default test
其實吧,vue裏面都是組件,只是,其實沒啥本質區別,只有使用方式的不同。這裏只是寫了一下屬性的獲取和顯示。另外就是爲了讓另一個組件來加載。
路由
// import Home from '../views/home.js?v=2'
const routes = [
{
path: '/',
name: 'Home',
component: () => import('../views/home.js?v=8')
},
{
path: '/state',
name: 'state',
component: () => import('../views/state.js?v=8')
},
{
path: '/component',
name: 'component',
component: () => import('../views/component.js?v=8')
}
]
const router = VueRouter.createRouter({
history: VueRouter.createWebHistory(),
routes
})
export default router
這個代碼也是很眼熟的,代碼基本一樣,加上"VueRouter." 就行。
路由可以加載組件,也可以傳遞參數給組件,細節就不寫了。以後可能會詳細介紹。
異步加載:
現在可以體驗到異步加載的感覺了。
一開始路由對應的組件並不會被下載,而是在第一次點導航的時候纔會開始下載(按F12看的很清楚)。
所以第一次點導航的時候會有一點點卡的感覺,當然這和網站的速度有關。
當然再次點導航的時候,就不會重複下載了。
狀態管理
export default Vuex.createStore({
state: {
count: 0,
myObject: {
time: '現在的時間'
}
},
getters: {
getCount: (state) => {
return state.count
},
getMyObject: (state) => {
return Vue.readonly(state.myObject)
},
getTime: (state) => {
return state.myObject.time
}
},
mutations: {
setCount(state) {
state.count++
},
setTime(state) {
state.myObject.time = '現在時間:' + new Date()
}
},
actions: {
},
modules: {
}
})
還是一樣,區別就在於加載方式。
這裏只是一個最簡單的演示,以後會詳細介紹。
優缺點
基本功能都實現了,我們來分析一下。
缺點
先說缺點吧。
-
組件的模板部分編寫很麻煩,因爲就是一個大字符串,各種輔助功能完全用不上,全憑經驗。
-
沒有開發環境,需要自己配置個web服務網站。
-
代碼改完了,需要按F5刷新才能更新,而且還有個緩存的問題,關掉緩存吧,每次刷新都要花好多時間加載;如果打開的話,又要想辦法更新。
-
沒有按需加載的功能,vue的全家桶、UI庫,不管用多少功能,統統都要下載。
-
js代碼沒有做處理,各種空格、換行符統統沒有去掉,佔用空間大,不保密,代碼可以隨便看。
-
擴展性未知,其他的第三方是否支持也都不清楚。
-
其他各種缺點。
優點
-
簡單粗暴,不用管那麼多,可以直接開魯代碼。
-
很方便做在線演示。(其實主要是爲了這個目的才折騰的)
-
因爲沒有打包這個步驟,所以可以部分更新代碼。
好像也沒啥優點了。
和vite的區別
用vite建立了一個項目,簡單的嘗試了一下,雖然用 也是用 import 加載,但是還是需要babel和webpack,當然這也是必須的,否則.vue怎麼處理?這是vue的一大特色,不能扔掉。
小結
生命在於不斷的折騰。也許這種折騰根本就沒啥意義。
以前用工程化的方式寫代碼,總是非常坎坷,因爲各種報錯。後來熟悉了,不會報錯了(或者是知道要如何處理),但是感覺對vue的瞭解還是停留在表面,稍微深入一點就不知道了。
於是去啃ES6,嘗試cnd的方式,現在感覺對vue的瞭解更深入了一點點。
不斷學習,不斷折騰,不斷進步嘛。
在線演示
https://naturefwvue.github.io/nf-vue-cnd/cnd/project/
源碼
https://github.com/naturefwvue/nf-vue-cnd/tree/main/cnd/project