复习

Vue: 渐进式JavaScript框架
核心理念:MVVM模式 Model-View-ViewModel 模型与视图的双向绑定
模板语法:
{{变量名}}
v-bind 绑定html标签的属性
v-on 指定事件及处理函数
v-for 循环
v-if v-else-if v-else 判断
Vue实例:
let app = new Vue({
el:”#app”,//挂载点
data:{},//数据
methods:{}//方法
});

MDN文档:https://developer.mozilla.org/zh-CN/

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8" />
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  7. <title>教师管理</title>
  8. </head>
  9. <body>
  10. <div id="app">
  11. <table>
  12. <thead>
  13. <tr>
  14. <th>ID</th>
  15. <th>姓名</th>
  16. <th>状态</th>
  17. <th>邮箱</th>
  18. <th>操作</th>
  19. </tr>
  20. </thead>
  21. <tr v-for='t in teachers'>
  22. <td>{{t.teacher_id}}</td>
  23. <td>{{t.teacher_name}}</td>
  24. <td>{{t.state}}</td>
  25. <td>{{t.email}}</td>
  26. <td>
  27. <button v-on:click='audit(t,true)'>审核通过</button>
  28. <button v-on:click='audit(t,false)'>审核不通过</button>
  29. <button v-on:click='fire(t)'>开除</button>
  30. </td>
  31. </tr>
  32. </table>
  33. </div>
  34. <!-- 引入vue -->
  35. <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  36. <script>
  37. let app = new Vue({
  38. el: "#app",
  39. data: {
  40. teachers: [
  41. {
  42. teacher_id: 1,
  43. teacher_name: "zhangsan",
  44. state: "wait",
  45. email: "abc@cyx.com",
  46. },
  47. {
  48. teacher_id: 2,
  49. teacher_name: "zhangsan2",
  50. state: "wait",
  51. email: "abc2@cyx.com",
  52. }
  53. ],
  54. },
  55. methods:{
  56. audit:function(teacher,pass){
  57. teacher.state= pass?"NORMAL":"FAIL";
  58. },
  59. fire:function(t){
  60. let pos = this.teachers.indexOf(t);
  61. this.teachers.splice(pos,1);
  62. }
  63. }
  64. });
  65. </script>
  66. </body>
  67. </html>

排错

出错,离成功还有距离
改完一个错,出现另一个错,离成功又近了一步
报错信息:穿越时空的对话


心态:我错了,我错在哪儿
找报错信息

  • 从下往上,从上往下
  • 从下往上,找第一个错误的报错信息,根源报错信息
  • 找自己的代码,看不懂的不看,看自己写的

对比:与可以运行的代码对比;换一个环境运行;
打日志,逐步缩小问题范围
几种可能性造成该问题

处理用户输入

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8" />
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  7. <title>教师管理</title>
  8. </head>
  9. <body>
  10. <div id="app">
  11. <div><input type="text" v-model='form.username' placeholder="用户名"></div>
  12. <div><input type="password" v-model='form.password' placeholder="密码"></div>
  13. <div>
  14. <select v-model='form.country'>
  15. <option value="China">中国</option>
  16. <option value="USA">美国</option>
  17. <option value="Russia">俄罗斯</option>
  18. </select>
  19. </div>
  20. <div>
  21. 讲师<input type="radio" v-model='form.role' name="role" value='teacher'>
  22. 学员<input type="radio" v-model='form.role' name="role" value='student'>
  23. </div>
  24. <div>
  25. <button @click='login'>登录</button>
  26. </div>
  27. </div>
  28. <!-- 引入vue -->
  29. <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  30. <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
  31. <script>
  32. let app = new Vue({
  33. el: "#app",
  34. data: {
  35. form:{
  36. username:'',
  37. password:'',
  38. country:'China',
  39. role:'student'
  40. }
  41. },
  42. methods:{
  43. login:function(){
  44. console.log(this.form);
  45. axios
  46. .post('http://localhost:8000/login',this.form)//发送到/login,参数是this.form
  47. .then(function(response){//成功处理
  48. console.log(response)
  49. })
  50. .catch(function(error){//异常处理
  51. console.log(error);
  52. })
  53. }
  54. }
  55. });
  56. </script>
  57. </body>
  58. </html>

v-model 在内部为不同的输入元素使用不同的 property 并抛出不同的事件:

  • text 和 textarea 元素使用 value 属性和 input 事件;
  • checkbox 和 radio 使用 checked 属性和 change 事件;
  • select 字段将 value 作为 属性并将 change 作为事件。

    缩写

    v-bind 缩写为 :
    v-on 缩写为 @

axios 通信

专用于发送ajax请求的js库
https://www.kancloud.cn/yunye/axios/234845

当前项目前后端完全分离,后端需要在controller添加@CrossOrigin(“*”) 支持跨域
后端接受参数时默认使用@RequestBody

  1. @RestController
  2. @Slf4j
  3. @CrossOrigin("*")
  4. public class LoginController {
  5. @PostMapping("/login")
  6. public Result login(@RequestBody LoginForm loginForm){

axios参数结构

axios.request({
url:’’,
method:’get’,
responseType:’json’,
data:{},

})
类似jquery的$.ajax
axios.get() / axios.post()都是简化过后的版本

axios响应

image.png
response.data.data才可以引用到返回的结果对象

跨域

image.png

练习Get\Post请求

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8" />
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  7. <title>教师管理</title>
  8. </head>
  9. <body>
  10. <div id="app">
  11. <button @click='queryTeacher'>查询</button>
  12. <table>
  13. <thead>
  14. <tr>
  15. <th>ID</th>
  16. <th>姓名</th>
  17. <th>状态</th>
  18. <th>邮箱</th>
  19. <th>操作</th>
  20. </tr>
  21. </thead>
  22. <tr v-for='t in teachers'>
  23. <td>{{t.teacherId}}</td>
  24. <td>{{t.teacherName}}</td>
  25. <td>{{t.state}}</td>
  26. <td>{{t.email}}</td>
  27. <td>
  28. <button v-on:click='audit(t,true)'>审核通过</button>
  29. <button v-on:click='audit(t,false)'>审核不通过</button>
  30. <button v-on:click='fire(t)'>开除</button>
  31. </td>
  32. </tr>
  33. </table>
  34. </div>
  35. <!-- 引入vue -->
  36. <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  37. <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
  38. <script>
  39. let app = new Vue({
  40. el: "#app",
  41. data: {
  42. teachers: [
  43. {
  44. teacher_id: 1,
  45. teacher_name: "zhangsan",
  46. state: "wait",
  47. email: "abc@cyx.com",
  48. },
  49. {
  50. teacher_id: 2,
  51. teacher_name: "zhangsan2",
  52. state: "wait",
  53. email: "abc2@cyx.com",
  54. }
  55. ],
  56. },
  57. methods:{
  58. audit:function(teacher,pass){
  59. teacher.state= pass?"NORMAL":"FAIL";
  60. axios
  61. .post('http://localhost:8000/audit',
  62. {
  63. 'teacherId':teacher.teacherId,
  64. 'pass':pass
  65. })
  66. .then(response=>{
  67. console.log(response);
  68. if(response.status==200 && response.data.success){
  69. alert("审核操作成功完成")
  70. }
  71. })
  72. .catch(error=>{
  73. console.error(error);
  74. alert("执行出错")
  75. })
  76. },
  77. fire:function(t){
  78. let pos = this.teachers.indexOf(t);
  79. this.teachers.splice(pos,1);
  80. },
  81. queryTeacher:function(){
  82. axios.get('http://localhost:8000/queryTeacher',{
  83. params:{
  84. state:'wait'
  85. }
  86. })
  87. .then(response=>{
  88. console.log(response)
  89. this.teachers=response.data.data;
  90. })
  91. .catch(error=>{
  92. console.error(error)
  93. })
  94. }
  95. }
  96. });
  97. </script>
  98. </body>
  99. </html>
  1. package com.example.demo56.controller;
  2. import com.example.demo56.common.Result;
  3. import com.example.demo56.controller.form.AuditForm;
  4. import com.example.demo56.entity.Teacher;
  5. import lombok.extern.slf4j.Slf4j;
  6. import org.springframework.web.bind.annotation.*;
  7. import java.util.Arrays;
  8. import java.util.List;
  9. @RestController
  10. @CrossOrigin("*")
  11. @Slf4j
  12. public class TeacherController {
  13. @PostMapping("audit")
  14. public Result audit(@RequestBody AuditForm form){
  15. log.info("审核讲师:{}",form);
  16. return Result.success();
  17. }
  18. @GetMapping("queryTeacher")
  19. public Result queryTeacher(String state){
  20. List<Teacher> teacherList = Arrays.asList(
  21. new Teacher(1,"zhangsan","wait","abc@123.com"),
  22. new Teacher(2,"chengyuxiang","wait","abc1@123.com")
  23. );
  24. return Result.success(teacherList);
  25. }
  26. }

Vue实例

  1. let app = new Vue({
  2. el:"",
  3. data:{},
  4. methods:{}
  5. });

生命周期钩子

bean的生命周期: init destroy
static代码块 构造器(带参构造器)
在某个时间点可以介入到生命周期中,进行一些操作
vue实例具备哪些生命周期阶段:
2021年6月22日 Vue2 - 图3
生命周期钩子函数

  • beforeCreate / created 初始化
  • beforeMount / mounted 挂载
  • beforeUpdate / updated 更新
  • beforeDestory / destroyed 销毁 ```javascript let app = new Vue({

    mounted:function(){

    }

});

  1. <a name="GTkAA"></a>
  2. ## 计算属性、监听属性
  3. 通过计算原有的值得到一个属性
  4. ```javascript
  5. <!DOCTYPE html>
  6. <html lang="en">
  7. <head>
  8. <meta charset="UTF-8">
  9. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  10. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  11. <title>购物车</title>
  12. </head>
  13. <body>
  14. <div id="app">
  15. <input type="text" v-model='familyName'>-<input type="text" v-model='givenName'>
  16. <div>
  17. 尊敬的{{name}}
  18. </div>
  19. <div>
  20. <ul>
  21. <li v-for='i in cartItems'>
  22. {{i.pName}} - {{i.price}}
  23. <input type="number" v-model="i.count">
  24. </li>
  25. </ul>
  26. <div>{{totalAmount}}</div>
  27. </div>
  28. </div>
  29. <!-- 引入vue -->
  30. <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  31. <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
  32. <script>
  33. let app = new Vue({
  34. el: "#app",
  35. data: {
  36. familyName:'',
  37. givenName:'',
  38. cartItems:[{pId:1,pName:'鞋子',price:200.0,count:3},{pId:2,pName:'袜子',price:30.0,count:2}]
  39. },
  40. computed:{
  41. name(){
  42. return this.familyName+"."+this.givenName;
  43. },
  44. totalAmount(){
  45. let totalAmount = 0.0;
  46. for(let i = 0;i<this.cartItems.length;i++){
  47. totalAmount+=(this.cartItems[i].price*this.cartItems[i].count);
  48. }
  49. return totalAmount;
  50. }
  51. },
  52. methods:{}
  53. });
  54. </script>
  55. </body>
  56. </html>

私有过滤器与全局过滤器

日期格式化,金额格式化,中英文状态转换
私有过滤器

  1. let app = new Vue({
  2. el: "#app",
  3. data: {
  4. teachers: []
  5. },
  6. mounted(){
  7. //ecmascript = es / es6
  8. this.queryTeacher();
  9. },
  10. //私有过滤器
  11. filters:{//日期格式化,金额格式化,中英文状态转换
  12. transalteState(raw){
  13. let result = '';
  14. switch(raw){
  15. case 'wait': result='待审核';break;
  16. case 'normal': result='审核通过';break;
  17. case 'fail': result='审核失败';break;
  18. default:
  19. console.warn("错误的状态:"+raw);
  20. }
  21. return result;
  22. }
  23. },

全局过滤器

  1. //注册全局过滤器
  2. Vue.filter('transalteState',function(raw){
  3. let result = '';
  4. switch(raw){
  5. case 'wait': result='待审核';break;
  6. case 'normal': result='审核通过';break;
  7. case 'fail': result='审核失败';break;
  8. default:
  9. console.warn("错误的状态:"+raw);
  10. }
  11. return result;
  12. })

使用过滤器

  1. <table>
  2. <thead>
  3. <tr>
  4. <th>ID</th>
  5. <th>姓名</th>
  6. <th>状态</th>
  7. <th>邮箱</th>
  8. <th>操作</th>
  9. </tr>
  10. </thead>
  11. <tr v-for='t in teachers'>
  12. <td>{{t.teacherId}}</td>
  13. <td>{{t.teacherName}}</td>
  14. >>>> <td>{{t.state | transalteState}}</td>
  15. <td>{{t.email}}</td>
  16. <td>
  17. <button v-on:click='audit(t,true)'>审核通过</button>
  18. <button v-on:click='audit(t,false)'>审核不通过</button>
  19. <button v-on:click='fire(t)'>开除</button>
  20. </td>
  21. </tr>
  22. </table>

处理样式

内联样式或者使用class

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Vue入门案例</title>
  8. <style>
  9. .hot{
  10. background-color: red;
  11. color:yellow;
  12. }
  13. .cold{
  14. background-color: blue;
  15. color:aliceblue;
  16. }
  17. </style>
  18. </head>
  19. <body>
  20. <!-- 视图 -->
  21. <div id="container">
  22. <!-- {类名:开关变量} -->
  23. <h2 :class="{cold:isClassPresent}">vue真好用啊~</h2>
  24. <div id="hello" :style="{fontSize:num+'px',textShadow:ts}">hello</div>
  25. </div>
  26. <!-- 引入vue -->
  27. <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  28. <script>
  29. //创建VUE对象
  30. //{}表示构造器参数
  31. let app = new Vue({//ViewModel
  32. el:"#container", //挂载点,与页面的某个dom节点关联
  33. data:{ //数据 Model
  34. myClass:'cold',
  35. isClassPresent:false,
  36. num:30,
  37. ts:'3px 3px 3px gold'
  38. },
  39. methods:{
  40. }
  41. });
  42. </script>
  43. </body>
  44. </html>

事件修饰符与按键修饰符

  1. <!-- 阻止单击事件继续传播 -->
  2. <a v-on:click.stop="doThis"></a>
  3. <!-- 提交事件不再重载页面 -->
  4. <form v-on:submit.prevent="onSubmit"></form>
  5. <!-- 修饰符可以串联 -->
  6. <a v-on:click.stop.prevent="doThat"></a>
  7. <!-- 只有修饰符 -->
  8. <form v-on:submit.prevent></form>
  9. <!-- 添加事件监听器时使用事件捕获模式 -->
  10. <!-- 即内部元素触发的事件先在此处理,然后才交由内部元素进行处理 -->
  11. <div v-on:click.capture="doThis">...</div>
  12. <!-- 只当在 event.target 是当前元素自身时触发处理函数 -->
  13. <!-- 即事件不是从内部元素触发的 -->
  14. <div v-on:click.self="doThat">...</div>

按键修饰符

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Vue入门案例</title>
  8. </head>
  9. <body>
  10. <!-- 视图 -->
  11. <div id="container">
  12. <input type="text" v-model="info" @keyup.enter='send'>
  13. </div>
  14. <!-- 引入vue -->
  15. <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  16. <script>
  17. //创建VUE对象
  18. //{}表示构造器参数
  19. let app = new Vue({//ViewModel
  20. el:"#container", //挂载点,与页面的某个dom节点关联
  21. data:{ //数据 Model
  22. info:''
  23. },
  24. methods:{
  25. send(){
  26. alert(this.info)
  27. }
  28. }
  29. });
  30. </script>
  31. </body>
  32. </html>

为了在必要的情况下支持旧浏览器,Vue 提供了绝大多数常用的按键码的别名:

  • .enter
  • .tab
  • .delete (捕获“删除”和“退格”键)
  • .esc
  • .space
  • .up
  • .down
  • .left
  • .right

组件化编程

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Document</title>
  8. </head>
  9. <body>
  10. <!-- 封装html组件 -->
  11. <navbar></navbar>
  12. <sidebar></sidebar>
  13. <form>
  14. <mz-input></mz-input>
  15. </form>
  16. </body>
  17. </html>

2021年6月22日 Vue2 - 图4

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Document</title>
  8. </head>
  9. <body>
  10. <div id="app">
  11. <ul>
  12. <todo-item v-for='t in todos' :todo="t" :key='t'></todo-item>
  13. </ul>
  14. </div>
  15. <!-- 引入vue -->
  16. <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  17. <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
  18. <script>
  19. //全局注册一个组件
  20. Vue.component('todo-item',{
  21. template:'<li>{{todo}}</li>',//html的内容
  22. props:['todo']//属性
  23. });
  24. let app = new Vue({
  25. el: "#app",
  26. data:{
  27. todos:["买锅","买刀","买把铁丝","买sql"]
  28. },
  29. methods:{}
  30. });
  31. </script>
  32. </body>
  33. </html>

加一个在页面上通过input输入待办事项的功能

注意事项:

  • 组件的模板只能有一个根标签
  • 组件的data是一个function
  • 组件内部支持事件及生命周期钩子函数
  • 命名,分词使用 -

父子组件通信

父组件->子组件传值, 使用props
子组件-> 父组件传值,使用自定义事件
image.png

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Document</title>
  8. </head>
  9. <body>
  10. <div id="app">
  11. <input type="text" v-model="newTodo" @keyup.enter='addTodo'>
  12. <ul>
  13. <!-- (2)在组件外部监听自定义事件del,交给处理函数 -->
  14. <todo-item v-for='t in todos' @del='handleDelete' :todo="t" :key='t.text'></todo-item>
  15. </ul>
  16. </div>
  17. <!-- 引入vue -->
  18. <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  19. <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
  20. <script>
  21. //全局注册一个组件
  22. Vue.component('todo-item',{
  23. template:'<li>{{todo.text}} {{content}} <input type="button" @click="del(todo)" value="点我"></input></li>',//html的内容
  24. props:['todo'],//属性,
  25. data:function(){
  26. return {
  27. content:'123'
  28. }
  29. },
  30. methods:{
  31. del(todo){
  32. console.log(todo);
  33. this.$emit("del",todo);//(1)在组件内触发一个自定义的事件,名为del,事件对象(事件内容)todo
  34. }
  35. },
  36. mounted(){
  37. }
  38. });
  39. let app = new Vue({
  40. el: "#app",
  41. data:{
  42. newTodo:"",
  43. todos:[{text:"买锅",state:false},{text:"买刀",state:false},{state:false,text:"买把铁丝"}]
  44. },
  45. methods:{
  46. handleDelete(todo){
  47. console.log("外部")
  48. console.log(todo);
  49. this.todos.splice(this.todos.indexOf(todo),1);
  50. },
  51. addTodo(){
  52. let todo = {text:this.newTodo,state:false};
  53. this.todos.push(todo)
  54. this.newTodo="";
  55. }
  56. }
  57. });
  58. </script>
  59. </body>
  60. </html>

vue练习-代办列表.gif