一直以来都是CDN引用vue, react, 关于vue3 + vite的CDN引用的教程, 网上看了下没有什么好的示例, 所以有此篇
有朋友就要问了, 官方推荐就是import, 你搞CDN引用是为啥? 爱折腾
爱折腾是一部分, 还有就是既然是公共且常用的包,
1: CDN可以减少项目包体积;
2: 可以提升加在速度
3: 可以被动锁定版本
4: 可以避免到处import, 提升代码美观, 提升构建速度
...等, 好处多多,
目标
实现CDN引用全家桶, 引用element, sass, 路由, 仓储, element组件, 自定义组件
完成以上应该就算完成了本demo
好了话不多说上代码
项目结构
image.png
核心, 也是重中之重就是这个配置项, 全家桶在打包构建时需要外部的取全局的变量 ,而不是node_modules中的
我也是看了一会官方文档, 百度上没啥有价值的资料
否则会报, 且目前百度, 谷歌无有效方案
resolveComponent can only be used in render() or setup().
Invalid VNode type: Symbol(Text) (symbol) at <App>
vite.config.js
import vue from "@vitejs/plugin-vue";
import commonjs from "rollup-plugin-commonjs";
import externalGlobals from "rollup-plugin-external-globals";
// 全局对象
let globals = externalGlobals({
vue: "Vue",
vuex: "Vuex",
vueRouter: "VueRouter",
"element-plus": "element"
})
const plugins = process.env.NODE_ENV === 'production' ? [] : [commonjs(), globals]
export default {
plugins: [
vue(),
...plugins
],
css: {
preprocessorOptions: {
scss: {
charset: false
}
}
},
build: {
target: 'es2015',
assetsDir: './static',
rollupOptions: {
external: ['vue', 'vuex', 'vueRouter' ],
plugins: [
commonjs(),
globals
],
},
},
};
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="./static/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite App</title>
<script src="/static/js/vue.js"></script>
<script src="/static/js/vue-router.js"></script>
<script src="/static/js/vuex.js"></script>
<script src="/static/js/element-plus.js"></script>
<link rel="stylesheet" href="/static/css/element-plus.css">
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>
main.js
import store from './store/index.js'
import router from './router.js'
import App from './app.vue'
import './assets/base.scss'
// 创建vue3的实例
const app = Vue.createApp(App)
.use(store) // 挂载vuex
.use(router) // 挂载路由
.use(ElementPlus) // 加载ElementPlus
.mount('#app') // 挂载Vue的app实例
router.js
const routes = [
{
path: '/',
name: 'Home',
component: () => import('./views/home.vue')
},
{
path: '/state',
name: 'state',
component: () => import('./views/state.vue')
},
{
path: '/component',
name: 'component',
component: () => import('./views/component.vue')
}
]
const router = VueRouter.createRouter({
history: VueRouter.createWebHistory(),
routes
})
export default router
app.vue
<template>
<div>
<img src="https://v3.cn.vuejs.org/logo.png" />
<br />
<div class="nav">
<router-link to="/">路由</router-link>
<router-link to="/component">组件</router-link>
<router-link to="/state">仓储</router-link>
</div>
<router-view class="router-view"></router-view>
<hr />
vuex状态演示<br />
$store - count:{{ $store.state.count }}<br />
<el-button @click="setCount">vuex的 计数</el-button><br />
</div>
</template>
<script>
export default {
name: 'app',
setup() {
const store = Vuex.useStore();
const setCount = () => {
store.commit("setCount");
};
return {
setCount,
};
},
data() {
return {
};
},
methods: {
},
components: {
},
};
</script>
<style lang="scss">
#app {
text-align: center;
color: #2c3e50;
.nav {
a {
margin-left: 20px;
}
}
}
</style>
home.vue
<template>
<div class="home">
<h3>首页</h3>
<el-button @click="$router.push({
path: '/state',
query: {
name: '张三',
foods: ['西红柿炒蛋', '红烧肉']
}
})" class="mg-right-10">去看store</el-button>
</div>
</template>
<script>
export default {
name: 'home',
data() {
return {
};
},
methods: {
},
components: {
},
};
</script>
<style lang="scss">
.home {
}
</style>
state.vue
<template>
<div class="state">
<div class="pad-10">{{$store.getters.getFood}}</div>
<el-button @click="addFood" class="mg-right-10">辣椒炒肉</el-button>
<el-input v-model="other" placeholder="请输入" style="width: 300px" clearable>
<template #append><el-button @click="addOther">加点别的</el-button></template>
</el-input>
<el-button @click="replace" class="mg-left-10">换菜谱</el-button>
<el-button @click="setFood" class="mg-left-10">拿地址栏参数</el-button>
</div>
</template>
<script>
export default {
setup() {
const store = Vuex.useStore();
const query = VueRouter.parseQuery(location.search)
console.log(query)
Object.hasOwnProperty.call(query, 'foods')
// 状态的控制事件
const setFood = () => {
console.log(query)
if (Object.hasOwnProperty.call(query, 'foods')) {
store.commit("setFood", [...query.foods]);
} else {
ElementPlus.ElMessage('拿地址栏没有参数呢')
}
};
return {
setFood
}
},
data() {
return {
count: 0,
other: ''
};
},
created () {
},
methods: {
addFood (e) {
this.$store.commit('addFood', '辣椒炒肉')
},
addOther () {
this.other && this.$store.commit('addFood', this.other)
},
replace () {
this.$store.commit('setFood', ['剁椒鱼头', '农家一碗香'])
}
},
components: {
},
};
</script>
<style lang="scss">
.state {
}
</style>
component.vue
<template>
<div class="component">
<child @countChange="countChange" msg="父传子" />
<br />
<div class="pad-20">子传过来的值:{{ count }}</div>
<el-button @click="$router.push('/')" class="mg-right-10">去首页</el-button>
</div>
</template>
<script>
import child from "../components/child.vue";
export default {
name: 'home',
data() {
return {
count: 0,
};
},
methods: {
countChange(e) {
this.count = e;
},
},
components: {
child
},
};
</script>
<style lang="scss">
.component {
}
</style>
store
export default Vuex.createStore({
state: {
count: 0,
food: []
},
getters: {
getCount: (state) => {
return state.count
},
// 只读
getFood: (state) => {
return Vue.readonly(state.food)
},
},
mutations: {
setCount(state) {
state.count++
},
setFood(state, food) {
state.food = food
},
addFood(state, food){
if (Array.isArray(food)) {
state.food.concat(food)
} else {
state.food.push(food)
}
}
},
actions: {
},
modules: {
}
})
child.vue
export default Vuex.createStore({
state: {
count: 0,
food: []
},
getters: {
getCount: (state) => {
return state.count
},
// 只读
getFood: (state) => {
return Vue.readonly(state.food)
},
},
mutations: {
setCount(state) {
state.count++
},
setFood(state, food) {
state.food = food
},
addFood(state, food){
if (Array.isArray(food)) {
state.food.concat(food)
} else {
state.food.push(food)
}
}
},
actions: {
},
modules: {
}
})
太多不看? 好吧 给你仓库
vue3 + vite + cdn + sass