vue 插件
四种类型
- 添加全局方法或者属性,如: vue-custom-element
- 添加全局资源:指令/过滤器/过渡等,如 vue-touch
- 通过全局 mixin 方法添加一些组件选项,如: vue-router
- 添加 Vue 实例方法,通过把它们添加到 Vue.prototype 上实现。
- 一个库,提供自己的 API,同时提供上面提到的一个或多个功能,如 vue-router
详见:https://cn.vuejs.org/v2/guide/plugins.html
个人练习的是实现类似Toast/Loading的插件,实现方法是上述第四个,即添加 Vue 实例方法,通过把它们添加到 Vue.prototype 上实现
组件和插件的关系
- 组件是需要的地方引入,插件可以全局使用
- 插件可以封装组件,组件可以暴露数据给插件
实现步骤
核心思想 实例化组件,并挂载组件;在vue原型链上添加方法操作上面的vue实例
- 建立一个vue文件,实现一个组件
- 建立一个js文件,封装插件,
- 在全局引入
- 在需要的地方调用
toast.vue1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79<template>
<div class="modal" v-show="isShow">
<div :class="level">
{{text}}
</div>
</div>
</template>
<script>
const levels = ['success','warm', 'info']
export default {
computed:{
level(){
if (levels.indexOf(this.type) != -1){
return this.type
}else{
return ''
}
}
},
data(){
return {
isShow:false
}
},
props:{
type:{
type:String,
default: 'success'
},
duration:{
type: Number,
default: 3000
},
text:{
type:String,
default:'你忘记传入值进来啦'
}
},
methods:{
show(){
this.isShow = true
},
disappear(){
this.isShow = false
}
}
}
</script>
<style scoped>
.modal{
position: fixed;
width: 100%;
height: 100%;
background:rgba(0,0,0,0.5);
left: 0;
top:0;
z-index: 2000;
display: flex;
align-items: center;
justify-content: center;
}
.message{
background-color: #fff;
opacity: 1;
width: 300px;
height: 70px;
}
.warm{
border: 1px solid red;
}
.success{
border: 1px solid green;
}
.info{
border:1px solid blue
}
</style>
config.js1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37import toast from './toast'
const ToastPlugin= {}
ToastPlugin.install = function(Vue, options){
// 实例化组件
const toastComp = Vue.extend(toast)
let toastInstance
const initInstance = function(){
toastInstance = new toastComp()
// 挂载组件
var html = toastInstance.$mount().$el
document.body.appendChild(html)
}
// 在vue原型链上添加方法操作上面的vue实例
Vue.prototype.$toast ={
show:function(options){
if(!toastInstance){
initInstance()
}
Object.assign(toastInstance,options)
toastInstance.show();
setTimeout(()=>{
toastInstance.disappear()
},toastInstance.duration)
}
}
}
export default ToastPlugin
main.js1
2import Toast from './plugin/toast/config'
Vue.use(Toast)
全局使用1
this.$toast.show({type:'success', duration:3000, text:'hello'})
vuex demo
一个小demo, 示范Vuex 中getter/mutaions/actions的一般用法1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vuex demo</title>
</head>
<body>
<div id="app">
<btn></btn>
</div>
<script src="https://cdn.bootcss.com/vue/2.3.0/vue.js"></script>
<script src="https://cdn.bootcss.com/vuex/3.0.1/vuex.js"></script>
<script>
getData = ()=>{
return new Promise((resolve,reject)=>{resolve(100)})
},
getOtherData = ()=>{
return new Promise((resolve,reject)=>{resolve(200)})
}
const store = new Vuex.Store({
state: {
count: 0,
todos: [
{ id: 1, text: 'A', done: true },
{ id: 2, text: 'B', done: false },
{ id: 3, text: 'C', done: true },
{ id: 4, text: 'D', done: false }
]
},
getters:{
doneTodos: state=> {return state.todos.filter(todo => todo.done)}
},
mutations: {
increment (state,payload) {
if(payload.offset)state.count += payload.offset
else state.count += 1
},
gotData(state, payload){
console.log('mutation: gotData', payload)
return new Promise((resolve,reject)=>{resolve(300)})
},
gotOtherData(state, payload){
console.log('mutation: gotOtherData', payload)
return new Promise((resolve,reject)=>{resolve(400)})
}
},
actions: {
increment ({commit},payload) {
commit('increment',payload)
},
async actionA({commit, state}){
let data = {...state}
console.log(data)
commit('gotData',await getData())
},
async actionB({dispatch,commit}){
await dispatch('actionA'); // action 一般是异步操作,触发后返回的是promise
commit('gotOtherData', await getOtherData())
}
}
})
</script>
<script>
let {mapState, mapMutations, mapActions, mapGetters} = Vuex
Vue.component('btn', {
template:
`<div><button @click="addNum({offset:1})">Add 1</button>
</br>
<button @click="add3({offset:3})">Add 3</button>
<p>data is :{{count}}</p>
<button @click="trigger">test</button>
<div v-for="(item, index) in doneTodos">{{item.text}}</div>
</div>`
,
computed:{
...mapState(['count']) ,
...mapGetters(['doneTodos'])
},
mounted(){
console.log(this.$store)
},
methods:{
...mapMutations({'addNum':'increment'}),
...mapActions({'add3':'increment'}) ,
...mapActions({'trigger':'actionB'})
}
})
new Vue({
el:"#app",
store
})
</script>
</body>
</html>
vue项目目录结构
- assets
- config
- env.js(dev和production环境配置切换)
- utils.js (基础js方法库)
- fetch.js (对axois库进行封装,统一处理请求错误)
- components (组件)
- filter
- index.js (过滤器,需在全局注册)
- site.js (不同过滤内容)
- taskStatus.js
- page (页面)
- base.vue (嵌套路由的基础页面)
- plugin
- router (路由配置)
- service
- index.js (网络服务层)
- roleA.js (不同权限或角色的请求)
- roleB.js
- store
- index.js (全局状态)
- mutation-type.js
全局scss文件
- style
- mixin.scss
- common.scss
1 | @mixin wh($width, $height){ |
1 | .ellipsis{ |
自定义vue双向绑定
v-model作用在标签上1
<input v-model="price">
语法糖,实际上是1
<input :value="price" @input="price=$event.target.value">
v-model作用在自定义组件上1
<cust-input v-model="price"></cust-input>
语法糖,实际上是1
2<cust-input :value="price" @input="price=argument[0]">
<cust-input :value="price" @input="price= $event"">
要让组件的v-model生效,必须
- 接受一个value属性
- 在新value的时候触发input事件。$emit
1 | <!DOCTYPE html> |