Vue组件开发实例:

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="UTF-8">
  5. <title></title>
  6. <link rel="stylesheet" href="SJStyle.css" />
  7. <style>
  8. /*
  9. * 由于IE不支持<template>标签,所以template标签中的内容在IE下会直接显示出来。
  10. * 将模板设为隐藏即可解决这个问题,template标签各浏览器支持请参考:http://caniuse.com/#feat=template
  11. */
  12. #grid-template,
  13. #dialog-template {
  14. display: none;
  15. }
  16. </style>
  17. </head>
  18. <body>
  19. <div id="app">
  20. <!-- 上部查询框:通过searchQuery过滤 -->
  21. <div class="container">
  22. <div class="form-group">
  23. <label>Search</label>
  24. <input type="text" class="search-input" v-model="searchQuery" />
  25. </div>
  26. </div>
  27. <!-- 下部表格框 -->
  28. <div class="container">
  29. <simple-grid :data-list="people" :columns="columns" :search-key="searchQuery">
  30. </simple-grid>
  31. </div>
  32. </div>
  33. <!-- 父组件simple-grid -->
  34. <template id="grid-template">
  35. <table>
  36. <!-- 表头,从columns里面取数据 -->
  37. <thead>
  38. <tr>
  39. <th v-for="col in columns">
  40. {{ col.name | capitalize}}
  41. </th>
  42. <th>Delete</th>
  43. </tr>
  44. </thead>
  45. <!-- 表体,从people绑定的dataList里面取数据 -->
  46. <tbody>
  47. <!-- 这里有个filterBy过滤器的使用 -->
  48. <tr v-for="(index,entry) in dataList | filterBy searchKey">
  49. <!-- 从columns里面取数据,判断是否有主键,有主键就显示编辑信息;没有就直接显示 -->
  50. <!-- 此处注意正好columns里的属性的值col.name,正好要是dataList里的entry的key,所以通过entry[col.name]去获取值 -->
  51. <td v-for="col in columns">
  52. <span v-if="col.isKey"><a href="javascript:void(0)" @click="openEditItemDialog(entry[col.name])">{{entry[col.name]}}</a></span>
  53. <span v-else>{{entry[col.name]}}</span>
  54. </td>
  55. <!-- 删除的操作按钮,传了整条数据的信息作为参数 -->
  56. <td class="text-center">
  57. <button class="btn-danger" @click="deleteItem(entry)">delete</button>
  58. </td>
  59. </tr>
  60. </tbody>
  61. </table>
  62. <!-- 新建操作按钮,传了标题作为参数 -->
  63. <div class="container">
  64. <button class="btn" @click="openNewItemDialog('Create New Item')">Create</button>
  65. </div>
  66. <!-- 此处就是通过props指定父子组件通信的东西,就是让父组件的内容和子组件的内容对应 -->
  67. <modal-dialog :mode="mode" :title="title" :item="item" :fields="columns" v-on:create-item="createItem" v-on:update-item="updateItem">
  68. </modal-dialog>
  69. </template>
  70. <!-- 子组件modal-dialog -->
  71. <template id="dialog-template">
  72. <div class="dialogs">
  73. <!-- v-bind:class通过show的值去判断是否新增class名,所以我们通过控制这个show值来达到显示和隐藏子组件的目的 -->
  74. <div class="dialog" v-bind:class="{ 'dialog-active': show }">
  75. <div class="dialog-content">
  76. <header class="dialog-header">
  77. <h1 class="dialog-title">{{ title }}</h1>
  78. </header>
  79. <div class="dialog-body">
  80. <!-- 通过遍历fields里的值,来加整个div -->
  81. <div v-for="field in fields" class="form-group">
  82. <label>{{ field.name }}</label>
  83. <!-- 如果column有dataSource属性就显示下拉列表 -->
  84. <!-- 如果是编辑模式,并且有主键属性,就禁用 -->
  85. <select v-if="field.dataSource" v-model="item[field.name]" :disabled="mode === 2 && field.isKey">
  86. <!-- 遍历column里的dataSource属性的值 -->
  87. <option v-for="opt in field.dataSource" :value="opt">{{ opt }}</option>
  88. </select>
  89. <!-- 如果没有dataSource属性,就显示文本框 -->
  90. <input v-else type="text" v-model="item[field.name]" :disabled="mode === 2 && field.isKey">
  91. </div>
  92. </div>
  93. <footer class="dialog-footer">
  94. <div class="form-group">
  95. <label></label>
  96. <button class="btn-save" v-on:click="save">Save</button>
  97. <button class="btn-close" v-on:click="close">Close</button>
  98. </div>
  99. </footer>
  100. </div>
  101. </div>
  102. <div class="dialog-overlay"></div>
  103. </div>
  104. </template>
  105.  
  106. <script src="vue.js"></script>
  107. <script>
  108. //注册父组件simple-grid
  109. Vue.component('simple-grid', {
  110. template: '#grid-template',
  111. //父组件其实也就是vue实例的子组件,所以也要通过props去与vue实例里的数据进行对应绑定:这里dataList绑定people,columns绑定columns,searchKey绑定searchQuery
  112. props: ['dataList', 'columns', 'searchKey'],
  113. //定义父组件里的数据
  114. data: function() {
  115. return {
  116. mode: ,
  117. title: '',
  118. keyColumn: '',
  119. item: {}
  120. }
  121. },
  122. //通过钩子函数去设定name为主键,并赋值给keyColumn,就是this.keyColumn就是获取到主键"name"
  123. ready: function() {
  124. for(var i = ; i < this.columns.length; i++) {
  125. if(this.columns[i].isKey) {
  126. this.keyColumn = this.columns[i]['name']
  127. break;
  128. }
  129. }
  130. },
  131. methods: {
  132. //点击新建按钮,弹出子组件
  133. openNewItemDialog: function(title) {
  134. // 对话框的标题
  135. this.title = title
  136. // mode = 1表示新建模式
  137. this.mode =
  138. // 初始化this.item
  139. this.item = {}
  140. // 广播事件,showDialog是modal-dialog组件的一个方法,传入参数true表示显示对话框
  141. this.$broadcast('showDialog', true)
  142. },
  143. //点击编辑弹出子组件
  144. openEditItemDialog: function(key) {
  145. // 根据主键查找当前修改的数据
  146. var currentItem = this.findItemByKey(key);//key就是传过来的name参数
  147. // 修改对话框的标题
  148. this.title = 'Edit Item - ' + key;
  149. // mode = 2表示修改模式
  150. this.mode = ;
  151. // 将选中的数据拷贝到this.item
  152. this.item = this.initItemForUpdate(currentItem);
  153. // 父组件让子组件显示:广播事件,传入参数true表示显示对话框
  154. this.$broadcast('showDialog', true);
  155. },
  156. // 就是一个深拷贝函数:弹出修改数据的对话框时,使用对象的深拷贝
  157. initItemForUpdate(p, c) {
  158. c = c || {};
  159. for(var i in p) {
  160. // 属性i是否为p对象的自有属性
  161. if(p.hasOwnProperty(i)) {
  162. // 属性i是否为复杂类型
  163. if(typeof p[i] === 'object') {
  164. // 如果p[i]是数组,则创建一个新数组
  165. // 如果p[i]是普通对象,则创建一个新对象
  166. c[i] = Array.isArray(p[i]) ? [] : {};
  167. // 递归拷贝复杂类型的属性
  168. this.initItemForUpdate(p[i], c[i]);
  169. } else {
  170. // 属性是基础类型时,直接拷贝
  171. c[i] = p[i];
  172. }
  173. }
  174. }
  175. return c;
  176. },
  177. //该函数的作用就是通过传过来的name,查找返回那条数据
  178. findItemByKey: function(key) {
  179. var keyColumn = this.keyColumn;//获取当前的主键
  180. for(var i = ; i < this.dataList.length; i++) {
  181. if(this.dataList[i][keyColumn] === key) {//this.dataList绑定的是vue实例的people对象
  182. return this.dataList[i]
  183. }
  184. }
  185. },
  186. //判断新增的item是否已经存在
  187. itemExists: function() {
  188. var keyColumn = this.keyColumn;//获取主键列
  189. for(var i = ; i < this.dataList.length; i++) {
  190. //判断当前数据的主键列值是否已经在dataList里面存在
  191. if(this.item[keyColumn] === this.dataList[i][keyColumn]){
  192. return true;
  193. }
  194. }
  195. return false;
  196. },
  197. //新建
  198. createItem: function() {
  199. var keyColumn = this.keyColumn;
  200. if(!this.itemExists()) {
  201. // 将item追加到dataList
  202. this.dataList.push(this.item);
  203. // 广播事件,传入参数false表示隐藏对话框
  204. this.$broadcast('showDialog', false)
  205. // 新建完数据后,重置item对象
  206. this.item = {};
  207. } else {
  208. alert(keyColumn + ' "' + this.item[keyColumn] + '" is already exists');
  209. }
  210. },
  211. //编辑
  212. updateItem: function() {
  213. // 获取主键列
  214. var keyColumn = this.keyColumn;
  215. for(var i = ; i < this.dataList.length; i++) {
  216. // 根据主键查找要修改的数据,然后将this.item数据更新到this.dataList[i]
  217. if(this.dataList[i][keyColumn] === this.item[keyColumn]) {
  218. //如果主键的值相同,就把当前item里的值赋值给dataList
  219. for(var j in this.item) {
  220. this.dataList[i][j] = this.item[j];
  221. }
  222. break;
  223. }
  224. }
  225. // 广播事件,传入参数false表示隐藏对话框
  226. this.$broadcast('showDialog', false);
  227. // 修改完数据后,重置item对象
  228. this.item = {};
  229. },
  230. //删除
  231. deleteItem: function(entry) {
  232. var data = this.dataList;//获取当前dataList数据
  233. data.forEach(function(item, i) {
  234. if(item === entry) {
  235. data.splice(i, );
  236. return;
  237. }
  238. })
  239. }
  240. },
  241. //局部注册子组件modal-dialog
  242. components: {
  243. 'modal-dialog': {
  244. template: '#dialog-template',
  245. data: function() {
  246. return {
  247. show: false // 对话框默认是不显示的
  248. }
  249. },
  250. /* 与父组件里面对应的数据:
  251. * mode = 1是新增数据模式,mode = 2是修改数据模式
  252. * title表示对话框的标题内容
  253. * fields表示对话框要显示的数据字段数组
  254. * item是由simple-dialog传下来,用于绑定表单字段的
  255. */
  256. props: ['mode', 'title', 'fields', 'item'],
  257. methods: {
  258. //关闭
  259. close: function() {
  260. this.show = false;//让子组件隐藏
  261. },
  262. //保存
  263. save: function() {
  264. //如果是新增或编辑,就向父组件发派生事件
  265. if(this.mode === ) {
  266. // 使用$dispatch调用simple-grid的create-item事件
  267. this.$dispatch('create-item');
  268. } else if(this.mode === ) {
  269. // 使用$dispatch调用simple-grid的update-item事件
  270. this.$dispatch('update-item');
  271. }
  272. }
  273. },
  274. events: {
  275. 'showDialog': function(show) {//show接受父组件传来的参数,决定是显示还是隐藏对话框
  276. this.show = show;
  277. }
  278. }
  279. }
  280. }
  281. })
  282.  
  283. var demo = new Vue({
  284. el: '#app',
  285. data: {
  286. searchQuery: '',
  287. columns: [{
  288. name: 'name',
  289. isKey: true
  290. }, {
  291. name: 'age'
  292. }, {
  293. name: 'sex',
  294. dataSource: ['Male', 'Female']
  295. }],
  296. people: [{
  297. name: 'Jack',
  298. age: ,
  299. sex: 'Male'
  300. }, {
  301. name: 'Bill',
  302. age: ,
  303. sex: 'Male'
  304. }, {
  305. name: 'Tracy',
  306. age: ,
  307. sex: 'Female'
  308. }, {
  309. name: 'Chris',
  310. age: ,
  311. sex: 'Male'
  312. }]
  313. }
  314. })
  315. </script>
  316. </body>
  317. </html>

  css文件:

  1. * {
  2. margin: ;
  3. padding: ;
  4. box-sizing: border-box;
  5. font-family: Helvetica, simhei, Arial, sans-serif;
  6. }
  7.  
  8. html {
  9. font-size: 1rem;
  10. }
  11.  
  12. body{
  13. margin-top: 100px;
  14. }
  15.  
  16. table,
  17. td,
  18. th {
  19. border-collapse: collapse;
  20. border-spacing:
  21. }
  22.  
  23. table {
  24. width: %;
  25. }
  26.  
  27. td,
  28. th {
  29. border: 1px solid #bcbcbc;
  30. padding: 5px 10px;
  31. }
  32.  
  33. th {
  34. padding: 10px;
  35. font-weight: ;
  36. color: #fff;
  37. background: #0090d3;
  38. cursor: pointer;
  39. }
  40.  
  41. tr:nth-of-type(odd) {
  42. background: #fff
  43. }
  44.  
  45. tr:nth-of-type(even) {
  46. background: #eee
  47. }
  48.  
  49. h1{
  50. font-size: .5rem;
  51. margin-bottom: 2rem;
  52. }
  53.  
  54. input {
  55. outline: none
  56. }
  57.  
  58. input[type=text] {
  59. padding: 3px 6px;
  60. font-size: .2rem;
  61. border: 1px solid #ccc;
  62. }
  63.  
  64. input[type=text]:focus {
  65. border-color: #0090d3;
  66. transition: .3s ease-in;
  67. }
  68.  
  69. button {
  70. display: inline-block;
  71. box-sizing: border-box;
  72. padding: 10px 30px;
  73. background: #0090d3;
  74. color: #fff;
  75. border: 1px solid #0090d3;
  76. border-radius: 3px;
  77. outline: ;
  78.  
  79. transition: .4s ease-out;
  80. }
  81.  
  82. button:hover,
  83. button:focus {
  84. opacity: 0.8;
  85. cursor: pointer;
  86. transition: .15s ease-in;
  87. }
  88.  
  89. #app {
  90. margin: auto;
  91. max-width: 640px;
  92. }
  93.  
  94. .btn-danger{
  95. padding: 5px 15px;
  96. border: 1px solid salmon;
  97. background: salmon;
  98. }
  99.  
  100. .btn-save{
  101. border: 1px solid #0090d3;
  102. background: #0090d3;
  103. }
  104.  
  105. .btn-close{
  106. border: 1px solid #ccc;
  107. background: #ccc;
  108. }
  109.  
  110. .container {
  111. padding-left: 15px;
  112. padding-right: 15px;
  113. margin: 10px;
  114. }
  115.  
  116. .search-input {
  117. width: %;
  118. }
  119.  
  120. .form-group {
  121. margin: 10px;
  122. }
  123.  
  124. .form-group > label {
  125. display: inline-block;
  126. padding-right: 1rem;
  127. width: 5rem;
  128. text-align: right;
  129. }
  130.  
  131. .form-group > input,
  132. .form-group > select {
  133. display: inline-block;
  134. height: .8rem;
  135. line-height: .8rem;
  136. }
  137.  
  138. .text-center {
  139. text-align: center;
  140. }
  141.  
  142. .dialog {
  143. width: 480px;
  144. position: fixed;
  145. left: %;
  146. top: 2em;
  147. transform: translateX(-%);
  148. z-index: ;
  149. visibility: hidden;
  150. backface-visibility: hidden;
  151. perspective: 1300px;
  152. }
  153.  
  154. .dialog-active {
  155. visibility: visible;
  156. }
  157.  
  158. .dialog-active .dialog-content {
  159. opacity: ;
  160. transform: rotateY();
  161. }
  162.  
  163. .dialog-active ~ .dialog-overlay {
  164. opacity: ;
  165. visibility: visible;
  166. }
  167.  
  168. .dialog-content {
  169. border-radius: 3px;
  170. background: #fff;
  171. overflow: hidden;
  172. box-shadow: 10px 20px rgba(, , , 0.1);
  173. transition: .5s ease-in-out;
  174. opacity: ;
  175. transform-style: preserve-3d;
  176. transform: rotateY(-70deg);
  177. }
  178.  
  179. .dialog-header {
  180. background: #0090d3;
  181. color: #fff;
  182. }
  183.  
  184. .dialog-title {
  185. margin: ;
  186. font-size: 2em;
  187. text-align: center;
  188. font-weight: ;
  189. line-height: 2em;
  190. }
  191.  
  192. .dialog-body {
  193. padding: 2em;
  194. }
  195.  
  196. .dialog-footer {
  197. margin: 2em;
  198. padding: 1em ;
  199. border-top: 1px solid rgba(, , , 0.1);
  200. }
  201.  
  202. .dialog-overlay {
  203. content: "";
  204. position: fixed;
  205. visibility: hidden;
  206. top: ;
  207. left: ;
  208. right: ;
  209. bottom: ;
  210. z-index: ;
  211. opacity: ;
  212. background: rgba(, , , 0.5);
  213. transition: all .6s;
  214. }

Vue组件开发实例(详细注释)的更多相关文章

  1. vue前端开发那些事——vue组件开发

    vue的学习曲线不是很陡(相比其它框架,如anglarjs),官方文档比较全面,分为基础篇和高级篇.我们刚开始学习的时候,肯定像引用jquery那样,先把vue的js引进来,然后学习基础内容.如果仅仅 ...

  2. Vue组件开发分享

    在开始本文之前,你可能需要先了解以下相关内容: Vue.js  一款高性能轻量化的MVVM框架 Webpack  前端模块化代码构建工具 Vue组件介绍 基于vue.js高效的双向数据绑定特性,让我们 ...

  3. Vue (三) --- Vue 组件开发

    ------------------------------------------------------------------好心情,会让你峰回路转. 5. 组件化开发 5.1 组件[compo ...

  4. vue 组件开发、vue自动化工具、axios使用与router的使用(3)

    一. 组件化开发 1.1 组件[component] 在网页中实现一个功能,需要使用html定义功能的内容结构,使用css声明功能的外观样式,还要使用js定义功能的特效,因此就产生了一个功能先关的代码 ...

  5. 三: vue组件开发及自动化工具vue-cli

    一: 组件化开发 1 组件 1: 组件(Component)是自定义封装的功能.在前端开发过程中,经常出现多个网页的功能是重复的,而且很多不同的网站之间,也存在同样的功能. 2: 什么是组件 而在网页 ...

  6. vue 开发系列(三) vue 组件开发

    概要 vue 的一个特点是进行组件开发,组件的优势是我们可以封装自己的控件,实现重用,比如我们在平台中封装了自己的附件控件,输入控件等. 组件的开发 在vue 中一个组件,就是一个独立的.vue 文件 ...

  7. Vue组件开发实践之scopedSlot的传递

    收录待用,修改转载已取得腾讯云授权 导语 现今的前端开发都讲究模块化组件化,即把公共的交互和功能封装到一个个的组件之中,在开发整体界面的时候就能像搭积木一样快速清晰高效.在使用Vue开发我们的vhtm ...

  8. vue组件开发练习--焦点图切换

    1.前言 vue用了有一段时间了,开发的后台管理系统也趋于完善,现在时间比较算是有点空闲吧!这个空闲时间我在研究vue的另外的一些玩法,比如组件,插件等.今天,我就分享一个组件的练手项目--焦点图切换 ...

  9. Vue 组件开发demo

    1.代码地址 github:https://github.com/MengFangui/VueComponentDemo- 2.关键代码 (1)main.js //引入vue import Vue f ...

随机推荐

  1. Linux : select()详解 和 实现原理【转】

    转自:http://blog.csdn.net/huntinux/article/details/39289317 原文:http://blog.csdn.net/boboiask/article/d ...

  2. pool.map的第二个参数想传入多个咋整?

    from functools import partial from multiprocessing import Pool as ThreadPool pageurls=[] if maxpage: ...

  3. iOS设计模式 —— KVC

    刨根问底KVC KVC 全称 key valued coding 键值编码 反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性 ...

  4. SQL--面试题

    表A字段如下 month  name income 月份   人员 收入 1      a    1000 2      a    2000 3      a    3000要求用一个SQL语句(注意 ...

  5. CentOS7配置阿里云yum源和EPEL源

    配置阿里云yum源(参考:http://mirrors.aliyun.com/help/centos) 1.备份 [root@bogon ~]# cd /etc/yum.repos.d/ [root@ ...

  6. css深入理解之border

    1.  border-width border-width不支持百分比,类似的还有outline,box-shadow,text-shadow等 border-width支持关键字:thin(1px, ...

  7. Ajaxterm + nginx 实现一个简单的堡垒机

    https://blog.csdn.net/zhang19771105/article/details/50497581 http://wuliangxx.iteye.com/blog/600113

  8. php获取rl完整地址

    /** * 获取url完整地址 * @author 梁景 * @date 2017-04-27 * @return */ function getUrlInfor() { $sys_protocal ...

  9. Git命令使用指南

    继续git相关的东西,网上很多讲解的,但是还是喜欢这个图:(爱屋及乌,当然内容也很好,文章链接:http://me.iblogc.com/2015/01/16/Git命令使用指南/) Git是软件开发 ...

  10. lca最短公共祖先模板(hdu2586)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586 #include<iostream> #include<cstdio> ...