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
- 公众号:前方录
- 有什么不懂的地方欢迎联系我,帮到你是我会很开心