vue组件开发的流程

注意:想要使下面的代码有效果必须要下载好vue.js文件哈。并且要注意引入路径是否正确,要不然页面会无效果哦

例子效果图

图 1

1.1.直接在DOM中写好弹窗组件的方法

<!doctype html>
<html lang="en">
<head>
	<meta charset="utf-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<meta name="viewport" content="width=device-width,initial-scale=1">
	<title>vue通迅录组件</title>
	<style>
		* { margin: 0; padding: 0;}
		li {list-style: none;}
		/*头部组件css开始*/
		#header {width: 100%; height: 40px; background-color: #666; color: #fff; text-align: center; line-height: 40px;top: 0; left: 0; z-index: 10;}
		#header button {height: 40px; line-height: 40px; text-align: center; padding: 0 5px;}
		#header button:first-of-type { float: left;}
		#header button:last-of-type { float: right;}
		/*头部组件css结束*/

		/*内容组件css开始*/
		#list { position: relative; top : 40px; overflow: hidden}
		#list .list_user p { background-color: #ccc; padding-left: 10px;}
		#list .list_user ul li { height: 50px; line-height: 50px;border-bottom: 1px #ccc solid; padding-left: 10px;}
		#list .list_index { position: fixed; right: 10px; top: 50%; font-size: 20px; }
		#list .list_index li { margin: 5px 0;}
		/*内容组件css结束*/

		/*弹窗组件css开始 */
		#alert { width: 100%; height: 100%; background:rgba(0, 0, 0, 0.5); position: fixed; left: 0; top: 0; z-index: 20; display: none;}
		#alert .alert_content { width: 200px; height: 150px; background-color: #fff; border-radius: 5px; margin: auto;position: relative;}
		#alert .alert_content .alert_title { padding: 5px; border-bottom: 1px solid #ccc; }
		#alert .alert_content .alert_body {height: 50px; border-bottom: 1px solid #ccc; line-height: 50px; text-align: center;}
		#alert .alert_content .alert_btn {position: absolute; right: 0; bottom: 0; margin: 10px; padding: 5px;}
		#alert .alert_content .alert_btn button:first-of-type { margin-right: 10px;}
		/*弹窗组件css结束 */
	</style>
	<script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
	<!-- 头部组件html开始 -->
	<my-header custom-title="通讯录" custom-fixed>
		<button v-on:touchstart="backBtn" slot="left">返回</button>
		<button v-on:touchstart="homeBtn" slot="right">主页</button>
	</my-header>
	<!-- 头部组件html结束 -->

	<!-- 内容组件html开始 -->
	<my-list :user-data="userData"></my-list>
	<!-- 内容组件html结束 -->

	<!-- 弹窗组件html开始 -->
	<my-alert custom-title="呼叫">
		<div class="alert_btn">
			<button @touchstart="confirmBtn">确定</button>
			<button @touchstart="cancelBtn">取消</button>
		</div>
	</my-alert>
	<!-- 弹窗组件html结束 -->

</div>
<script>
//创建空实例开始
var busVM = new Vue();


//创建空实例结束

// 头部组件开始 
Vue.component('my-header', {
	template: `<div id="header" v-bind:style="{'position': customFixed ? 'fixed' : 'absolute'}">
					<slot name="left"></slot>
					{{customTitle}}
					<slot name="right"></slot>
				</div>`,
	props: {
		'customTitle': {
			type: String,
			default: '标题'
		},
		'customFixed': {
			type: Boolean,
			default: false
		}
	}
})
// 头部组件结束
// 内容组件js开始
var userData = [
	{"index": "A", "users": [
		{"name": "a1", "tel": "13520331111"},
		{"name": "a2", "tel": "13520331112"},
		{"name": "a3", "tel": "13520331113"}
	]},
	{"index": "B", "users": [
		{"name": "b1", "tel": "13520331121"},
		{"name": "b2", "tel": "13520331122"},
		{"name": "b3", "tel": "13520331123"}
	]},
	{"index": "C", "users": [
		{"name": "c1", "tel": "13520331131"},
		{"name": "c2", "tel": "13520331132"},
		{"name": "c3", "tel": "13520331133"}
	]},
	{"index": "D", "users": [
		{"name": "d1", "tel": "13520331141"},
		{"name": "d2", "tel": "13520331142"},
		{"name": "d3", "tel": "13520331143"}
	]},
	{"index": "E", "users": [
		{"name": "e1", "tel": "13520331151"},
		{"name": "e2", "tel": "13520331152"},
		{"name": "e3", "tel": "13520331153"}
	]},
	{"index": "F", "users": [
		{"name": "f1", "tel": "13520331161"},
		{"name": "f2", "tel": "13520331162"},
		{"name": "f3", "tel": "13520331163"}
	]}
]
Vue.component('my-list', {
	template: `<div id="list">
				<ul class="list_user" ref="listUser" @touchMove="bMove=true">
					<li v-for="item in userData">
						<p>{{item.index}}</p>
						<ul>
							<li @touchend="showTel(user.tel)" v-for="user in item.users">{{user.name}}</li>	
						</ul>
					</li>
					
				</ul>
				<ul class="list_index" ref="listIndex">
					<li @touchstart="setScroll" v-for="item in userIndex">{{item}}</li>
				</ul>
			</div>`,
	data: function () {
		return {
			bMove: false
		}
	},
	props: {
		'user-data': {
			type: Array,
			default: function () {
				return []
			}
		}	
	},
	computed: {
		userIndex: function () {
			return this.filterIndex(this.userData);
		}
	},
	methods: {
		//取出右侧索引栏的数据
		filterIndex: function (data) {
			var result = [];
			for (var i = 0; i < data.length; i++) {
				if (data[i].index) {
					result.push(data[i].index);
				}				
			}
			return result;
		},
		// 让右侧索引上下居中对齐
		setListIndexPos: function () {
			var iH = this.$refs.listIndex.offsetHeight;
			this.$refs.listIndex.style.marginTop = - iH / 2 + 'px';
		},
		// 点击索引按钮让页面滚动到当前索引的位置
		setScroll: function (ev) {			
			var aP = this.$refs.listUser.getElementsByTagName('p');
			for (var i = 0; i < aP.length; i++) {
				if (aP[i].innerHTML == ev.target.innerHTML) {
					window.scrollTo(0, aP[i].offsetTop)
				}
			}
		},
		showTel: function (tel) {
			if (!this.bMove) {
				console.log(tel);
				busVM.$emit('changeEvents', tel)
			} else {
				this.bMove = false;
			}
		}
	},
	mounted: function () {
		// 在初始化的时候执行函数:让右侧索引上下居中对齐
		this.setListIndexPos();
	}
})
// 内容组件js结束

// 弹窗组件js开始
Vue.component('my-alert', {
	template: `<div id="alert" ref="alert">
				<div class="alert_content">
					<div class="alert_title">{{customTitle}}</div>
					<div class="alert_body">{{customBody}}</div>
					<slot></slot>
				</div>
			</div>`,
	props: {
		'customTitle': {
			type: String,
			default: '弹窗'
		},	
	},
	data: function () {
		return {
			'customBody': ''
		}
	},
	mounted: function () {
		busVM.$on('changeEvents', function (tel) {
			this.customBody = tel;
			this.$refs.alert.style.display = "flex";
		}.bind(this))
	}
})
// 弹窗组件js结束
var vm = new Vue({
	el: "#app",
	data: {
		userData: userData
	},
	methods: {
		backBtn: function () {
			alert("backBtn");
		},
		homeBtn: function () {
			alert("homeBtn");
		},
		confirmBtn: function () {
			alert('confirmBtn');
		},
		cancelBtn: function () {
			this.$children[2].$el.style.display = "none"
		}
	}
})
</script>
</body>
</html>

1.2.用javascript动态地创建DOM弹窗组件

<!doctype html>
<html lang="en">
<head>
	<meta charset="utf-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<meta name="viewport" content="width=device-width,initial-scale=1">
	<title>vue js动态创建通迅录弹窗组件</title>
	<style>
		* { margin: 0; padding: 0;}
		li {list-style: none;}
		/*头部组件css开始*/
		#header {width: 100%; height: 40px; background-color: #666; color: #fff; text-align: center; line-height: 40px;top: 0; left: 0; z-index: 10;}
		#header button {height: 40px; line-height: 40px; text-align: center; padding: 0 5px;}
		#header button:first-of-type { float: left;}
		#header button:last-of-type { float: right;}
		/*头部组件css结束*/

		/*内容组件css开始*/
		#list { position: relative; top : 40px; overflow: hidden}
		#list .list_user p { background-color: #ccc; padding-left: 10px;}
		#list .list_user ul li { height: 50px; line-height: 50px;border-bottom: 1px #ccc solid; padding-left: 10px;}
		#list .list_index { position: fixed; right: 10px; top: 50%; font-size: 20px; }
		#list .list_index li { margin: 5px 0;}
		/*内容组件css结束*/

		/*弹窗组件css开始 */
		#alert { width: 100%; height: 100%; background:rgba(0, 0, 0, 0.5); position: fixed; left: 0; top: 0; z-index: 20; display: flex;}
		#alert .alert_content { width: 200px; height: 150px; background-color: #fff; border-radius: 5px; margin: auto;position: relative;}
		#alert .alert_content .alert_title { padding: 5px; border-bottom: 1px solid #ccc; }
		#alert .alert_content .alert_body {height: 50px; border-bottom: 1px solid #ccc; line-height: 50px; text-align: center;}
		#alert .alert_content .alert_btn {position: absolute; right: 0; bottom: 0; margin: 10px; padding: 5px;}
		#alert .alert_content .alert_btn button:first-of-type { margin-right: 10px;}

		/*弹窗组件css结束 */
	</style>
	<script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
	<!-- 头部组件html开始 -->
	<my-header custom-title="通讯录" custom-fixed>
		<button v-on:touchstart="backBtn" slot="left">返回</button>
		<button v-on:touchstart="homeBtn" slot="right">主页</button>
	</my-header>
	<!-- 头部组件html结束 -->

	<!-- 内容组件html开始 -->
	<my-list :user-data="userData"></my-list>
	<!-- 内容组件html结束 -->
        因为弹窗组件要动态创建,所以这里没有弹窗组件了!
</div>
<script>
//创建空实例开始
// var busVM = new Vue();
// 这里不需要空实例了;
//创建空实例结束

// 头部组件开始 
Vue.component('my-header', {
	template: `<div id="header" v-bind:style="{'position': customFixed ? 'fixed' : 'absolute'}">
					<slot name="left"></slot>
					{{customTitle}}
					<slot name="right"></slot>
				</div>`,
	props: {
		'customTitle': {
			type: String,
			default: '标题'
		},
		'customFixed': {
			type: Boolean,
			default: false
		}
	}
})
// 头部组件结束
// 内容组件js开始
var userData = [
	{"index": "A", "users": [
		{"name": "a1", "tel": "13520331111"},
		{"name": "a2", "tel": "13520331112"},
		{"name": "a3", "tel": "13520331113"}
	]},
	{"index": "B", "users": [
		{"name": "b1", "tel": "13520331121"},
		{"name": "b2", "tel": "13520331122"},
		{"name": "b3", "tel": "13520331123"}
	]},
	{"index": "C", "users": [
		{"name": "c1", "tel": "13520331131"},
		{"name": "c2", "tel": "13520331132"},
		{"name": "c3", "tel": "13520331133"}
	]},
	{"index": "D", "users": [
		{"name": "d1", "tel": "13520331141"},
		{"name": "d2", "tel": "13520331142"},
		{"name": "d3", "tel": "13520331143"}
	]},
	{"index": "E", "users": [
		{"name": "e1", "tel": "13520331151"},
		{"name": "e2", "tel": "13520331152"},
		{"name": "e3", "tel": "13520331153"}
	]},
	{"index": "F", "users": [
		{"name": "f1", "tel": "13520331161"},
		{"name": "f2", "tel": "13520331162"},
		{"name": "f3", "tel": "13520331163"}
	]}
]
Vue.component('my-list', {
	template: `<div id="list">
				<ul class="list_user" ref="listUser" @touchMove="bMove=true">
					<li v-for="item in userData">
						<p>{{item.index}}</p>
						<ul>
							<li @touchend="showTel(user.tel)" v-for="user in item.users">{{user.name}}</li>	
						</ul>
					</li>
					
				</ul>
				<ul class="list_index" ref="listIndex">
					<li @touchstart="setScroll" v-for="item in userIndex">{{item}}</li>
				</ul>
			</div>`,
	data: function () {
		return {
			bMove: false
		}
	},
	props: {
		'user-data': {
			type: Array,
			default: function () {
				return []
			}
		}	
	},
	computed: {
		userIndex: function () {
			return this.filterIndex(this.userData);
		}
	},
	methods: {
		//取出右侧索引栏的数据
		filterIndex: function (data) {
			var result = [];
			for (var i = 0; i < data.length; i++) {
				if (data[i].index) {
					result.push(data[i].index);
				}				
			}
			return result;
		},
		// 让右侧索引上下居中对齐
		setListIndexPos: function () {
			var iH = this.$refs.listIndex.offsetHeight;
			this.$refs.listIndex.style.marginTop = - iH / 2 + 'px';
		},
		// 点击索引按钮让页面滚动到当前索引的位置
		setScroll: function (ev) {			
			var aP = this.$refs.listUser.getElementsByTagName('p');
			for (var i = 0; i < aP.length; i++) {
				if (aP[i].innerHTML == ev.target.innerHTML) {
					window.scrollTo(0, aP[i].offsetTop)
				}
			}
		},
		showTel: function (tel) {
			if (!this.bMove) {
				myAlert({
					title: '呼叫',
					body: tel,
					confirm: function () {
						alert(1);	
					},
					cancel: function () {
						// alert(2);
						document.getElementById('app').removeChild(document.getElementById('alert'));
					}
				})
			} else {
				this.bMove = false;
			}
		}
	},
	mounted: function () {
		// 在初始化的时候执行函数:让右侧索引上下居中对齐
		this.setListIndexPos();
	}
})
// 内容组件js结束

// 弹窗组件js开始

var myAlert = (function () {
	var defaults = {
		title: '弹窗',
		body: '',
		confirm: null,
		cancel: null
	}
	var alertCom = {
		template: `<div id="alert" ref="alert">
				<div class="alert_content">
					<div class="alert_title">{{customTitle}}</div>
					<div class="alert_body">{{customBody}}</div>
					<div class="alert_btn">
						<button v-if="confirm" @touchstart="confirm">确定</button>
						<button  v-if="cancel" @touchstart="cancel">取消</button>
					</div>
				</div>
			</div>` 
	};
	var MyComponent = Vue.extend(alertCom);
	return function (opts) {
		for (var attr in opts) {
			defaults[attr] = opts[attr];
		}
		var vm = new MyComponent({
			el: document.createElement('div'),
			data: {
				customTitle: defaults.title,
				customBody: defaults.body,
				confirm: defaults.confirm,
				cancel: defaults.cancel
			}
		})
		document.getElementById('app').appendChild(vm.$el);
	}
})()
// 弹窗组件js结束
var vm = new Vue({
	el: "#app",
	data: {
		userData: userData
	},
	methods: {
		backBtn: function () {
			alert("backBtn");
		},
		homeBtn: function () {
			alert("homeBtn");
		},
 
		// confirmBtn: function () {
		//	alert('confirmBtn');
		// },
		// cancelBtn: function () {
		//	this.$children[2].$el.style.display = "none"
		// }
                上面的两个方法是无用的,因为js写的组件里面已经包涵了这两个方法了

	}
})
</script>
</body>
</html>

下一篇:同样的组件开发流程小案例演示

博主联系方式:

  • 微信:34419369
  • QQ: 34419369
  • 公众号:前方录
  • 有什么不懂的地方欢迎联系我,帮到你是我会很开心

Leave a Reply

电子邮件地址不会被公开。 必填项已用*标注