JobbyM's Blog

记一次基于vant 组件的二次开发

简介

在开发手机端的H5 项目时,选择了vue + vant生态,在使用PullRefresh 下拉刷新 组件时,需要进行自定义显示。但是首页Tab 下有3 个页面都需要进行定制,为了方便将其封装为一个组件。

源码

下面是pullRefresh.vue 以及parent.vue 的相关源码

1.子组件pullRefresh.vue

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
<template>
<van-pull-refresh v-model="isLoading" :head-height="80" @refresh="onRefresh">
<!-- 下拉提示,通过 scale 实现一个缩放效果 -->
<template #pulling="props">
<img
class="doge"
src="https://img.yzcdn.cn/vant/doge.png"
:style="{ transform: `scale(${props.distance / 80})` }"
/>
</template>

<!-- 释放提示 -->
<template #loosing>
<img class="doge" src="https://img.yzcdn.cn/vant/doge.png" />
</template>

<!-- 加载提示 -->
<template #loading>
<img class="doge" src="https://img.yzcdn.cn/vant/doge-fire.jpg" />
</template>
<slot></slot>
</van-pull-refresh>
</template>
<script>
export default {
name: 'pull-refresh',
props: {
value: {
type: Boolean,
default: false,
}
},
data () {
return {
isLoading: false,
}
},
watch: {
value(val) {
// 3.1 侦听到value 值改为true, 这时的val 为 true
// 7. 侦听到父组件isLoading 值的改变,这是的val 为false
if (val == false) {
// 8. 由于val == false,此时子组件的isLoading 赋值为 false,完成下拉刷新过程
this.isLoading = false
}
}
},
methods: {
// 1. 子组件首次触发onRefresh 事件
onRefresh () {
// 2. 更新父组件的value 的值,这里的value 在父组件中是isLoading
this.$emit('input', true)
// 4. 触发父组件的refresh 事件,也就是父组件中的onRefresh 事件
this.$emit('refresh')
},
}
}
</script>
<style>
.doge {
width: 140px;
height: 72px;
margin-top: 8px;
border-radius: 4px;
}
</style>

2.父组件parent.vue

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
<tempalte>
<pull-refresh v-model="isLoading" @refresh="onRefresh">
父组件信息
</pull-refresh>
</template>
<script>
import pullRefresh from './pullRefresh.vue'
export default {
components: {
'pull-refresh': pullRefresh
},
data () {
return {
// 3.2 由于子组件中产生了input 事件,导致isLoading = true
isLoading: false,
}
},
methods: {
// 5. 子组件触发了父组件中的onRefresh 方法
onRefresh () {
setTimeout(()=>{

// 6. 下拉刷新完成时,更新父组件的isLoading 为false,此时触发了子组件中的value 的值改变
this.isLoading: false
}, 2000)
}
}
}
</script>

源码解析

使用到的相关知识点:

  1. 插槽
  2. 计算属性和侦听属性
  3. 自定义事件
  4. 自定义组件的v-model

过程分析

在页面上模拟一次下拉刷新

  1. 子组件首次触发onRefresh 事件
  2. 更新父组件的value 的值,这里的value 在父组件中是isLoading
  3. 此时会触发两次改变
    3.1 侦听到value 值改为true, 这时的val 为 true
    3.2 由于子组件中产生了input 事件,导致isLoading = true
  4. 触发父组件的refresh 事件,也就是父组件中的onRefresh 事件
  5. 子组件触发了父组件中的onRefresh 方法
  6. 下拉刷新完成时,更新父组件的isLoading 为false,此时触发了子组件中的value 的值改变
  7. 侦听到父组件isLoading 值的改变,这是的val 为false
  8. 由于val == false,此时子组件的isLoading 赋值为 false,完成下拉刷新过程

总结

项目中还是需要多看多写多总结,这样才能更好的理解Vue