vue结合element ui CDN踩坑

2019.9.18,个人对element ui 的踩坑经验

安装下载

搭建环境:vue.js+element ui+axios.min.js+xlsx.full.min.js
构建工具:HBuilderX+chrome

下载地址:element ui

1.登录界面

编写后台登录界面
HTML代码如下:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title></title>
		<!-- elementUI——css cdn -->
		<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
		<!-- login.css -->
		<link rel="stylesheet" href="css/login.css" />
	</head>
	<body>
		<div id="app" v-cloak>
			<el-container direction='vertical'>
				<!-- 登录内容容器 -->
				<el-main>
					<div class="login-div">
						<h4>XXX医院管理系统</h4>
						<div class="register">
							<span>登录</span>
							<!-- <a href="#">还没有账号,立即注册</a> -->
						</div>
						<!-- 登录表单 -->
						<el-form ref="form" :model='form' v-show='formCode1'>
							<el-form-item>
								<el-input v-model='form.name' :placeholder='placeholdermsg'
								prefix-icon="el-icon-user-solid"
								></el-input>
							</el-form-item>
							<el-form-item v-show='passshow'>
								<el-input type='password' v-model='form.password' placeholder='请输入密码'
								prefix-icon="el-icon-s-goods"
								></el-input>
							</el-form-item>
							<el-form-item v-show='show'>
								<el-input v-model='form.code' style='width: 228px;' placeholder='请输入手机验证码'
								prefix-icon="el-icon-phone"
								></el-input>
								<!-- 验证码  -->
								<el-button type='primary' round @click='send' :disabled='isdisabled'>{{codemsg}}</el-button>
							</el-form-item>
							<el-form-item class='form4'>
								<el-switch v-model='form.verify' id='mima' @change='remenber(form.verify)'></el-switch><label for='mima'>记住密码</label>
								<a href="#" @click.prevent="wangji">忘记密码?</a>
							</el-form-item>
							<el-form-item>
								<el-button type="primary" @click="submitForm(form)" style='margin-left: 155px;'>登录</el-button>
								<el-button @click="resetForm(form)">重置</el-button>
							</el-form-item>
						</el-form>
						<!-- 验证手机验证码 -->
						<el-form ref="forget1" :model='forget1' v-show='formCode2'>
							<el-form-item>
								<el-input v-model='forget1.name'  placeholder='请输入手机号'
								prefix-icon="el-icon-phone"></el-input>
							</el-form-item>
							<el-form-item>
								<el-input v-model='forget1.code' style='width: 228px;' placeholder='请输入手机验证码'
								prefix-icon="el-icon-s-goods"
								></el-input>
								<el-button type='primary' round @click='send' :disabled='isdisabled'>{{codemsg}}</el-button>
							</el-form-item>
							<el-form-item>
								<el-button @click="last">上一步</el-button>
								<el-button @click="next(forget1)">下一步</el-button>
							</el-form-item>
							<el-form-item>
								
							</el-form-item>
						</el-form>
						<!-- 修改密码 -->
						<el-form ref="forget2" :model='forget2' v-show='formCode3'>
							<el-form-item>
								<el-input v-model='forget2.name' placeholder='请输入账号或手机号'
								prefix-icon="el-icon-phone"></el-input>
							</el-form-item>
							<el-form-item>
								<el-input v-model='forget2.password' placeholder='请输入密码'
								prefix-icon="el-icon-s-goods"></el-input>
							</el-form-item>
							<el-form-item>
								<el-input v-model='forget2.newpass' placeholder='请再次输入密码'
								prefix-icon="el-icon-s-goods"></el-input>
							</el-form-item>
							<el-form-item>
								<el-button @click="finish(forget2)">完成</el-button>
							</el-form-item>
						</el-form>
					</div>
				</el-main>
				<!-- 底部容器 -->
				<el-footer></el-footer>
			</el-container>
		</div>
	</body>
	<!-- vue CDN -->
	<script src="https://unpkg.com/vue/dist/vue.js"></script>
	<!-- 支持vue的elenemtUI封装js CDN -->
	<script src="https://unpkg.com/element-ui/lib/index.js"></script>
	<!-- axios AJAX库 -->
	<script src="https://cdn.bootcss.com/axios/0.19.0-beta.1/axios.min.js"></script>
	<!-- login.js -->
	<script src="js/login.js"></script>
</html>

这是HTML的代码,可以看得出来,写的不是很好,使用的element提供的组件进行开发,整体使用虚拟DOM 组件功能实现,从布局开始,使用标签
el-container这个标签定义 全局 盒子,然后看自己需要什么样的布局方式 ,可提供的有 el-header头部导航 ,el-main中部身体和el-aside左侧导航,跟el-footer尾部
布局
需要注意的是在Container 中 子元素中有 el-header 或 el-footer 时为 vertical,否则为 horizontal

body{
	margin: 0px;
	padding: 0px;
	background: ;
}
[v-cloak]{
	display: none;
}
.el-main{
	position: relative;
	top:150px;
}
.login-div{
	position: fixed;
	    top: 50%;
	    left: 50%;
	    width: 500px;
	    height: auto;
		border: 1px solid skyblue;
	    transform: translate(-50%,-50%);
	border-radius: 20px;
	box-shadow: 0 4px 4px rgba(0, 0, 0, .12), 0 0 6px rgba(0, 0, 0, .04);
}
.login-div  h4{
	text-align: center;
}
.register{
	width: 450px;
	height: 50px;
	margin: auto;
	text-align: center;
	color: brown;
	font-size: 20px;
}
.el-form{
	width: 450px;
	margin: auto;
}
.form4{
	color: #A52A2A;
	margin-left: 0px;
}
.form4 a{
	float: right;
	color: #A52A2A;
	text-decoration: none;
}

css样式 主要是对页面 效果做细节调整,虽然没怎么 调好,但是相信小编对div的窗口居中有问题,所以 记录 下来

position: fixed;
	    top: 50%;
	    left: 50%;
	    width: 500px;
	    height: auto;
		border: 1px solid skyblue;
	    transform: translate(-50%,-50%);

使用固定定位将这个div居中,当然这个只限于整个页面需要展示的只有登录才行,如果小范围div中元素居中就不行了

new Vue({
	el:"#app",
	data:{
		//登录表单
		form:{
			name:"",
			password:"",
			code:"",
			verify:false,
			numbers:0,
		},
		//忘记密码步骤一表格
		forget1:{
			name:"",
			code:""
		},
		//更改密码表单
		forget2:{
			name:"",
			password:"",
			newpass:""
		},
		//登录通过
		formCode1:true,
		//忘记密码验证
		formCode2:false,
		//重新设置密码
		formCode3:false,
		//提示语
		placeholdermsg:'请输入账号',
		//判断密码是否显示
		passshow:true,
		//判断次数
		count:0,
		//判断验证码是否显示
		show:false,
		//按钮信息
		codemsg:'发送手机验证码',
		//判断是否禁用按钮
		isdisabled:false,
		//短信按钮定时器
		timer:null,
		//cookie保存
		setCookie:(cname,cvalue,exdays)=>{
			var d = new Date();
			d.setTime(d.getTime()+(exdays*24*60*60*1000));
			var expires = "expires="+d.toGMTString();
			document.cookie = cname+"="+cvalue+"; "+expires;
		},
		//cookie查询
		getCookie:(cname)=>{
			var name = cname + "=";
			var ca = document.cookie.split(';');
			for(var i=0; i<ca.length; i++) {
				var c = ca[i].trim();
				if (c.indexOf(name)==0) { return c.substring(name.length,c.length); }
			}
			return "";
		},
	},
	methods:{
		//发送倒计时
		send(){
			let downTime=60;
			if(!this.timer){
				this.timer=setInterval(()=>{
					if(downTime>0 && downTime<=60){
						downTime--;
						if(downTime!==0){
							this.codemsg="重新发送("+downTime+")";
							this.isdisabled=true;
						}else{
							clearInterval(this.timer);
							this.codemsg="发送手机验证码";
							downTime=60;
							this.timer=null;
							this.isdisabled=false;
						}
					}
				},1000)
			}
		},
		//登录表单提交验证
		submitForm(form){
			let mima='123456';
			if(form.password===mima){
				this.setCookie('code',"",-1)
				/* 测试 */
				 this.$message('密码正确');
				 this.setCookie('name',this.form.name,6)
				 this.setCookie('pass',this.form.password,6)
				 window.location.href="backstage.html" 
			 
			}else{
				this.count++;
				this.$message('密码错误')
				this.setCookie('code',this.count,6)
			}
			let c = this.getCookie('code')
			if(c==3){
				this.$message('密码错误3次,请使用手机验证码登陆')
				this.placeholdermsg='请输入手机号'
				this.show=true;
				this.passshow=false
			}
		},
		//重置按钮
		resetForm(form) {
		    form.name=''
			form.password=''
			form.code=''
			form.verify=false
			this.setCookie('code',"",-1)
		},
		//记住密码
		remenber(isremenber){
			if(isremenber){
				this.setCookie('name',this.form.name,6)
				this.setCookie('pass',this.form.password,6)
			}
		},
		//忘记密码
		wangji(){
			this.formCode2=true
			this.formCode1=false
			this.formCode3=false
		},
		//忘记密码-验证手机验证码
		next(msg){
			// 验证码接口:通过:ajax
			//举例
			let data=1234
			if(msg.name==null||msg.name==""){
				this.$message('手机号码为空')
			}else if(msg.code==null||msg.code==""){
				this.$message('验证码为空')
			}else if(msg.code==data){
				this.formCode3=true
				this.formCode2=false
				this.formCode1=false
			}
			else{
				this.$message('验证码错误')
			}
		},
		last(){
			this.formCode3=false
			this.formCode2=false
			this.formCode1=true
		},
		//修改密码,成功后返回登录
		finish(msg){
			// let data=JSON.stringify(msg)
			// $.ajax({
			// 	url:"",
			// 	ContextType:{},
			// 	data{
			// 		数据
			// 	},
			// 	success
			// })
			//举例
			if(msg!=null){
				this.formCode3=false
				this.formCode2=false
				this.formCode1=true
			}
		}
	},
	//初始化判断cookie是否有内容,给出提示
	created:function(){
		//判断输入密码是否超过三次,改用手机号登录
		let c = this.getCookie('code')
		if(c>=3){
			this.show=true;
			this.passshow=false;
			this.count=c;
			this.placeholdermsg='请输入手机号';
		}
		//判断是否点击保存密码,直接将值赋予input
		let name=this.getCookie('name')
		let pass=this.getCookie('pass')
		if(name!=""&&pass!=""){
			this.form.verify=true
			this.form.name=name;
			this.form.password=pass;
		}else{
			this.form.verify=false
		}
	}
})

js采用纯粹的vue方式创建 ,其中涉及到 使用 cookie缓存的记住密码功能,手动编写即可
cooike
随后是关于忘记密码的发送定时器
忘记密码
这是登录页面的demo实现效果图
后台登录界面

没做太多效果 ,不过没关系,登录界面的主体功能都是有的,当然,没有注册,应该后台登录界面我的设想是后台用户管理中使用权限添加用户
,做完登录后感觉 有点重复造轮子了,很多功能组件可以写成一个个小的功能组件来做的

2.后台界面

后台界面这个我是使用的iframe来做路由的,算是路由吧…
那么废话不多说,上代码:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>后台管理</title>
		<!-- elementUI——css cdn -->
		<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
		<!-- backstage.css后台css表 -->
		<link rel="stylesheet" href="css/backstage.css" />
	</head>
	<body>
		<div id="app2">
			<!-- 最外层容器-横向 -->
			<el-container v-cloak  style='height: 770px;'>
				<!-- 左菜单 -->
			  <el-aside width="auto">
				  <el-menu default-active='2-1' class="el-menu-vertical-demo" :collapse='isCollapse'  @select="select">
				  	  <el-menu-item index="1">
				  	    <i class="el-icon-s-home"></i>
				  	    <a href="backstage.html" style="text-decoration: none;color: black;">
							<span slot="title">XXX医院后台管理系统</span>
						</a>
				  	  </el-menu-item>
					<el-submenu index='2'>
						<template slot='title'>
							<i class="el-icon-user"></i>
							<span slot="title">员工管理</span>
						</template>
						<el-menu-item-group>
							<span slot='title'>员工信息管理</span>
							<a href="people_management.html" class="jump_where" target='main'>
								<el-menu-item index="2-1">员工基本信息</el-menu-item>
							</a>
							<a href="" class="jump_where" target='main'>
								<el-menu-item index="2-2">员工权限</el-menu-item>
							</a>
						</el-menu-item-group>
					</el-submenu>
				  	<el-submenu index='3'>
				  		<template slot='title'>
				  			<i class="el-icon-s-custom"></i>
				  			<span slot="title">病人管理</span>
				  		</template>
				  		<el-menu-item-group>
				  			<span slot='title'>病人信息管理</span>
				  			<a href="Patient_Information.html" class="jump_where" target='main'>
								<el-menu-item index="3-1">病人基本信息</el-menu-item>
							</a>
				  			<el-menu-item index="3-2">病人离院审核</el-menu-item>
				  		</el-menu-item-group>
				  	</el-submenu>
					<el-submenu index='4'>
						<template slot='title'>
							<i class="el-icon-s-tools"></i>
							<span slot="title">系统管理</span>
						</template>
						<el-menu-item-group>
							<el-menu-item index="4-1">日志信息</el-menu-item>
							<el-menu-item index="4-2">背景颜色</el-menu-item>
						</el-menu-item-group>
					</el-submenu>
				  </el-menu>
			  </el-aside>
			  <!-- 第二个容器-竖向中部容器 -->
			  <el-container>
			    <!-- 头部 -->
			    <el-header style='background: #87CEEB;'>
			    	<el-row class='row-1'>
			    		<el-col :span='1'>
			    			<el-checkbox-group v-model="isCollapse" style="margin-top: 11px;">
			    			  <el-checkbox-button :label="isCollapse">
			    					  <i class="el-icon-s-grid"></i>	
			    			  </el-checkbox-button>
			    			</el-checkbox-group>
			    		</el-col>
			    		<el-col :span='12' style='line-height: 60px;'>
			    			 <el-autocomplete
			    			      v-model="state"
			    				  suffix-icon="el-icon-search"
			    			      :fetch-suggestions="querySearch"
			    			      placeholder="请输入内容"
			    				  @select="handleSelect"
			    				  style='float:right;'
			    			    >
			    				</el-autocomplete>
			    		</el-col>
			    		<el-col :span='11'>
			    			<!-- 头像 -->
			    			<el-dropdown style='float: right;' @command='selectdrop'>
			    				<span>
			    					<template>
			    						<div class="demo-type">
			    							<el-avatar icon="el-icon-user-solid"></el-avatar>
			    						</div>
			    					</template>
			    				</span>
			    				<el-dropdown-menu slot='dropdown'>
			    					<el-dropdown-item command='1'>消息通知</el-dropdown-item>
			    					<el-dropdown-item command='2'>个人中心</el-dropdown-item>
			    					<el-dropdown-item command='3'>系统设置</el-dropdown-item>
			    					<el-dropdown-item command='4'>退出登录</el-dropdown-item>
			    				</el-dropdown-menu>
			    			</el-dropdown>
			    		</el-col>
			    	</el-row>
			    </el-header>
			    <!-- 主体内容部分 -->
			    <el-main style='background:#E9E4EA;padding: 0px;'>
			    	<iframe id='uiui' src="people_management.html" name="main" width="99%" height="100%"></iframe>
			    </el-main>
			    <!-- 尾部 -->
			    <el-footer>
					请在此处放置备案
				</el-footer>
			  </el-container>
			</el-container>
		</div>
	</body>
	<!-- vue CDN -->
	<script src="https://unpkg.com/vue/dist/vue.js"></script>
	<!-- 支持vue的elenemtUI封装js CDN -->
	<script src="https://unpkg.com/element-ui/lib/index.js"></script>
	<!-- axios AJAX库 -->
	<script src="https://cdn.bootcss.com/axios/0.19.0-beta.1/axios.min.js"></script>
	<!-- backstage后台js -->
	<script src="js/backstage.js"></script>
</html>

后端HTML的鸡架子先给它搭好,这样就知道哪里放什么了 ,然后呢,我这里使用了element ui 提供的左侧导航栏可收缩样式,看起来会轻便一些,
输入框本来设想是做一个跳转的,发现没啥页面,就算了,但是依然保留
主要点还是在iframe的使用吧,记住使用时name很重要,它必须跟target标签一致,也就是说,如果你使用a标签跳转,a标签必须添加target属性并且与iframe的name属性一致,好了,看看css样式吧

body{
	margin: 0px;
	padding: 0px;
}
[v-cloak]{
	display: none;
}
.el-menu-vertical-demo{
	background: rgb(236,245,255);
}
.el-menu-vertical-demo:not(.el-menu--collapse) {
    width: 200px;
    height: 770px;
}
.demo-type{
	height: 60px;
	width: 40px;
}
.demo-type span{
	margin-top: 11px;
}
.jump_where{
	text-decoration: none;
}

从这以后,css就写的少了,主要做一些微调,其它不需要了
那么还是看看我们的js代码吧没啥可说的。

new Vue({
	el:'#app2',
	data:{
		//菜单缩放
		isCollapse:false,
		//header搜索
		state:'',
		//搜索下拉列表值
		restaurants:[],
		
	},
	methods:{
		//过滤筛选对应下拉列表值
		querySearch(queryString, cb) {
		        let restaurants = this.restaurants;
		        let results = queryString ? restaurants.filter(this.createFilter(queryString)) : restaurants;
		        // 调用 callback 返回建议列表的数据
		        cb(results);
				//查询跳转
				var newAll=this.loadAll();
				document.onkeydown=function(event){
					var e = event || window.event || arguments.callee.caller.arguments[0];
					if(e&&e.keyCode==13){
						var add=''
						newAll.filter((item)=>{
							if(item.value.indexOf(queryString)!=-1){
								add=item.address
							}
						});
						if(add!=null||add==""){
							if(add.indexOf(".html")!=-1){
								window.location.href=""+add
							}
						}
					}
				};
		      },
		//创建过滤器
		createFilter(queryString) {
		    return (restaurant) => {
		        return (restaurant.value.indexOf(queryString) === 0);
		    };
		},
		//点击列表跳转
		handleSelect(ev){
			console.log(ev.address)
			window.location.href=""+ev.address
		},
		//AJAX传入参数
		loadAll(){
			return [
				{"value": "三全鲜食(北新泾店)","address": "./login.html" },
				{"value": "Hot honey 首尔炸鸡(仙霞路)","address": "长宁区北新泾街道天山西路490-1号"},
				{"value": "新旺角茶餐厅"},
				{"value": "泷千家(天山西路店)"},
				{"value": "胖仙女纸杯蛋糕(上海凌空店)"},
				{"value": "贡茶"},
			];
		},
		//登录用户系图标下拉列表
		selectdrop(e){
			console.log(e)
		},
		//左边导航栏下拉列表
		select(e,a){
			console.log(e,a)
		},
	},
	//生命周期钩子方法加载页面传递数据到搜索框restaurants中
	mounted:function(){
		let el=document.querySelector('.el-menu')
		let ifarme=document.querySelector('#uiui')
		// console.log(ifarme.getAttribute('src'))
		console.log(el)
		this.restaurants=this.loadAll();
	}
})

好吧,感觉也没啥可说的,全是套用的element的组件,简直就是抄的,附上效果图吧,也让大家明白点
后台界面
当当当当,就是这么个效果,low吧,不过只要实现效果就好,毕竟是练习demo,接下来说一说关于这表格的页面把,其中涉及到axios异步读取json文件,接着是xlsx的导入导出功能实现,来看 代码 吧

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<!-- elementUI——css cdn -->
	<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
	<!-- 1.css后台css表 -->
	<link rel="stylesheet" href="css/people_management.css" />
	<body>
		<div id="app3" v-cloak>
			<el-container>
				<el-header>
					<div class="fun_group">
						<el-button plain icon='el-icon-upload el-icon--right' @click="uploadFile()">导入</el-button>
						<el-button plain icon='el-icon-download' @click="downloadFile(tableData)">下载</el-button>
						<el-button plain icon='el-icon-delete' @click="delBates(Selection)" :disabled='this.Selection.length===0'>批量删除</el-button>
						<el-button plain icon='el-icon-edit-outline' @click="isaddtab=true">添加数据</el-button>
					</div>
				</el-header>
				<el-main>
					<el-dialog title='添加数据' :visible.sync='isaddtab'>
						<div style="width: 250px;margin: auto;">
							<el-form :model='addform'>
								<el-form-item label='日期' prop='dateTime' label-width='40px'>
									<el-date-picker v-model="addform.dateTime" type="date" placeholder="选择日期"></el-date-picker>
								</el-form-item>
								<el-form-item  label='名字' prop='name' label-width='40px'>
									<el-input v-model='addform.name' placeholder='请输入名称' autocomplete="off"></el-input>
								</el-form-item>
								<el-form-item  label='地址' prop='address' label-width='40px'>
									<el-input v-model='addform.address' placeholder='地址到县级即可'></el-input>
								</el-form-item>
								<el-form-item>
									<el-button type='primary' @click="handleEditadd">确定</el-button>
									<el-button plain @click='isaddtab=false'>取消</el-button>
								</el-form-item>
							</el-form>
						</div>
					</el-dialog>
					<el-dialog title='更新数据' :visible.sync='isUpdata'>
						<div style="width: 250px;margin: auto;">
							<el-form :model='updata'>
								<el-form-item label='日期' prop='dateTime' label-width='40px'>
									<el-date-picker v-model="updata.dateTime" type="date" placeholder="选择日期"></el-date-picker>
								</el-form-item>
								<el-form-item  label='名字' prop='name' label-width='40px'>
									<el-input v-model='updata.name' placeholder='请输入名称' autocomplete="off"></el-input>
								</el-form-item>
								<el-form-item  label='地址' prop='address' label-width='40px'>
									<el-input v-model='updata.address' placeholder='地址到县级即可'></el-input>
								</el-form-item>
								<el-form-item>
									<el-button type='primary' @click="handleEditupdata">确定</el-button>
									<el-button plain @click='isUpdata=false'>取消</el-button>
								</el-form-item>
							</el-form>
						</div>
					</el-dialog>
						<div v-loading.fullscreen.lock='fullscreenLoading' element-loading-text='拼命加载中...'>
							<!-- 导入文件 -->
							<input type="file" @change="importFile(this)" id="imFile" style="display: none"
								accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel"/>
							<!-- 下载链接 -->
							<a id="downlink"></a>
						</div>
						<el-table :data='tableData' @selection-change='handleSelectionChange'>
							<el-table-column type="selection" width="55"></el-table-column>
							<el-table-column label='日期' prop='dateTime'></el-table-column>
							<el-table-column label='名字' prop='name'></el-table-column>
							<el-table-column label='地址' prop='address'></el-table-column>
							<el-table-column align="left" label='操作'>
								<template slot-scope="scope">
									<el-button
									  size="mini"
									  @click="handleEdit(scope.$index, scope.row)">更新</el-button>
									<el-button
									  size="mini"
									  type="danger"
									  @click.native.prevent="handleDelete(scope.$index, tableData)">删除</el-button>
								</template>
							</el-table-column>
						</el-table>
				</el-main>
			</el-container>
		</div>
	</body>
	<!-- vue CDN -->
	<script src="https://unpkg.com/vue/dist/vue.js"></script>
	<!-- 支持vue的elenemtUI封装js CDN -->
	<script src="https://unpkg.com/element-ui/lib/index.js"></script>
	<!-- axios AJAX库 -->
	<script src="https://cdn.bootcss.com/axios/0.19.0-beta.1/axios.min.js"></script>
	<!-- xlsx表格文件导入导出工具类 -->
	<script src="https://cdn.bootcss.com/xlsx/0.15.1/xlsx.full.min.js"></script>
	<!-- people_management.js -->
	<script src="js/people_management.js"></script>
</html>

HTML照搬一下即可实现一样的效果没啥可以说的,css也一样,根本就没有,那么 直接看js

new  Vue({
	el:'#app3',
	data:{
		//查询数据
		// search:"",
		fullscreenLoading: false,//加载
		imfile:'',//导入
		outfile:'',//导出
		//模拟数据
		tableData:[
			{'dateTime': '2016-05-02','name': '王小虎','address': '上海市普陀区金沙江路 1518 弄'}
		],
		//储存选中数据
		Selection:[],
		//添加数据对话框控件
		isaddtab:false,
		//添加数据form表单
		addform:{
			dateTime:'',
			name:'',
			address:''
		},
		//更新数据对话框控件
		isUpdata:false,
		//更新数据表单
		updata:{
			dateTime:'',
			name:'',
			address:''
		},
		//控制更新数据下标
		index:''
	},
	mounted(){
		this.imfile=document.getElementById('imFile')
		this.outfile=document.getElementById('downlink');
		Vue.prototype.$ajax=axios;
		this.$ajax.get('./json/file.json').then(res=>{
			this.tableData=res.data
		})
	},
	methods:{
		//更新按钮
		handleEdit(index,row){
			// let arr=[]
			// this.$ajax.get('./json/file.json').then(res=>{
			// 	arr=res.data
			// })
			this.isUpdata=true;
			this.updata=row
			this.index=index
			// this.handleEdit(row)
		},
		//更新表单  
		handleEditupdata(){
			this.updata.dateTime=this.formatDate(this.updata.dateTime)
			this.tableData[this.index]=this.updata
			this.isUpdata=false;
			this.$message({message: '更新成功',type: 'success'});
		},
		//批量删除
		delBates(Selection){
			for(let i=0;i<this.tableData.length;i++){
				for(let j=0;j<Selection.length;j++){
					if(this.tableData[i]==Selection[j]){
						this.tableData.splice(i,1)
					}
				}
			}
		},
		//删除操作
		handleDelete(index,row){
			row.splice(index, 1);
		},
		//时间格式
		formatDate(date) {
			if(date instanceof Date){
				var y = date.getFullYear();  
				var m = date.getMonth() + 1;  
				m = m < 10 ? ('0' + m) : m;  
				var d = date.getDate();  
				d = d < 10 ? ('0' + d) : d;  
				return y + '-' + m + '-' + d;
			}
				return date
		},
		//添加操作
		handleEditadd(){
			let data=this.addform
			if(data.dateTime==null||data.dateTime==""){
				this.$message.error('时间不能为空');
			}else if(data.name==null||data.name==""){
				this.$message.error('名字不能为空');
			}else if(data.address==null||data.address==""){
				this.$message.error('地址不能为空');
			}else{
				data.dateTime=this.formatDate(data.dateTime)
				this.tableData.push(data)
				this.isaddtab=false
				this.$message({
				    message: '添加成功',
				    type: 'success'
				});
				this.addform={}
			}
		},
		//获取checkbox选中表全部数据
		handleSelectionChange(val){
			this.Selection=val
		},
		//点击导入按钮
		uploadFile(){
			this.imfile.click()
		},
		//点击导出按钮 
		downloadFile(re){
			let data=[{}]
			for(let key in re[0]){
				data[0][key]=key
			}
			data=data.concat(re)
			this.downloadExl(data,"医院信息")
		},
		//导入操作change事件
		importFile() { // 导入excel
		    this.fullscreenLoading = true
		    let obj = this.imfile
		    if (!obj.files) {
		        this.fullscreenLoading = false
		        return
		    }
		    var f = obj.files[0] 
		    var reader = new FileReader()
		    let $t = this
		    reader.onload = function (e) {
		        var data = e.target.result
		        if ($t.rABS) {
		            $t.wb = XLSX.read(btoa(this.fixdata(data)), {  // 手动转化
		            type: 'base64'
					})
		        } else {
		            $t.wb = XLSX.read(data, {
		            type: 'binary'
		            })
		        }
		          let json = XLSX.utils.sheet_to_json($t.wb.Sheets[$t.wb.SheetNames[0]])
		          // console.log(typeof json)
		          $t.dealFile($t.analyzeData(json)) // analyzeData: 解析导入数据
		        }
		        if (this.rABS) {
		          reader.readAsArrayBuffer(f)
		        } else {
		          reader.readAsBinaryString(f)
		        }
		},
		//导出操作引用事件具体实现
		downloadExl(json, downName, type) {// 导出到excel
		        let keyMap = [] // 获取键
		        for (let k in json[0]) {
		          keyMap.push(k)
		        }
		        // console.info('keyMap', keyMap, json)
		        let tmpdata = [] // 用来保存转换好的json
		        json.map((v, i) => keyMap.map((k, j) => Object.assign({}, {
		          v: v[k],
		          position: (j > 25 ? this.getCharCol(j) : String.fromCharCode(65 + j)) + (i + 1)
		        }))).reduce((prev, next) => prev.concat(next)).forEach(function (v) {
		          tmpdata[v.position] = {
		            v: v.v
		          }
		        })
				//替换字符串
				for(let key in tmpdata){
					if(tmpdata[key].v=='dateTime'){
						tmpdata[key].v='日期'
					}else if(tmpdata[key].v=='name'){
						tmpdata[key].v='名字'
					}else if(tmpdata[key].v=='address'){
						tmpdata[key].v='地址'
					}
				}
		        let outputPos = Object.keys(tmpdata)  // 设置区域,比如表格从A1到D10
		        let tmpWB = {
		          SheetNames: ['mySheet'], // 保存的表标题
		          Sheets: {
		            'mySheet': Object.assign({},
		              tmpdata, // 内容
		              {
		                '!ref': outputPos[0] + ':' + outputPos[outputPos.length - 1] // 设置填充区域
		              })
		          }
		        }
		        let tmpDown = new Blob([this.s2ab(XLSX.write(tmpWB,
		          {bookType: (type === undefined ? 'xlsx' : type), bookSST: false, type: 'binary'} // 这里的数据是用来定义导出的格式类型
		        ))], {
		          type: ''
		        })  // 创建二进制对象写入转换好的字节流
		        var href = URL.createObjectURL(tmpDown)  // 创建对象超链接
		        this.outfile.download = downName + '.xlsx'  // 下载名称
		        this.outfile.href = href  // 绑定a标签
		        this.outfile.click()  // 模拟点击实现下载
		        setTimeout(function () {  // 延时释放
		          URL.revokeObjectURL(tmpDown) // 用URL.revokeObjectURL()来释放这个object URL
		        }, 100)
		},
		analyzeData(data) {  // 此处可以解析导入数据
		    return data
		},
		dealFile(data) {   // 处理导入的数据
			// console.log(data[0])
			//替换表头
			let newdata=[]
			for(let i=0;i<data.length;i++){
				let json1 = JSON.parse(JSON.stringify(data[i]).replace(/日期/g,"dateTime"));
				let json2 = JSON.parse(JSON.stringify(json1).replace(/名字/g,"name"));
				let json3 = JSON.parse(JSON.stringify(json2).replace(/地址/g,"address"));
				newdata.push(json3)
			}
		    this.imfile.value = ''
		    this.fullscreenLoading = false
			if (newdata.length <= 0) {
				this.$message.error('请导入正确信息');
		    } else {
				this.$message({
				          message: '导入成功',
				          type: 'success'
				        });
		        this.tableData = newdata
		    }
		},
		s2ab(s) { // 字符串转字符流
		    var buf = new ArrayBuffer(s.length)
		    var view = new Uint8Array(buf)
		    for (var i = 0; i !== s.length; ++i) {
		        view[i] = s.charCodeAt(i) & 0xFF
		    }
			return buf
		},
		getCharCol(n) { // 将指定的自然数转换为26进制表示。映射关系:[0-25] -> [A-Z]。
		        let s = ''
		        let m = 0
		    while (n > 0) {
		        m = n % 26 + 1
				s = String.fromCharCode(m + 64) + s
		        n = (n - m) / 26
		    }
		    return s
		},
		fixdata(data) {  // 文件流转BinaryString
		    var o = ''
		    var l = 0
		    var w = 10240
		    for (; l < data.byteLength / w; ++l) {
		          o += String.fromCharCode.apply(null, new Uint8Array(data.slice(l * w, l * w + w)))
		    }
		    o += String.fromCharCode.apply(null, new Uint8Array(data.slice(l * w)))
				return o
		}
	},
	
})

内容可丰富了,主要讲讲关于axios和xlsx的使用吧 ,axios我是直接赋值给了vue实例原型创建的$ajax上的

mounted(){
		this.imfile=document.getElementById('imFile')
		this.outfile=document.getElementById('downlink');
		Vue.prototype.$ajax=axios;
		this.$ajax.get('./json/file.json').then(res=>{
			this.tableData=res.data
		})
	},

那么,然后就是关于methods的一些方法了,主要说xlsx的使用吧,由于导入导出需要我直接从网上拷了一套使用方式

//导入操作change事件
		importFile() { // 导入excel
		    this.fullscreenLoading = true
		    let obj = this.imfile
		    if (!obj.files) {
		        this.fullscreenLoading = false
		        return
		    }
		    var f = obj.files[0] 
		    var reader = new FileReader()
		    let $t = this
		    reader.onload = function (e) {
		        var data = e.target.result
		        if ($t.rABS) {
		            $t.wb = XLSX.read(btoa(this.fixdata(data)), {  // 手动转化
		            type: 'base64'
					})
		        } else {
		            $t.wb = XLSX.read(data, {
		            type: 'binary'
		            })
		        }
		          let json = XLSX.utils.sheet_to_json($t.wb.Sheets[$t.wb.SheetNames[0]])
		          // console.log(typeof json)
		          $t.dealFile($t.analyzeData(json)) // analyzeData: 解析导入数据
		        }
		        if (this.rABS) {
		          reader.readAsArrayBuffer(f)
		        } else {
		          reader.readAsBinaryString(f)
		        }
		},
		//导出操作引用事件具体实现
		downloadExl(json, downName, type) {// 导出到excel
		        let keyMap = [] // 获取键
		        for (let k in json[0]) {
		          keyMap.push(k)
		        }
		        // console.info('keyMap', keyMap, json)
		        let tmpdata = [] // 用来保存转换好的json
		        json.map((v, i) => keyMap.map((k, j) => Object.assign({}, {
		          v: v[k],
		          position: (j > 25 ? this.getCharCol(j) : String.fromCharCode(65 + j)) + (i + 1)
		        }))).reduce((prev, next) => prev.concat(next)).forEach(function (v) {
		          tmpdata[v.position] = {
		            v: v.v
		          }
		        })
				//替换字符串
				for(let key in tmpdata){
					if(tmpdata[key].v=='dateTime'){
						tmpdata[key].v='日期'
					}else if(tmpdata[key].v=='name'){
						tmpdata[key].v='名字'
					}else if(tmpdata[key].v=='address'){
						tmpdata[key].v='地址'
					}
				}
		        let outputPos = Object.keys(tmpdata)  // 设置区域,比如表格从A1到D10
		        let tmpWB = {
		          SheetNames: ['mySheet'], // 保存的表标题
		          Sheets: {
		            'mySheet': Object.assign({},
		              tmpdata, // 内容
		              {
		                '!ref': outputPos[0] + ':' + outputPos[outputPos.length - 1] // 设置填充区域
		              })
		          }
		        }
		        let tmpDown = new Blob([this.s2ab(XLSX.write(tmpWB,
		          {bookType: (type === undefined ? 'xlsx' : type), bookSST: false, type: 'binary'} // 这里的数据是用来定义导出的格式类型
		        ))], {
		          type: ''
		        })  // 创建二进制对象写入转换好的字节流
		        var href = URL.createObjectURL(tmpDown)  // 创建对象超链接
		        this.outfile.download = downName + '.xlsx'  // 下载名称
		        this.outfile.href = href  // 绑定a标签
		        this.outfile.click()  // 模拟点击实现下载
		        setTimeout(function () {  // 延时释放
		          URL.revokeObjectURL(tmpDown) // 用URL.revokeObjectURL()来释放这个object URL
		        }, 100)
		},
		analyzeData(data) {  // 此处可以解析导入数据
		    return data
		},
		dealFile(data) {   // 处理导入的数据
			// console.log(data[0])
			//替换表头
			let newdata=[]
			for(let i=0;i<data.length;i++){
				let json1 = JSON.parse(JSON.stringify(data[i]).replace(/日期/g,"dateTime"));
				let json2 = JSON.parse(JSON.stringify(json1).replace(/名字/g,"name"));
				let json3 = JSON.parse(JSON.stringify(json2).replace(/地址/g,"address"));
				newdata.push(json3)
			}
		    this.imfile.value = ''
		    this.fullscreenLoading = false
			if (newdata.length <= 0) {
				this.$message.error('请导入正确信息');
		    } else {
				this.$message({
				          message: '导入成功',
				          type: 'success'
				        });
		        this.tableData = newdata
		    }
		},
		s2ab(s) { // 字符串转字符流
		    var buf = new ArrayBuffer(s.length)
		    var view = new Uint8Array(buf)
		    for (var i = 0; i !== s.length; ++i) {
		        view[i] = s.charCodeAt(i) & 0xFF
		    }
			return buf
		},
		getCharCol(n) { // 将指定的自然数转换为26进制表示。映射关系:[0-25] -> [A-Z]。
		        let s = ''
		        let m = 0
		    while (n > 0) {
		        m = n % 26 + 1
				s = String.fromCharCode(m + 64) + s
		        n = (n - m) / 26
		    }
		    return s
		},
		fixdata(data) {  // 文件流转BinaryString
		    var o = ''
		    var l = 0
		    var w = 10240
		    for (; l < data.byteLength / w; ++l) {
		          o += String.fromCharCode.apply(null, new Uint8Array(data.slice(l * w, l * w + w)))
		    }
		    o += String.fromCharCode.apply(null, new Uint8Array(data.slice(l * w)))
				return o
		}
	},

当然也有一些自己改的地方,比如,导入导出会出现表头如果是英文那么,导入会是英文,而我的数据是需要中文表头的,所以导入我给 替换了一下

let newdata=[]
			for(let i=0;i<data.length;i++){
				let json1 = JSON.parse(JSON.stringify(data[i]).replace(/日期/g,"dateTime"));
				let json2 = JSON.parse(JSON.stringify(json1).replace(/名字/g,"name"));
				let json3 = JSON.parse(JSON.stringify(json2).replace(/地址/g,"address"));
				newdata.push(json3)
			}

导出也一样

//替换字符串
				for(let key in tmpdata){
					if(tmpdata[key].v=='dateTime'){
						tmpdata[key].v='日期'
					}else if(tmpdata[key].v=='name'){
						tmpdata[key].v='名字'
					}else if(tmpdata[key].v=='address'){
						tmpdata[key].v='地址'
					}
				}

这样就可以保障导入不会出现数据key不对称啊,导出表头为英文啊这种问题了
例子
好了 ,就说这么多,持续踩坑中哦
www.gzsdkt.com ,没别的意思,就是推广一下网站,欢迎广州地区有需要中央空调的同志们来本站看看

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值