您当前的位置: 首页 > 学无止境 > JS经典实例 网站首页JS经典实例
mixin插件、history及骨架屏原理-mixin插件
发布时间:2020-05-21 16:37:59编辑:雪饮阅读()
安装mixin
为了不和之前的项目影响,就单独初始化一个
命令如:vue init webpack-simple 01_mixin
C:\Users\xy>vue init webpack-simple 01_mixin
Command vue init requires a global addon to be installed.
Please run npm install -g @vue/cli-init and try again.
C:\Users\xy>npm install -g @vue/cli-init
npm WARN deprecated vue-cli@2.9.6: This package has been deprecated in favour of @vue/cli
npm WARN deprecated coffee-script@1.12.7: CoffeeScript on NPM has moved to "coffeescript" (no hyphen)
+ @vue/cli-init@4.3.1
added 253 packages from 207 contributors in 14.943s
C:\Users\xy>vue init webpack-simple 01_mixin
? Project name 01_mixin
? Project description A Vue.js project
? Author
? License MIT
? Use sass? No
vue-cli · Generated "01_mixin".
To get started:
cd 01_mixin
npm install
npm run dev
C:\Users\xy>
然后同样的进入项目目录运行npm install和npm run dev
Mixin应用-多个组件调用同一逻辑(封装业务)
在app.vue同级目录建立my_mixin.js如
export default {
created() {
setTimeout(()=>{
console.log(`${this.$options.name}请求发出去了`);
},1000)
}
}
这里的create就是多个组件共同的业务
然后app.vue中挂载son.vue并实现调用该封装(那个组件要用,那个组件就调用)
<template>
<div id="app">
我是父组件
<son/>
</div>
</template>
<script>
import Son from "./son";
import mixin from "./my_mixin";
export default {
mixins:[mixin],
name: 'app',
components: {Son},
data () {
return {
msg: 'Welcome to Your Vue.js App'
}
}
}
</script>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
h1, h2 {
font-weight: normal;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>
那么同样的道理,son组件也要调用该逻辑,则son组件
<template>
<div>我是子组件</div>
</template>
<script>
import mixin from "./my_mixin";
export default {
mixins:[mixin],
name: "son"
}
</script>
<style scoped>
</style>
Mixin精炼
上面的代码虽然实现了各个组件共同调用的逻辑代码的封装,但是显得不那么精炼,每个要使用的组件中都要多加两行代码。
首先在main.js中统一导入
import Vue from 'vue'
import App from './App.vue'
import my_mixin from "./my_mixin";
Vue.mixin(my_mixin);
new Vue({
el: '#app',
render: h => h(App)
})
然后app组件就可以少两行
<template>
<div id="app">
我是父组件
<son/>
</div>
</template>
<script>
import Son from "./son";
export default {
name: 'app',
components: {Son},
data () {
return {
msg: 'Welcome to Your Vue.js App'
}
}
}
</script>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
h1, h2 {
font-weight: normal;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>
那么son组件也是相同的
<template>
<div>我是子组件</div>
</template>
<script>
export default {
name: "son"
}
</script>
<style scoped>
</style>
结果如
指定组件使用mixin
一个需求:
1、 指定只能某几个组件使用,上面的虽然实现了组件功能的封装,但是其它新增的组件没有使用到该封装功能也会被自动调用。
2、 该公共封装的功能一次只能被任何一个组件调用,调用过后其它组件即便是属于“某几个组件”也不能调用。
为了实现该需求,同样为了不影响上面功能,这里还是重新初始化一个项目
这里用vue-cli3.x来创建
命令如
vue create 02_plugin_mixin_config
如果之前有用过vue ui创建过项目,则这里可能有各种预设方案,我们这里就直接选择自定义吧
Vue CLI v3.6.1
┌───────────────────────────┐
│ Update available: 4.3.1 │
└───────────────────────────┘
? Please pick a preset:
vuex-test (vue-router, vuex, babel)
test-vuex (vue-router, vuex, babel, typescript)
test2 (vuex, typescript)
test3 (vue-router, vuex, babel, typescript)
test4 (vue-router, vuex, babel)
default (babel, eslint)
> Manually select features
自定义我们就先选择这三个,Eslint也不要
Vue CLI v3.6.1
┌───────────────────────────┐
│ Update available: 4.3.1 │
└───────────────────────────┘
? Please pick a preset: Manually select features
? Check the features needed for your project:
(*) Babel
( ) TypeScript
( ) Progressive Web App (PWA) Support
(*) Router
>(*) Vuex
( ) CSS Pre-processors
( ) Linter / Formatter
( ) Unit Testing
( ) E2E Testing
History模式我们暂时也不要
Vue CLI v3.6.1
┌───────────────────────────┐
│ Update available: 4.3.1 │
└───────────────────────────┘
? Please pick a preset: Manually select features
? Check the features needed for your project: Babel, Router, Vuex, Linter
? Use history mode for router? (Requires proper server setup for index fallback in production) (Y/n) n
最后的预设我们也暂时不要
Vue CLI v3.6.1
┌───────────────────────────┐
│ Update available: 4.3.1 │
└───────────────────────────┘
? Please pick a preset: Manually select features
? Check the features needed for your project: Babel, Router, Vuex
? Use history mode for router? (Requires proper server setup for index fallback in production) No
? Where do you prefer placing config for Babel, PostCSS, ESLint, etc.? In dedicated config files
? Save this as a preset for future projects? (y/N) n
然后编译完成后cd到项目目录npm run serve即可启动项目
项目配置完成后基于上面的需求开始来实现
首先我们这里用vuex来实现数据读写部分,则store/index.js如
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
num:9999
},
mutations: {
add(state){
state.num++;
}
},
actions: {
//模拟发起异步请求
addByAct({state,commit}){
if(state.num!==10000){
setTimeout(function(){
commit('add');
},0)
}
}
},
getters:{
getNum(state){
return state.num;
},
},
modules: {
}
})
然后在main.js同目录创建myPlugin.js做为对项目中所有组件进行指定组件使用封装功能的插件
let myOptions;
function myPlugin(options){
myOptions=options;
return myPlugin;
}
//该对象具备install函数
myPlugin.install=function(Vue){
//mixin
Vue.mixin({
created(){
console.log("mixin created ready");
//遍历所有允许调用封装的addByAct方法的组件列表
myOptions.forEach(opt=>{
//判断当前的组件名
if(this.$options.name===opt){
console.log("组件"+this.$options.name+"操作了add");
//根据vuex去调用,改变数据
this.$store.dispatch('addByAct');
}
})
}
})
}
export default myPlugin;
那么接下来就在main.js中引用该插件并传递所允许使用封装的addByAct方法的组件列表,该项目初始化下来默认就有home和about组件,所以就将这两个设为允许使用封装的addByAct组件列表中的成员。
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
Vue.config.productionTip = false
//配置插件
import MyPlugin from './myPlugin.js'
Vue.use(MyPlugin(['About','Home']));
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
这套方案既然是基于组件名来区分的,那么我们自然要为每个使用的组件保证有组件名并且为了便于查看addByAct一次只能被任何一个组件调用,调用过后其它组件即便是属于“某几个组件”也不能调用的效果则上面的home和about组件中都要调用下getters中的getNum以及给这两个组件各自设置组件名,则有About.vue
<template>
<div class="about">
{{$store.getters.getNum}}
</div>
</template>
<script>
export default {
name: 'About'
}
</script>
则有Home.vue
<template>
<div class="home">
{{$store.getters.getNum}}
</div>
</template>
<script>
// @ is an alias to /src
import HelloWorld from '@/components/HelloWorld.vue'
export default {
name: 'Home',
components: {
HelloWorld
}
}
</script>
则最后无论操作进入home组件或者about组件,总值只加到10000就都不会再次重复加了,并且都是用的公共封装的addByAct
关键字词:mixin,vue