基本案例
<!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.0" /><!-- 引入样式 --><linkrel="stylesheet"href="https://unpkg.com/element-ui/lib/theme-chalk/index.css"/><title>Document</title></head><body><div id="app"><el-button @click="visible = true">Button</el-button><el-dialog :visible.sync="visible" title="Hello world"><p>Try Element</p></el-dialog></div><script src="https://unpkg.com/vue/dist/vue.js"></script><!-- 引入组件库 --><script src="https://unpkg.com/element-ui/lib/index.js"></script><script>let app = new Vue({el:'#app',data:{visible:false}});</script></body></html>
布局
通过基础的 24 分栏,迅速简便地创建布局。通过el-row和el-col布局,总共24分栏,span表示占用的栏数,offset表示偏移量
<el-row><el-col :span="24"><div class="grid-content bg-purple-dark"></div></el-col></el-row><el-row><el-col :span="12"><div class="grid-content bg-purple"></div></el-col><el-col :span="12"><div class="grid-content bg-purple-light"></div></el-col></el-row><el-row><el-col :span="8"><div class="grid-content bg-purple"></div></el-col><el-col :span="8"><div class="grid-content bg-purple-light"></div></el-col><el-col :span="8"><div class="grid-content bg-purple"></div></el-col></el-row>
Form
<!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.0" /><!-- 引入样式 --><linkrel="stylesheet"href="https://unpkg.com/element-ui/lib/theme-chalk/index.css"/><title>Document</title></head><body><div id="app"><el-container><el-header><el-menu default-active="1" class="el-menu-demo" mode="horizontal"><el-menu-item index="1">处理中心</el-menu-item><el-submenu index="2"><template slot="title">我的工作台</template><el-menu-item index="2-1">选项1</el-menu-item><el-menu-item index="2-2">选项2</el-menu-item><el-menu-item index="2-3">选项3</el-menu-item><el-submenu index="2-4"><template slot="title">选项4</template><el-menu-item index="2-4-1">选项1</el-menu-item><el-menu-item index="2-4-2">选项2</el-menu-item><el-menu-item index="2-4-3">选项3</el-menu-item></el-submenu></el-submenu><el-menu-item index="3" disabled>消息中心</el-menu-item><el-menu-item index="4"><a href="https://www.ele.me" target="_blank">订单管理</a></el-menu-item></el-menu></el-header><el-main><el-row><el-col :span='12' :offset="6"><el-form ref="form" :model="form" label-width="80px"><el-form-item label="活动名称"><el-input v-model="form.name"></el-input></el-form-item><el-form-item label="活动区域"><el-select v-model="form.region" placeholder="请选择活动区域"><el-option label="区域一" value="shanghai"></el-option><el-option label="区域二" value="beijing"></el-option></el-select></el-form-item><el-form-item label="活动时间"><el-col :span="11"><el-date-picker type="date" format='yyyy-MM-dd' value-format="yyyy-MM-dd" placeholder="选择日期" v-model="form.date1" style="width: 100%;"></el-date-picker></el-col><el-col class="line" :span="2">-</el-col><el-col :span="11"><el-time-picker format='HH:mm:ss' value-format='HH:mm:ss' placeholder="选择时间" v-model="form.date2" style="width: 100%;"></el-time-picker></el-col></el-form-item><el-form-item label="即时配送"><el-switch v-model="form.delivery"></el-switch></el-form-item><el-form-item label="活动性质"><el-checkbox-group v-model="form.type"><el-checkbox label="美食/餐厅线上活动" name="type"></el-checkbox><el-checkbox label="地推活动" name="type"></el-checkbox><el-checkbox label="线下主题活动" name="type"></el-checkbox><el-checkbox label="单纯品牌曝光" name="type"></el-checkbox></el-checkbox-group></el-form-item><el-form-item label="特殊资源"><el-radio-group v-model="form.resource"><el-radio label="线上品牌商赞助"></el-radio><el-radio label="线下场地免费"></el-radio></el-radio-group></el-form-item><el-form-item><el-uploadclass="upload-demo"action="http://localhost:8080/upload"name='file':on-preview="handlePreview":on-remove="handleRemove":before-remove="beforeRemove"multiple:limit="3":on-success="handleSuccess":on-exceed="handleExceed":file-list="form.fileList"><el-button size="small" type="primary">点击上传</el-button><div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过500kb</div></el-upload></el-form-item><el-form-item label="活动形式"><el-input type="textarea" v-model="form.desc"></el-input></el-form-item><el-form-item><el-button type="primary" @click="onSubmit">立即创建</el-button><el-button>取消</el-button></el-form-item></el-form></el-col></el-row></el-main><el-container></div><script src="https://unpkg.com/vue/dist/vue.js"></script><!-- 引入组件库 --><script src="https://unpkg.com/element-ui/lib/index.js"></script><script>let app = new Vue({el:'#app',data:{form:{name: 'defaultName',region: '大中国',date1: '',date2: '',delivery: false,type: [],resource: '',desc: '',fileList: [{name: 'food.jpeg', url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100'}, {name: 'food2.jpeg', url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100'}]},},methods:{onSubmit(){console.log(this.form);},handleRemove(file, fileList) {console.log(file, fileList);},handlePreview(file) {console.log(file);},handleExceed(files, fileList) {this.$message.warning(`当前限制选择 3 个文件,本次选择了 ${files.length} 个文件,共选择了 ${files.length + fileList.length} 个文件`);},beforeRemove(file, fileList) {return this.$confirm(`确定移除 ${ file.name }?`);},handleSuccess(response, file, fileList){console.log(file);let fileObj = {name:file.name,url:file.response.data};this.form.fileList.push(fileObj)}}});</script></body></html>
upload使用注意事项:
- name指定上传时的文件名
- action指定提交的目标地址
需要在成功回调on-success时手工添加到fileList中
分页
<el-paginationbackgroundlayout="prev, pager, next,sizes":total="page.total" 总条数:current-page='page.current' 当前页:page-size='page.size' 页容量@current-change='search' 当前页码改变时间,回传改变后的页码></el-pagination>search(current){//发请求到后端,搜索数据let param = this.searchForm;param.pageIndex=current;param.pageSize=this.page.size;axios.get('http://localhost:8000/queryTeacher',{params:param}).then(resp=>{if(resp.status=200&&resp.data.success){let data = resp.data.data;this.tableData=data.records;//将后端返回的数据绑定到分页条上this.page.total=data.total;this.page.current=data.current;this.page.size=data.size;}else{this.$message({message:'查询失败,'+resp.data.message,type:'warning'})}}).catch(error=>{this.$message({message:'查询失败,'+error.message,type:'error'})})}}
JS发展
nodejs js运行时环境 让js脱离浏览器,在电脑上运行
- 后端代码,创建httpserver,接受http请求,并且响应;可以访问数据库;可以创建文件读取文件
- 框架 express / sequelize
- 桌面端应用程序
- 框架 electron
- 移动端应用程序
- react-native
- vue -> uniapp / weex
npm nodejs 自带的包管理器,功能类似于maven的依赖管理
webpack 打包工具,类似于Maven的构建流程
html => pug模板,简化html的编写
css => sass / less css拓展语言
js => typescript / coffeescript 升级
安装Node环境
- nodejs 自带npm
https://nodejs.org/zh-cn/
安装,下一步,下一步
- 测试
node -vnpm -v - 编写一个例子
# 编写一个helloworld.js,内容如下console.log("hello world");# 通过node命令运行node helloworld.js
```javascript var mysql = require(‘mysql’); var http = require(‘http’);npm initnpm install mysql# 编写index.js,内容如下# 运行node index.js# 访问 localhost:8888 即可在控制台看到数据
http.createServer(function (request, response) {
// 发送 HTTP 头部// HTTP 状态值: 200 : OK// 内容类型: text/plainresponse.writeHead(200, {'Content-Type': 'text/plain'});var connection = mysql.createConnection({host: 'localhost',port:3306,user: 'root',password: 'root123',database: 'edu_56'});connection.connect();connection.query('SELECT * from edu_teacher', function (error, results, fields) {if (error) throw error;console.log('The solution is: ', results);// 发送响应数据 "Hello World"response.end(results);});
}).listen(8888);
// 终端打印如下信息 console.log(‘Server running at http://127.0.0.1:8888/‘);
4. 安装taobao的npm源```bashnpm i -g cnpm --registry=https://registry.npm.taobao.org
vue-cli
安装
cnpm install -g @vue/clivue -V
创建项目
# cmdvue create my-project# 界面vue ui





cd vue56npm run serve# 访问 IP:8080 看到界面
解析脚手架项目
node_modules node下载的依赖
public
src 源码
- assets 图片等资源
- components 组件
- router 路由配置
- views 视图,界面
- App.vue 应用的容器
- main.js 整个项目的入口 ```javascript //从vue依赖包当中导入Vue对象 import Vue from ‘vue’ //导入一个组件App import App from ‘./App.vue’ //导入vue-router,路由器 import router from ‘./router’
//关闭生产环境 Vue.config.productionTip = false
//实例化vue new Vue({ router, //引入路由器 render: h => h(App)//渲染App组件 }) .$mount(‘#app’)//挂载到App组件内部id为app的元素上
package.json 项目管理文件约定:<br />在文件夹下的index.js, 当引入文件夹时,默认读取index.js<a name="pAMB6"></a>## 包js内部,封装多个方法或者类的一个工具,类似于java包<br />在包内部,导出数据和方法```javascriptfunction helloPlus(){hello();}function hello(){alert('123');}//导出的内容export default {delta : 1.99,sayHello: helloPlus}
需要使用时,引入
import a from './a.js'a.sayHello();
单文件组件 .vue文件
before :
Vue.component('todo-item',{template:`<li style="list-style:none"><input type="checkbox" name="" v-model="todo.state" id=""><span contenteditable @keydown.esc='handleCancel' @focus="save" @blur='handleChange' >{{todo.text}}</span><span style='color:red;cursor:pointer' @click='del(todo)'>x</span></li>`,//html的内容props:['todo'],//属性,data:function(){return {prev:this.todo.text}},methods:{del(todo){this.$emit("del",todo);//(1)在组件内触发一个自定义的事件,名为del,事件对象(事件内容)todo},handleChange(e){console.log("changing:"+this.prev +" canceled:"+this.canceled)this.todo.text=e.target.innerText;},handleCancel(e){console.log("cancel:"+this.prev)this.todo.text=this.prev;e.target.innerText=this.prev;e.target.blur();},save(){console.log("saving:"+this.todo.text)this.prev=this.todo.text}},mounted(){}});
after:
现在我们获得:
一个 .vue 文件,就是一个组件
vue-router 路由器
单页面应用 Single Page Application SPA
不切换页面的情况下更新内容,极佳的用户体验,类似于App的使用体验,成为潮流
map.baidu.com
juejin.im
实例
<!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.0"><title>Document</title></head><body><div id="app"><!-- 使用 router-link 组件来导航. --><!-- 通过传入 `to` 属性指定链接. --><!-- <router-link> 默认会被渲染成一个 `<a>` 标签 --><router-link to='/idx'>首页</router-link><router-link to='/ctr'>个人中心</router-link><!-- 路由出口 --><!-- 路由匹配到的组件将渲染在这里 --><router-view></router-view></div><script src="https://unpkg.com/vue/dist/vue.js"></script><script src="https://unpkg.com/vue-router/dist/vue-router.js"></script><script>//1. 定义两个组件let index = Vue.component('index',{template:'<div><h1>首页</h1></div>'});let center = Vue.component('center',{template:'<div><h1>个人中心</h1></div>'});//2. 定义路径与组件之间的映射关系const routes=[{path:'/idx',component:index},{path:'/ctr',component:center}]//3. 创建路由对象const router = new VueRouter({routes});//4.将路由对象设置到Vue实例中,使之生效new Vue({router}).$mount('#app');</script></body></html>
动态路由
根据路径动态匹配组件
<!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.0"><title>Document</title></head><body><div id="app"><!-- 使用 router-link 组件来导航. --><!-- 通过传入 `to` 属性指定链接. --><!-- <router-link> 默认会被渲染成一个 `<a>` 标签 --><router-link to='/idx'>首页</router-link><router-link to='/ctr'>个人中心</router-link><router-link to='/product/bottle'>产品介绍</router-link><!-- 路由出口 --><!-- 路由匹配到的组件将渲染在这里 --><router-view></router-view></div><script src="https://unpkg.com/vue/dist/vue.js"></script><script src="https://unpkg.com/vue-router/dist/vue-router.js"></script><script>//1. 定义两个组件let index = Vue.component('index',{template:'<div><h1>首页</h1></div>'});let center = Vue.component('center',{template:'<div><h1>个人中心</h1></div>'});let product = Vue.component('product',{template:'<div><h1>产品介绍:{{$route.params.productName}}</h1></div>'});//2. 定义路径与组件之间的映射关系const routes=[{path:'/idx',component:index},{path:'/ctr',component:center},{path:'/product/:productName',component:product}]//3. 创建路由对象const router = new VueRouter({routes});//4.将路由对象设置到Vue实例中,使之生效new Vue({router}).$mount('#app');</script></body></html>
嵌套路由
在组件内部存在路由链接及路由视图
在routes路由表中使用children表示嵌套的路由关系
<!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.0"><title>Document</title></head><body><div id="app"><!-- 使用 router-link 组件来导航. --><!-- 通过传入 `to` 属性指定链接. --><!-- <router-link> 默认会被渲染成一个 `<a>` 标签 --><router-link to='/idx'>首页</router-link><router-link to='/ctr'>个人中心</router-link><!-- 路由出口 --><!-- 路由匹配到的组件将渲染在这里 --><router-view></router-view></div><script src="https://unpkg.com/vue/dist/vue.js"></script><script src="https://unpkg.com/vue-router/dist/vue-router.js"></script><script>//1. 定义两个组件let index = Vue.component('index',{template:'<div><h1>首页</h1></div>'});let center = Vue.component('center',{template:`<div><h1>个人中心</h1><!-- 嵌套路由的链接 --><router-link to='/center/intro'>intro</router-link><router-link to='/center/modify'>modify</router-link><!-- 嵌套路由的出口 --><router-view></router-view></div>`});//嵌套路由的组件let intro = Vue.component('intro',{template:`<h2>个人介绍:大帅哥一个</h2>`})let modify = Vue.component('modify',{template:`<h2>修改个人信息</h2>`})//2. 定义路径与组件之间的映射关系const routes=[{path:'/idx',component:index},{path:'/ctr',component:center,children:[{path:'/center/intro', component: intro},{path:'/center/modify', component: modify}]},]//3. 创建路由对象const router = new VueRouter({routes});//4.将路由对象设置到Vue实例中,使之生效new Vue({router}).$mount('#app');</script></body></html>
编程式路由导航
调用this.$router.push方法进行跳转
- 直接传链接
传对象 ```html <!DOCTYPE html>
<!-- 使用 router-link 组件来导航. --><!-- 通过传入 `to` 属性指定链接. --><!-- <router-link> 默认会被渲染成一个 `<a>` 标签 --><router-link to='/login'>登录</router-link><router-link to='/reg'>注册</router-link><!-- 路由出口 --><!-- 路由匹配到的组件将渲染在这里 --><router-view></router-view>
</div><script src="https://unpkg.com/vue/dist/vue.js"></script><script src="https://unpkg.com/vue-router/dist/vue-router.js"></script><script>//1. 定义两个组件let reg = Vue.component('reg',{template:`<div><h1>注册</h1><input type="text" v-model='regForm.username' id=""><input type="password" v-model='regForm.password' id=""><button @click='doReg'>注册</button></div>`,data(){return{regForm:{username:'',password:''}}},methods:{doReg(){console.log(this.regForm);alert('注册成功');console.log(this.$router);// this.$router.push('/login'); //直接传链接this.$router.push({path:'/login',query:{username:'zhangsan'}});//传对象}}});let login = Vue.component('login',{template:'<div><h1>登录 {{$route.query.username}}</h1></div>'});//2. 定义路径与组件之间的映射关系const routes=[{path:'/login',component:login},{path:'/reg',component:reg}]//3. 创建路由对象const router = new VueRouter({routes});//4.将路由对象设置到Vue实例中,使之生效new Vue({router}).$mount('#app');</script>
<a name="AvJBr"></a>### 路由守卫在跳转过程中检查是否有权限跳转到目标链接<br />全局:前置守卫、解析守卫、后置钩子<br />局部:单个路由内部、组件内部<br />完整的导航流程 : [https://router.vuejs.org/zh/guide/advanced/navigation-guards.html#%E5%AE%8C%E6%95%B4%E7%9A%84%E5%AF%BC%E8%88%AA%E8%A7%A3%E6%9E%90%E6%B5%81%E7%A8%8B](https://router.vuejs.org/zh/guide/advanced/navigation-guards.html#%E5%AE%8C%E6%95%B4%E7%9A%84%E5%AF%BC%E8%88%AA%E8%A7%A3%E6%9E%90%E6%B5%81%E7%A8%8B)```javascript//添加全局的前置守卫router.beforeEach((to,from,next)=>{if(to.path=='/reg'){alert("目前尚未开放注册!")return;}//放行next();});
路由的参数:
每个守卫方法接收三个参数:
**to: Route**: 即将要进入的目标 路由对象**from: Route**: 当前导航正要离开的路由**next: Function**: 一定要调用该方法来resolve这个钩子。执行效果依赖next方法的调用参数。**next()**: 进行管道中的下一个钩子。如果全部钩子执行完了,则导航的状态就是 confirmed (确认的)。**next(false)**: 中断当前的导航。如果浏览器的 URL 改变了 (可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到from路由对应的地址。**next('/')**或者**next({ path: '/' })**: 跳转到一个不同的地址。当前的导航被中断,然后进行一个新的导航。你可以向next传递任意位置对象,且允许设置诸如replace: true、name: 'home'之类的选项以及任何用在[router-link](https://router.vuejs.org/zh/api/#to)的[to](https://router.vuejs.org/zh/api/#to)prop 或[router.push](https://router.vuejs.org/zh/api/#router-push)中的选项。**next(error)**: (2.4.0+) 如果传入next的参数是一个Error实例,则导航会被终止且该错误会被传递给[router.onError()](https://router.vuejs.org/zh/api/#router-onerror)注册过的回调。
代码
main.js
- 实例化Vue
- 挂载到App.vue
- 导入router文件夹 引入了vue-router
App.vue
- 页面骨架 router-link 、 router-view
router文件夹 index.js
- 配置路由器,提供了路由表 (路径 和 组件映射)
- 根据路由表将多个组件组织起来
/=> Home- Home.vue
- 引入了HelloWorld组件(import Helloworld ; 在 组件的实例中使用 components注册)
- Home.vue
开发一个页面
- 编写页面
```vue
{{person.name}}
2. 在 App.vue增加链接```vue<router-link to="/">Home</router-link> |<router-link to="/about">About</router-link> |>>>>> <router-link to="/center">个人中心</router-link>
- 在router/index.js中配置路径映

使用axios
- 在项目根目录(package.json所在目录)下
npm add axios(本质是在package.json中添加axios依赖,并执行install拉取) - 在main.js中引入并绑定到vue上 ```javascript import axios from ‘axios’
//定制axios 具体可以定制的选项,参考https://www.kancloud.cn/yunye/axios/234845 请求配置一节 var instance = axios.create({ baseURL: ‘http://localhost:8000‘, timeout: 1000 }); //将axios绑定到Vue上,全局变量 Vue.prototype.$http=instance;
3. 在其他组件即可使用```jsonthis.$http.get("/getPersonInfo",{params:{id:1}}).then(resp=>{if(resp.status==200&&resp.data.success){this.person=resp.data.data;}}).catch(error=>{console.error("加载出错",error);})
如果报依赖缺失,执行 cnpm install
These dependencies were not found:* core-js/modules/es.object.to-string.js in ./src/router/index.js* core-js/modules/es.string.iterator.js in ./src/router/index.js* core-js/modules/web.dom-collections.iterator.js in ./src/router/index.js
使用elementUI
- 添加依赖
cnpm i element-ui -S - 在main.js中启用element ```javascript //引入element import ElementUI from ‘element-ui’; import ‘element-ui/lib/theme-chalk/index.css’;
Vue.use(ElementUI);
3. 使用elementUI```vue<template><div class="about"><el-container><el-header><el-menu default-active="1" class="el-menu-demo" mode="horizontal"><el-menu-item index="1">处理中心</el-menu-item><el-submenu index="2"><template slot="title">我的工作台</template><el-menu-item index="2-1">选项1</el-menu-item><el-menu-item index="2-2">选项2</el-menu-item><el-menu-item index="2-3">选项3</el-menu-item><el-submenu index="2-4"><template slot="title">选项4</template><el-menu-item index="2-4-1">选项1</el-menu-item><el-menu-item index="2-4-2">选项2</el-menu-item><el-menu-item index="2-4-3">选项3</el-menu-item></el-submenu></el-submenu><el-menu-item index="3" disabled>消息中心</el-menu-item><el-menu-item index="4"><a href="https://www.ele.me" target="_blank">订单管理</a></el-menu-item></el-menu></el-header><el-main><el-form :inline="true" :model="searchForm" class="demo-form-inline"><el-form-item label="教师姓名"><el-input v-model="searchForm.teacherName" placeholder="教师姓名"></el-input></el-form-item><el-form-item label="审核状态"><el-select clearable v-model="searchForm.state" placeholder="审核状态"><el-option label="待审核" value="wait"></el-option><el-option label="审核通过" value="normal"></el-option><el-option label="审核失败" value="fail"></el-option></el-select></el-form-item><el-form-item><el-button type="primary" @click="search">查询</el-button><el-button type="success" @click="addTeacherDialogVisible=true" icon="el-icon-plus" circle></el-button></el-form-item></el-form><el-row><el-col ><el-table:data="tableData"style="width: 100%"><el-table-columnprop="teacherId"label="教师ID"width="180"></el-table-column><el-table-columnprop="teacherName"label="教师姓名"width="180"></el-table-column><!-- 格式化器 --><el-table-columnprop="state":formatter="stateFormatter"label="状态"></el-table-column><el-table-columnprop="email"label="邮箱"></el-table-column><el-table-columnlabel="操作"><template slot-scope='scope'><el-button v-if='scope.row.state=="wait"' @click="audit(scope.row,true)" type="text" size="small">审核通过</el-button><el-button v-if='scope.row.state=="wait"' @click="audit(scope.row,false)" type="text" size="small">审核失败</el-button><el-button v-if='scope.row.state=="normal"' @click="fire(scope.row)" type="text" size="small">开除</el-button><el-button v-if='scope.row.state=="normal"' @click="modifyTeacher(scope.row)" type="text" size="small">修改</el-button></template></el-table-column></el-table><el-paginationbackgroundlayout="prev, pager, next,sizes":total="page.total":current-page='page.current':page-size='page.size'@current-change='search'></el-pagination></el-col></el-row></el-main></el-container><el-dialog title="新增讲师" :visible.sync="addTeacherDialogVisible"><el-form :model="addTeacherForm"><el-row><el-col :span='15'><el-form-item label="讲师姓名" label-width="180px"><el-input v-model="addTeacherForm.teacherName" autocomplete="off"></el-input></el-form-item></el-col></el-row><el-row><el-col :span='15'><el-form-item label="生日" label-width="180px"><el-date-pickerv-model="addTeacherForm.birthday"type="date"format="yyyy-MM-dd"value-format="yyyy-MM-dd HH:mm:ss"placeholder="选择生日"></el-date-picker></el-form-item></el-col></el-row><el-form-item label="email" label-width="180px"><el-input v-model="addTeacherForm.email" autocomplete="off"></el-input></el-form-item></el-form><div slot="footer" class="dialog-footer"><el-button @click="addTeacherDialogVisible = false">取 消</el-button><el-button type="primary" @click="addTeacher">新增</el-button></div></el-dialog><el-dialog title="修改讲师" :visible.sync="modifyTeacherDialogVisible"><el-form :model="modifyTeacherForm"><el-row><el-col :span='15'><el-form-item label="讲师姓名" label-width="180px"><el-input v-model="modifyTeacherForm.teacherName" autocomplete="off"></el-input></el-form-item></el-col></el-row><el-row><el-col :span='15'><el-form-item label="生日" label-width="180px"><el-date-pickerv-model="modifyTeacherForm.birthday"type="date"format="yyyy-MM-dd"value-format="yyyy-MM-dd HH:mm:ss"placeholder="选择生日"></el-date-picker></el-form-item></el-col></el-row><el-form-item label="email" label-width="180px"><el-input v-model="modifyTeacherForm.email" autocomplete="off"></el-input></el-form-item></el-form><div slot="footer" class="dialog-footer"><el-button @click="modifyTeacherDialogVisible = false">取 消</el-button><el-button type="primary">修改</el-button></div></el-dialog></div></template><script>export default {name:'About',data(){return {page:{total:0,current:1,size:10},searchForm:{teacherName:'',state:''},formLabelWidth:"80px",modifyTeacherDialogVisible:false,addTeacherForm: {teacherName: '',email:'',birthday:''},modifyTeacherForm: {teacherId:'',teacherName: '',email:'',birthday:''},addTeacherDialogVisible:false,tableData:[]}},mounted(){this.search(1);},methods:{modifyTeacher(row){this.modifyTeacherForm=row;this.modifyTeacherDialogVisible=true;},addTeacher(){console.log(this.addTeacherForm)this.$http.post('/addNewTeacher',this.addTeacherForm).then(resp=>{this.$message({message:"新增成功",type:"success"});this.search(1);this.addTeacherDialogVisible=false;}).catch(resp=>{this.$message({message:"操作失败",type:"warning"});this.addTeacherDialogVisible=false;})},stateFormatter(row, column, cellValue, index){switch(cellValue){case 'wait': return '待审核';case 'normal': return '审核通过';case 'fail': return '审核失败';default : console.error("错误的状态"+cellValue+",无法格式化");}},audit(row,pass){console.log(row,pass);this.$http.post('/audit',{"teacherId":row.teacherId,"pass":pass}).then(resp=>{this.$message({message:"审核操作完成",type:"success"});this.search(1);}).catch(resp=>{this.$message({message:"操作失败",type:"warning"});})},fire(row){},handleClick(row){console.log(row);this.dialogFormVisible=true;// this.$message({message:'你查看成功了',type:'warning'});},search(current){//发请求到后端,搜索数据let param = this.searchForm;param.pageIndex=current;param.pageSize=this.page.size;this.$http.get('/queryTeacher',{params:param}).then(resp=>{if(resp.status=200&&resp.data.success){let data = resp.data.data;this.tableData=data.records;//将后端返回的数据绑定到分页条上this.page.total=data.total;this.page.current=data.current;this.page.size=data.size;}else{this.$message({message:'查询失败,'+resp.data.message,type:'warning'})}}).catch(error=>{this.$message({message:'查询失败,'+error.message,type:'error'})})}}}</script>
特别说明:
在el-menu上添加router属性,将激活vue-router模式,使用index作为path导航
<el-menu router default-active="1" class="el-menu-demo" mode="horizontal"><el-menu-item index="/">主页</el-menu-item><el-menu-item index="/about">关于</el-menu-item><el-menu-item index="/center">个人中心</el-menu-item>
Vuex
问题: 前端需要存储类似是否登录这样的数据,用于判断页面能否显示?
两种方式:
简单处理方式(丐版),在浏览器中存储数据: localStorage / sessionStorage (html5)
为何不用Cookie?
页面切换时,可能不发请求;数据量比较大
localStorage和sessionStorage的API是一致的,如下:
- 保存数据:localStorage.setItem(key,value);
- 读取数据:localStorage.getItem(key);
- 删除单个数据:localStorage.removeItem(key);
- 删除所有数据:localStorage.clear();
- 得到某个索引的key:localStorage.key(index);
localStorage和sessionStorage的区别在于作用域范围,localStroge针对一个网站,持久存储;sessionStorage只对一个标签,关闭则消失;一般使用localStorage;
拦截登录实例
- 路由守卫,拦截所有请求,基于router实现守卫,代码写在/router/index.js ```javascript import {Message} from ‘element-ui’
…
router.beforeEach((to,from,next)=>{ let isLogined = localStorage.getItem(“isLogined”); console.log(“是否登录”+isLogined);
if(to.path==’/login’){ console.log(“登陆请求,放行”); next(); return; } if(isLogined){ console.log(“已登录,放行”); next(); return; }
Message({ type:”error”, message:”请您先登录” }); //this.$router 是在vue实例中使用 //跳转 router.push(“/login”);
});
2. 登录完成后,存入登录标记```vue<template><el-form:model="ruleForm"status-iconref="ruleForm"label-width="100px"class="demo-ruleForm"><el-form-item label="用户名" prop="pass"><el-inputtype="text"v-model="ruleForm.username"autocomplete="off"></el-input></el-form-item><el-form-item label="密码" prop="checkPass"><el-inputtype="password"v-model="ruleForm.password"autocomplete="off"></el-input></el-form-item><el-form-item><el-button type="primary" @click="submitForm">登录</el-button></el-form-item></el-form></template><script>export default {name: "Login",data() {return {ruleForm: {username: "",password: "",}};},methods: {submitForm() {alert("登录成功");localStorage.setItem("isLogined","true");}},};</script>
可以通过开发者控制台查看localStorage所存的数据
Vuex
https://vuex.vuejs.org/zh/
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
处理中大型的vue应用程序的数据状态管理
- state,数据存储,驱动应用的数据源;
- view,以声明方式将 state 映射到视图;
- actions,用来修改state的一些操作,响应在 view 上的用户输入导致的状态变化。
如果state里有一个属性叫余额,那么actions就可能存在充值或者提现这样方法
以下是一个表示“单向数据流”理念的简单示意:


<!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.0"><title>Document</title></head><body><div id="app"><div>{{count}}</div><div><button @click='add'>+</button><button @click='minus'>-</button></div></div><script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script><script src="https://unpkg.com/vuex@3.6.2/dist/vuex.js"></script><script>// public class A{// private int count=0;// public void incr(){// count++;// }// public void decr(){// count--;// }// }//创建了一个Vuex的store对象const store = new Vuex.Store({state:{//数据count:0},mutations:{//action,对数据的操作incr(state){//参数为state对象state.count++;},decr(state){state.count--;}}});let app = new Vue({el:"#app",data:{// count:0},computed:{//通过计算属性将store内部的值放进到vue实例中count(){return store.state.count;}},methods:{add(){//触发store的相应的mutation更改器store.commit('incr');},minus(){store.commit('decr');}}})</script></body></html>
