Kros的博客 Kros的博客
首页
  • CSS
  • 工具
  • Vue
  • js
  • Vue3
  • 算法
  • 折腾笔记
一言
  • 分类
  • 标签
  • 归档
码云

Kros

凡心所向,素履以往,生如逆旅,一苇以航
首页
  • CSS
  • 工具
  • Vue
  • js
  • Vue3
  • 算法
  • 折腾笔记
一言
  • 分类
  • 标签
  • 归档
码云
  • CSS

  • JavaScript

  • 工具

  • Vue

    • vue批量引入组件
    • vue中watch用法
    • vue使用基础JSX语法
    • vue首页白屏
    • vue长列表优化
    • 模板文件中script、template、style存在必要性
    • popup弹窗组件
    • 使用$mount和extend扩展vue
    • 扩展toast合并popup(按需加载)
    • canvas实现弧形进度条
    • vue中使用CSS Modules
    • vue实现无限轮播图
    • vue半圆形菜单
    • 纯CSS实现圆形进度条
    • v-model简单实现
    • vue带箭头下拉框
    • vue事件修饰符
    • vue鼠标悬浮显示提示文字
    • vue添加发布版本号方法
    • vue配置全局样式文件
    • vue在env development中设置全局变量不生效
    • vue引入less或scss全局变量
    • vue中使用Keepalive
    • vue2为什么只支持一个根节点
    • vue打包优化分析工具—webpack-bundle-analyzer
    • vue使用echarts(按需加载)
    • echarts柱形图重合堆叠
    • vue使用draggable实现多列拖拽(解决空列不能拖拽问题)
    • vue禁止三方库打包到bundle中
    • npm run serve运行背后的思考
    • vxe-table树结构不允许insert
    • vue组件延迟加载
    • 多页面应用配置
    • vue项目常用优化
    • vue实现拖动拼图验证码
    • vue虚拟dom
    • canvas心形动画
    • canvas绘制玫瑰曲线
    • element表单validateField验证部分字段
    • element日期选择限制今天以后并精确到小时
    • 前端使用JSEncrypt和node-rsa进行rsa加密传输和接收解密
    • elementui日期选择器生日只选择月和日不选择年并隐藏年份
    • el-upload组件第二次点击手动submit时不生效
    • element表单内输入框使用@keyup enter native回车时会刷新页面
  • antdv踩坑记录

  • Vue3

  • 前端
  • Vue
kros
2021-01-03

使用$mount和extend扩展vue

上一篇我已经对popup组件进行了封装,在要使用的地方进行import即可。但如果使用过于频繁你又不想注册为全局组件,这里就不得不利用vue的$mount和extend方法了。 $mount大家应该都很熟悉了,在vue项目的main.js中都有使用:

new Vue({
  render: h => h(App),
}).$mount('#app')
//或者
const app = new Vue({
  render: h => h(App),
})
app.$mount('#app');
// 又或者
new Vue({
  el: '#app',
  render: h => h(App)
})
1
2
3
4
5
6
7
8
9
10
11
12
13

官方文档 说的很详细,new Vue时指定el会自定调用$mount,如果没有指定可以在后面手动调用$mount方法进行挂载

extend的作用是为vue组件构建一个子类,它一般搭配$mount方法使用。先创建组件实例在通过$mount动态挂载元素。

将上一篇的popup代码修改如下:

<template>
	<div class="popup" :class="showPop ? 'show' : 'hide'">
		<div class="mask">
			<div class="body">
				<div class="title">{{title}}</div>
				<div class="content">{{content}}</div>
				<div class="btn">
					<div class="button" @click="cancelClick">{{cancelText}}</div>
					<div class="button" @click="confirmClick">{{confirmText}}</div>
				</div>
				
			</div>
		</div>
	</div>
</template>

<script>
	export default {
		data(){
			return {
				title: '',
				content: '',
				cancelText: '',
				confirmText: '',
				confirm: null,
				cancel: null,
				// 没有隐藏状态,只存在显示和移除状态
				showPop: true
			}
		},
		methods: {
			confirmClick() {
				if(typeof this.confirm == 'function') {
					this.confirm('click:comfirm');
					this.destorySelf();
				}
			},
			cancelClick() {
				if(typeof this.cancel == 'function') {
					this.cancel('click:cancel');
					this.destorySelf();
				}
			},
			
			// 移除
			destorySelf() {
				this.showPop = false;
				// 延迟以播放动画
				setTimeout(() => {
					// 销毁实例 移除事件、指令,删除子实例,但dom依然存在
					this.$destroy(true);
					// 从dom节点删除
					this.$el && this.$el.parentNode.removeChild(this.$el) 
				}, 200);
			}
		},
		mounted() {
		}
	}
</script>

<style scoped>
	.popup,.mask {
		position: fixed;
		z-index: 10000;
		top: 0;
		left: 0;
		right: 0;
		bottom: 0;
	}
	
	.popup .mask {
		position: fixed;
		z-index: 10001;
		background: rgba(1,1,1,0);
	}
	
	.popup .mask .body {
		position: absolute;
		display: flex;
		flex-direction: column;
		justify-content: center;
		z-index: 10002;
		width: 60%;
		min-height: auto;
		top: 50%;
		left: 50%;
		transform: translate(-50%, -50%);
		background: #FFFFFF;
		border-radius: 10px;
		text-align: center;
	}
	
	.popup .mask .body .content{
		padding: 10px 25px 20px;
		text-align: center;
		font-size: 18px;
		color: #333333;
	}
	
	.popup .mask .body .title {
		padding: 5px 25px;
		text-align: center;
		font-size: 22px;
		color: #333333;
	}
	
	.popup .mask .body .btn {
		display: flex;
		flex-direction: row;
		align-items: center;
		height: 50px;
		border-top: 1px solid #005599;
	}
	
	.popup .mask .body .btn .button {
		flex: 1;
		line-height: 2;
		text-align: center;
		box-sizing: border-box;
		color: #005599;
	}
	
	.popup .mask .body .btn .button + .button {
		border-left: 1px solid #005599;
	}
	
	.popup.show .mask {
		animation: maskShow .2s linear forwards;
	}
	
	.popup.hide .mask {
		animation: maskHide .2s linear forwards;
	}
	
	.popup.show .mask .body {
		animation: bodyShow .2s linear forwards;
	}
	
	.popup.hide .mask .body {
		animation: bodyHide .2s linear forwards;
	}
	
	/* mask入场动画 */
	@keyframes maskShow{
		from{
			background-color: rgba(1,1,1,0);
		}
		to{
			background-color: rgba(1,1,1,.4);
		}
	}
	
	/* body入场动画 */
	@keyframes bodyShow{
		from{
			opacity: 0;
		}
		to{
			opacity: 1;
		}
	}
	
	/* mask退场动画 */
	@keyframes maskHide{
		from{
			background-color: rgba(1,1,1,.4);
		}
		to{
			background-color: rgba(1,1,1,0);
		}
	}
	
	/* body退场动画 */
	@keyframes bodyHide{
		from{
			opacity: 1;
		}
		to{
			opacity: 0;
		}
	}
</style>

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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184

添加控制modal生成文件

  • 使用extend生成新的modal实例
  • new modal时传入data参数,它会自动给modal组件data赋值。注意这里data可以不是函数
  • 使用$mount挂载,因为没有提供挂载元素需要手动使用appendChild添加到真实dom
  • 使用vue插件使用方式install导出用于Vue.use使用
// modal.js
import Vue from 'vue'
import modal from './modal.vue'

const modalSub = Vue.extend(modal)

export function createModal(options) {
	let m = new modalSub({
		data: {
			title: options && options.title || '',
			content: options && options.content || '',
			cancelText: options && options.cancelText || '取消' ,
			confirmText: options && options.confirmText || '确定',
			confirm: options && options.confirm || null,
			cancel: options && options.cancel || null
		}
	});
	let vm = m.$mount();
	document.querySelector('#app').appendChild(vm.$el);
	return vm;
}

export default {
	install: (Vue) => {
		Vue.prototype.$modal = createModal;
	}
}
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

在main.js中添加以下代码,即可在工程中使用

// main.js
import modal from './modal/modal.js'
Vue.use(modal);
1
2
3

具体使用方式如下:

// 打开模态框
this.$modal({
	title: 'title',
	content: '内容内容内容内容内容内容内容内容内容内容内容内容内容',
	cancelText: '取消测试',
	confirmText: '确定测试',
	confirm: (e) => {
		console.log(e);
	},
	cancel: (e) => {
		console.log(e);
	}
});
1
2
3
4
5
6
7
8
9
10
11
12
13

代码示例

#vue
上次更新: 2025/09/05, 8:09:00
popup弹窗组件
扩展toast合并popup(按需加载)

← popup弹窗组件 扩展toast合并popup(按需加载)→

最近更新
01
Find the next perfect square
09-05
02
Regex validate PIN code
09-05
03
Find the odd int
09-05
更多文章>
Theme by Vdoing | Copyright © 2020-2025 kros king
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
icon-heart-o icon-heart icon-infinity icon-pause icon-play link next prev