Vue组件开发实例(详细注释)
Vue组件开发实例:
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="UTF-8">
- <title></title>
- <link rel="stylesheet" href="SJStyle.css" />
- <style>
- /*
- * 由于IE不支持<template>标签,所以template标签中的内容在IE下会直接显示出来。
- * 将模板设为隐藏即可解决这个问题,template标签各浏览器支持请参考:http://caniuse.com/#feat=template
- */
- #grid-template,
- #dialog-template {
- display: none;
- }
- </style>
- </head>
- <body>
- <div id="app">
- <!-- 上部查询框:通过searchQuery过滤 -->
- <div class="container">
- <div class="form-group">
- <label>Search</label>
- <input type="text" class="search-input" v-model="searchQuery" />
- </div>
- </div>
- <!-- 下部表格框 -->
- <div class="container">
- <simple-grid :data-list="people" :columns="columns" :search-key="searchQuery">
- </simple-grid>
- </div>
- </div>
- <!-- 父组件simple-grid -->
- <template id="grid-template">
- <table>
- <!-- 表头,从columns里面取数据 -->
- <thead>
- <tr>
- <th v-for="col in columns">
- {{ col.name | capitalize}}
- </th>
- <th>Delete</th>
- </tr>
- </thead>
- <!-- 表体,从people绑定的dataList里面取数据 -->
- <tbody>
- <!-- 这里有个filterBy过滤器的使用 -->
- <tr v-for="(index,entry) in dataList | filterBy searchKey">
- <!-- 从columns里面取数据,判断是否有主键,有主键就显示编辑信息;没有就直接显示 -->
- <!-- 此处注意正好columns里的属性的值col.name,正好要是dataList里的entry的key,所以通过entry[col.name]去获取值 -->
- <td v-for="col in columns">
- <span v-if="col.isKey"><a href="javascript:void(0)" @click="openEditItemDialog(entry[col.name])">{{entry[col.name]}}</a></span>
- <span v-else>{{entry[col.name]}}</span>
- </td>
- <!-- 删除的操作按钮,传了整条数据的信息作为参数 -->
- <td class="text-center">
- <button class="btn-danger" @click="deleteItem(entry)">delete</button>
- </td>
- </tr>
- </tbody>
- </table>
- <!-- 新建操作按钮,传了标题作为参数 -->
- <div class="container">
- <button class="btn" @click="openNewItemDialog('Create New Item')">Create</button>
- </div>
- <!-- 此处就是通过props指定父子组件通信的东西,就是让父组件的内容和子组件的内容对应 -->
- <modal-dialog :mode="mode" :title="title" :item="item" :fields="columns" v-on:create-item="createItem" v-on:update-item="updateItem">
- </modal-dialog>
- </template>
- <!-- 子组件modal-dialog -->
- <template id="dialog-template">
- <div class="dialogs">
- <!-- v-bind:class通过show的值去判断是否新增class名,所以我们通过控制这个show值来达到显示和隐藏子组件的目的 -->
- <div class="dialog" v-bind:class="{ 'dialog-active': show }">
- <div class="dialog-content">
- <header class="dialog-header">
- <h1 class="dialog-title">{{ title }}</h1>
- </header>
- <div class="dialog-body">
- <!-- 通过遍历fields里的值,来加整个div -->
- <div v-for="field in fields" class="form-group">
- <label>{{ field.name }}</label>
- <!-- 如果column有dataSource属性就显示下拉列表 -->
- <!-- 如果是编辑模式,并且有主键属性,就禁用 -->
- <select v-if="field.dataSource" v-model="item[field.name]" :disabled="mode === 2 && field.isKey">
- <!-- 遍历column里的dataSource属性的值 -->
- <option v-for="opt in field.dataSource" :value="opt">{{ opt }}</option>
- </select>
- <!-- 如果没有dataSource属性,就显示文本框 -->
- <input v-else type="text" v-model="item[field.name]" :disabled="mode === 2 && field.isKey">
- </div>
- </div>
- <footer class="dialog-footer">
- <div class="form-group">
- <label></label>
- <button class="btn-save" v-on:click="save">Save</button>
- <button class="btn-close" v-on:click="close">Close</button>
- </div>
- </footer>
- </div>
- </div>
- <div class="dialog-overlay"></div>
- </div>
- </template>
- <script src="vue.js"></script>
- <script>
- //注册父组件simple-grid
- Vue.component('simple-grid', {
- template: '#grid-template',
- //父组件其实也就是vue实例的子组件,所以也要通过props去与vue实例里的数据进行对应绑定:这里dataList绑定people,columns绑定columns,searchKey绑定searchQuery
- props: ['dataList', 'columns', 'searchKey'],
- //定义父组件里的数据
- data: function() {
- return {
- mode: ,
- title: '',
- keyColumn: '',
- item: {}
- }
- },
- //通过钩子函数去设定name为主键,并赋值给keyColumn,就是this.keyColumn就是获取到主键"name"
- ready: function() {
- for(var i = ; i < this.columns.length; i++) {
- if(this.columns[i].isKey) {
- this.keyColumn = this.columns[i]['name']
- break;
- }
- }
- },
- methods: {
- //点击新建按钮,弹出子组件
- openNewItemDialog: function(title) {
- // 对话框的标题
- this.title = title
- // mode = 1表示新建模式
- this.mode =
- // 初始化this.item
- this.item = {}
- // 广播事件,showDialog是modal-dialog组件的一个方法,传入参数true表示显示对话框
- this.$broadcast('showDialog', true)
- },
- //点击编辑弹出子组件
- openEditItemDialog: function(key) {
- // 根据主键查找当前修改的数据
- var currentItem = this.findItemByKey(key);//key就是传过来的name参数
- // 修改对话框的标题
- this.title = 'Edit Item - ' + key;
- // mode = 2表示修改模式
- this.mode = ;
- // 将选中的数据拷贝到this.item
- this.item = this.initItemForUpdate(currentItem);
- // 父组件让子组件显示:广播事件,传入参数true表示显示对话框
- this.$broadcast('showDialog', true);
- },
- // 就是一个深拷贝函数:弹出修改数据的对话框时,使用对象的深拷贝
- initItemForUpdate(p, c) {
- c = c || {};
- for(var i in p) {
- // 属性i是否为p对象的自有属性
- if(p.hasOwnProperty(i)) {
- // 属性i是否为复杂类型
- if(typeof p[i] === 'object') {
- // 如果p[i]是数组,则创建一个新数组
- // 如果p[i]是普通对象,则创建一个新对象
- c[i] = Array.isArray(p[i]) ? [] : {};
- // 递归拷贝复杂类型的属性
- this.initItemForUpdate(p[i], c[i]);
- } else {
- // 属性是基础类型时,直接拷贝
- c[i] = p[i];
- }
- }
- }
- return c;
- },
- //该函数的作用就是通过传过来的name,查找返回那条数据
- findItemByKey: function(key) {
- var keyColumn = this.keyColumn;//获取当前的主键
- for(var i = ; i < this.dataList.length; i++) {
- if(this.dataList[i][keyColumn] === key) {//this.dataList绑定的是vue实例的people对象
- return this.dataList[i]
- }
- }
- },
- //判断新增的item是否已经存在
- itemExists: function() {
- var keyColumn = this.keyColumn;//获取主键列
- for(var i = ; i < this.dataList.length; i++) {
- //判断当前数据的主键列值是否已经在dataList里面存在
- if(this.item[keyColumn] === this.dataList[i][keyColumn]){
- return true;
- }
- }
- return false;
- },
- //新建
- createItem: function() {
- var keyColumn = this.keyColumn;
- if(!this.itemExists()) {
- // 将item追加到dataList
- this.dataList.push(this.item);
- // 广播事件,传入参数false表示隐藏对话框
- this.$broadcast('showDialog', false)
- // 新建完数据后,重置item对象
- this.item = {};
- } else {
- alert(keyColumn + ' "' + this.item[keyColumn] + '" is already exists');
- }
- },
- //编辑
- updateItem: function() {
- // 获取主键列
- var keyColumn = this.keyColumn;
- for(var i = ; i < this.dataList.length; i++) {
- // 根据主键查找要修改的数据,然后将this.item数据更新到this.dataList[i]
- if(this.dataList[i][keyColumn] === this.item[keyColumn]) {
- //如果主键的值相同,就把当前item里的值赋值给dataList
- for(var j in this.item) {
- this.dataList[i][j] = this.item[j];
- }
- break;
- }
- }
- // 广播事件,传入参数false表示隐藏对话框
- this.$broadcast('showDialog', false);
- // 修改完数据后,重置item对象
- this.item = {};
- },
- //删除
- deleteItem: function(entry) {
- var data = this.dataList;//获取当前dataList数据
- data.forEach(function(item, i) {
- if(item === entry) {
- data.splice(i, );
- return;
- }
- })
- }
- },
- //局部注册子组件modal-dialog
- components: {
- 'modal-dialog': {
- template: '#dialog-template',
- data: function() {
- return {
- show: false // 对话框默认是不显示的
- }
- },
- /* 与父组件里面对应的数据:
- * mode = 1是新增数据模式,mode = 2是修改数据模式
- * title表示对话框的标题内容
- * fields表示对话框要显示的数据字段数组
- * item是由simple-dialog传下来,用于绑定表单字段的
- */
- props: ['mode', 'title', 'fields', 'item'],
- methods: {
- //关闭
- close: function() {
- this.show = false;//让子组件隐藏
- },
- //保存
- save: function() {
- //如果是新增或编辑,就向父组件发派生事件
- if(this.mode === ) {
- // 使用$dispatch调用simple-grid的create-item事件
- this.$dispatch('create-item');
- } else if(this.mode === ) {
- // 使用$dispatch调用simple-grid的update-item事件
- this.$dispatch('update-item');
- }
- }
- },
- events: {
- 'showDialog': function(show) {//show接受父组件传来的参数,决定是显示还是隐藏对话框
- this.show = show;
- }
- }
- }
- }
- })
- var demo = new Vue({
- el: '#app',
- data: {
- searchQuery: '',
- columns: [{
- name: 'name',
- isKey: true
- }, {
- name: 'age'
- }, {
- name: 'sex',
- dataSource: ['Male', 'Female']
- }],
- people: [{
- name: 'Jack',
- age: ,
- sex: 'Male'
- }, {
- name: 'Bill',
- age: ,
- sex: 'Male'
- }, {
- name: 'Tracy',
- age: ,
- sex: 'Female'
- }, {
- name: 'Chris',
- age: ,
- sex: 'Male'
- }]
- }
- })
- </script>
- </body>
- </html>
css文件:
- * {
- margin: ;
- padding: ;
- box-sizing: border-box;
- font-family: Helvetica, simhei, Arial, sans-serif;
- }
- html {
- font-size: 1rem;
- }
- body{
- margin-top: 100px;
- }
- table,
- td,
- th {
- border-collapse: collapse;
- border-spacing:
- }
- table {
- width: %;
- }
- td,
- th {
- border: 1px solid #bcbcbc;
- padding: 5px 10px;
- }
- th {
- padding: 10px;
- font-weight: ;
- color: #fff;
- background: #0090d3;
- cursor: pointer;
- }
- tr:nth-of-type(odd) {
- background: #fff
- }
- tr:nth-of-type(even) {
- background: #eee
- }
- h1{
- font-size: .5rem;
- margin-bottom: 2rem;
- }
- input {
- outline: none
- }
- input[type=text] {
- padding: 3px 6px;
- font-size: .2rem;
- border: 1px solid #ccc;
- }
- input[type=text]:focus {
- border-color: #0090d3;
- transition: .3s ease-in;
- }
- button {
- display: inline-block;
- box-sizing: border-box;
- padding: 10px 30px;
- background: #0090d3;
- color: #fff;
- border: 1px solid #0090d3;
- border-radius: 3px;
- outline: ;
- transition: .4s ease-out;
- }
- button:hover,
- button:focus {
- opacity: 0.8;
- cursor: pointer;
- transition: .15s ease-in;
- }
- #app {
- margin: auto;
- max-width: 640px;
- }
- .btn-danger{
- padding: 5px 15px;
- border: 1px solid salmon;
- background: salmon;
- }
- .btn-save{
- border: 1px solid #0090d3;
- background: #0090d3;
- }
- .btn-close{
- border: 1px solid #ccc;
- background: #ccc;
- }
- .container {
- padding-left: 15px;
- padding-right: 15px;
- margin: 10px;
- }
- .search-input {
- width: %;
- }
- .form-group {
- margin: 10px;
- }
- .form-group > label {
- display: inline-block;
- padding-right: 1rem;
- width: 5rem;
- text-align: right;
- }
- .form-group > input,
- .form-group > select {
- display: inline-block;
- height: .8rem;
- line-height: .8rem;
- }
- .text-center {
- text-align: center;
- }
- .dialog {
- width: 480px;
- position: fixed;
- left: %;
- top: 2em;
- transform: translateX(-%);
- z-index: ;
- visibility: hidden;
- backface-visibility: hidden;
- perspective: 1300px;
- }
- .dialog-active {
- visibility: visible;
- }
- .dialog-active .dialog-content {
- opacity: ;
- transform: rotateY();
- }
- .dialog-active ~ .dialog-overlay {
- opacity: ;
- visibility: visible;
- }
- .dialog-content {
- border-radius: 3px;
- background: #fff;
- overflow: hidden;
- box-shadow: 10px 20px rgba(, , , 0.1);
- transition: .5s ease-in-out;
- opacity: ;
- transform-style: preserve-3d;
- transform: rotateY(-70deg);
- }
- .dialog-header {
- background: #0090d3;
- color: #fff;
- }
- .dialog-title {
- margin: ;
- font-size: 2em;
- text-align: center;
- font-weight: ;
- line-height: 2em;
- }
- .dialog-body {
- padding: 2em;
- }
- .dialog-footer {
- margin: 2em;
- padding: 1em ;
- border-top: 1px solid rgba(, , , 0.1);
- }
- .dialog-overlay {
- content: "";
- position: fixed;
- visibility: hidden;
- top: ;
- left: ;
- right: ;
- bottom: ;
- z-index: ;
- opacity: ;
- background: rgba(, , , 0.5);
- transition: all .6s;
- }
Vue组件开发实例(详细注释)的更多相关文章
- vue前端开发那些事——vue组件开发
vue的学习曲线不是很陡(相比其它框架,如anglarjs),官方文档比较全面,分为基础篇和高级篇.我们刚开始学习的时候,肯定像引用jquery那样,先把vue的js引进来,然后学习基础内容.如果仅仅 ...
- Vue组件开发分享
在开始本文之前,你可能需要先了解以下相关内容: Vue.js 一款高性能轻量化的MVVM框架 Webpack 前端模块化代码构建工具 Vue组件介绍 基于vue.js高效的双向数据绑定特性,让我们 ...
- Vue (三) --- Vue 组件开发
------------------------------------------------------------------好心情,会让你峰回路转. 5. 组件化开发 5.1 组件[compo ...
- vue 组件开发、vue自动化工具、axios使用与router的使用(3)
一. 组件化开发 1.1 组件[component] 在网页中实现一个功能,需要使用html定义功能的内容结构,使用css声明功能的外观样式,还要使用js定义功能的特效,因此就产生了一个功能先关的代码 ...
- 三: vue组件开发及自动化工具vue-cli
一: 组件化开发 1 组件 1: 组件(Component)是自定义封装的功能.在前端开发过程中,经常出现多个网页的功能是重复的,而且很多不同的网站之间,也存在同样的功能. 2: 什么是组件 而在网页 ...
- vue 开发系列(三) vue 组件开发
概要 vue 的一个特点是进行组件开发,组件的优势是我们可以封装自己的控件,实现重用,比如我们在平台中封装了自己的附件控件,输入控件等. 组件的开发 在vue 中一个组件,就是一个独立的.vue 文件 ...
- Vue组件开发实践之scopedSlot的传递
收录待用,修改转载已取得腾讯云授权 导语 现今的前端开发都讲究模块化组件化,即把公共的交互和功能封装到一个个的组件之中,在开发整体界面的时候就能像搭积木一样快速清晰高效.在使用Vue开发我们的vhtm ...
- vue组件开发练习--焦点图切换
1.前言 vue用了有一段时间了,开发的后台管理系统也趋于完善,现在时间比较算是有点空闲吧!这个空闲时间我在研究vue的另外的一些玩法,比如组件,插件等.今天,我就分享一个组件的练手项目--焦点图切换 ...
- Vue 组件开发demo
1.代码地址 github:https://github.com/MengFangui/VueComponentDemo- 2.关键代码 (1)main.js //引入vue import Vue f ...
随机推荐
- Linux : select()详解 和 实现原理【转】
转自:http://blog.csdn.net/huntinux/article/details/39289317 原文:http://blog.csdn.net/boboiask/article/d ...
- pool.map的第二个参数想传入多个咋整?
from functools import partial from multiprocessing import Pool as ThreadPool pageurls=[] if maxpage: ...
- iOS设计模式 —— KVC
刨根问底KVC KVC 全称 key valued coding 键值编码 反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性 ...
- SQL--面试题
表A字段如下 month name income 月份 人员 收入 1 a 1000 2 a 2000 3 a 3000要求用一个SQL语句(注意 ...
- CentOS7配置阿里云yum源和EPEL源
配置阿里云yum源(参考:http://mirrors.aliyun.com/help/centos) 1.备份 [root@bogon ~]# cd /etc/yum.repos.d/ [root@ ...
- css深入理解之border
1. border-width border-width不支持百分比,类似的还有outline,box-shadow,text-shadow等 border-width支持关键字:thin(1px, ...
- Ajaxterm + nginx 实现一个简单的堡垒机
https://blog.csdn.net/zhang19771105/article/details/50497581 http://wuliangxx.iteye.com/blog/600113
- php获取rl完整地址
/** * 获取url完整地址 * @author 梁景 * @date 2017-04-27 * @return */ function getUrlInfor() { $sys_protocal ...
- Git命令使用指南
继续git相关的东西,网上很多讲解的,但是还是喜欢这个图:(爱屋及乌,当然内容也很好,文章链接:http://me.iblogc.com/2015/01/16/Git命令使用指南/) Git是软件开发 ...
- lca最短公共祖先模板(hdu2586)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586 #include<iostream> #include<cstdio> ...