复习

  1. v-model 表单控件的绑定
  2. axios 发送http请求框架
    1. get axios.get(‘url’,{params:{k:v,k2:v2}}).then(response=>{ this.xxxx指向vue }).catch(error=>{…})
    2. post axios.post(‘url’,{k:v,k2:v2}).then(response=>{ this.xxxx指向vue }).catch(error=>{…}) 注意后端需要用@RequestBody接收
    3. 跨域问题 @CrossOrigin(“*”)
  3. 生命周期
    1. beforeCreate / created 初始化
    2. beforeMount / mounted 挂载
    3. beforeUpdate / updated 更新
    4. beforeDestroy / destroyed 销毁
  4. 计算属性 计算
    1. computed
  5. 过滤器 : 格式化 转换
    1. filters
  6. 事件修饰符跟按键修饰符
    1. 事件冒泡:嵌套标签,触发了内层标签的事件,也会触发外层标签的事件;两种处理模式,
      1. 冒泡 bubble: 先触发内层标签的事件,再触发外层标签的事件
      2. 捕获 capture:先触发外层标签的事件,再触发内层标签的事件
    2. 事件修饰符:行为控制 .stop 阻止事件传播 .capture 使用捕获模式… .prevent 阻止默认行为
    3. 按键修饰符: .enter .ctrl .esc
  7. 组件化编程
    1. 封装自定义组件/标签
    2. Vue.component(‘组件名’,{ }) 组件就是一个vue实例
      1. template 组件模板
      2. props 属性: 外部传入数据
  8. 父子组件传值
    1. 父->子 props
    2. 子->父 自定义事件 组件 this.$emit(“事件名”,事件对象) 外部 监听自定义事件
  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. <style>
  9. </style>
  10. </head>
  11. <body>
  12. <div id="app">
  13. <input type="text" v-model="newTodo" @keyup.enter='addTodo'>
  14. <div>
  15. 共有{{total}}目标,已完成{{finished}}目标,还有{{unfinished}}条未完成
  16. </div>
  17. <div>
  18. <input type="radio" v-model="show" value="showAll">所有目标
  19. <input type="radio" v-model="show" value="showFinished">已完成目标
  20. <input type="radio" v-model="show" value="showUnfinished">未完成
  21. </div>
  22. <ul>
  23. <!-- (2)在组件外部监听自定义事件del,交给处理函数 -->
  24. <todo-item v-for='t in showTodos' @del='handleDelete' :todo="t" :key='t.text'></todo-item>
  25. </ul>
  26. </div>
  27. <!-- 引入vue -->
  28. <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  29. <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
  30. <script>
  31. //全局注册一个组件
  32. Vue.component('todo-item',{
  33. template:`<li style="list-style:none">
  34. <input type="checkbox" name="" v-model="todo.state" id="">
  35. <span contenteditable @keydown.esc='handleCancel' @focus="save" @blur='handleChange' >{{todo.text}}</span>
  36. <span style='color:red;cursor:pointer' @click='del(todo)'>x</span>
  37. </li>`,//html的内容
  38. props:['todo'],//属性,
  39. data:function(){
  40. return {
  41. prev:this.todo.text
  42. }
  43. },
  44. methods:{
  45. del(todo){
  46. this.$emit("del",todo);//(1)在组件内触发一个自定义的事件,名为del,事件对象(事件内容)todo
  47. },
  48. handleChange(e){
  49. console.log("changing:"+this.prev +" canceled:"+this.canceled)
  50. this.todo.text=e.target.innerText;
  51. },
  52. handleCancel(e){
  53. console.log("cancel:"+this.prev)
  54. this.todo.text=this.prev;
  55. e.target.innerText=this.prev;
  56. e.target.blur();
  57. },
  58. save(){
  59. console.log("saving:"+this.todo.text)
  60. this.prev=this.todo.text
  61. }
  62. },
  63. mounted(){
  64. }
  65. });
  66. let app = new Vue({
  67. el: "#app",
  68. data:{
  69. newTodo:"",
  70. show:"showAll",
  71. todos:[{text:"买锅",state:false},{text:"买刀",state:true},{state:false,text:"买把铁丝"}]
  72. },
  73. computed:{
  74. total(){
  75. return this.todos.length;
  76. },
  77. finished(){
  78. return this.todos.filter(t=> t.state).length;
  79. },
  80. unfinished(){
  81. return this.total-this.finished;
  82. },
  83. showTodos(){
  84. switch(this.show){
  85. case "showAll": return this.todos;
  86. case "showFinished": return this.todos.filter(t=>t.state);
  87. case "showUnfinished": return this.todos.filter(t=>!t.state);
  88. }
  89. return this.todos;
  90. }
  91. },
  92. methods:{
  93. handleDelete(todo){
  94. console.log("外部")
  95. console.log(todo);
  96. this.todos.splice(this.todos.indexOf(todo),1);
  97. },
  98. addTodo(){
  99. let todo = {text:this.newTodo,state:false};
  100. this.todos.push(todo)
  101. this.newTodo="";
  102. }
  103. }
  104. });
  105. </script>
  106. </body>
  107. </html>

一个组件对外提供了哪些接口?

  • props属性
  • 自定义事件
  • slot插槽

插槽 slot

  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. <submit-button>
  13. <a href="">
  14. <img src="http://woniuxy.com/page/img/logo-500px.png" >
  15. </a>
  16. </submit-button>
  17. <base-layout>
  18. <template v-slot:header>
  19. 一个菜单
  20. </template>
  21. <h2>好消息,好消息!</h2>
  22. <template v-slot:footer>
  23. 版权所有&copy 麦子科技
  24. </template>
  25. </base-layout>
  26. </div>
  27. <!-- 引入vue -->
  28. <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  29. <script>
  30. Vue.component('submit-button',{
  31. template:`
  32. <button @click='handleSubmit'>
  33. <slot>提交</slot>
  34. </button>
  35. `,
  36. methods:{
  37. handleSubmit(){
  38. alert('提交啦');
  39. }
  40. }
  41. });
  42. Vue.component("base-layout",{
  43. template:`
  44. <div>
  45. <header>
  46. <slot name='header'></slot>
  47. </header>
  48. <main>
  49. <slot></slot>
  50. </main>
  51. <footer>
  52. <slot name='footer'></slot>
  53. </footer>
  54. </div>
  55. `
  56. })
  57. //创建VUE对象
  58. //{}表示构造器参数
  59. let app = new Vue({//ViewModel
  60. el:"#container", //挂载点,与页面的某个dom节点关联
  61. data:{ //数据 Model
  62. },
  63. methods:{
  64. }
  65. });
  66. </script>
  67. </body>
  68. </html>

ElementUI的使用

https://element.eleme.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. <!-- 引入样式 -->
  8. <link
  9. rel="stylesheet"
  10. href="https://unpkg.com/element-ui/lib/theme-chalk/index.css"
  11. />
  12. <title>Document</title>
  13. </head>
  14. <body>
  15. <div id="app">
  16. <el-button @click="visible = true">Button</el-button>
  17. <el-dialog :visible.sync="visible" title="Hello world">
  18. <p>Try Element</p>
  19. </el-dialog>
  20. </div>
  21. <script src="https://unpkg.com/vue/dist/vue.js"></script>
  22. <!-- 引入组件库 -->
  23. <script src="https://unpkg.com/element-ui/lib/index.js"></script>
  24. <script>
  25. let app = new Vue({
  26. el:'#app',
  27. data:{
  28. visible:false
  29. }
  30. });
  31. </script>
  32. </body>
  33. </html>

布局

通过基础的 24 分栏,迅速简便地创建布局。通过el-row和el-col布局,总共24分栏,span表示占用的栏数,offset表示偏移量

  1. <el-row>
  2. <el-col :span="24"><div class="grid-content bg-purple-dark"></div></el-col>
  3. </el-row>
  4. <el-row>
  5. <el-col :span="12"><div class="grid-content bg-purple"></div></el-col>
  6. <el-col :span="12"><div class="grid-content bg-purple-light"></div></el-col>
  7. </el-row>
  8. <el-row>
  9. <el-col :span="8"><div class="grid-content bg-purple"></div></el-col>
  10. <el-col :span="8"><div class="grid-content bg-purple-light"></div></el-col>
  11. <el-col :span="8"><div class="grid-content bg-purple"></div></el-col>
  12. </el-row>

Form

  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. <!-- 引入样式 -->
  8. <link
  9. rel="stylesheet"
  10. href="https://unpkg.com/element-ui/lib/theme-chalk/index.css"
  11. />
  12. <title>Document</title>
  13. </head>
  14. <body>
  15. <div id="app">
  16. <el-container>
  17. <el-header>
  18. <el-menu default-active="1" class="el-menu-demo" mode="horizontal">
  19. <el-menu-item index="1">处理中心</el-menu-item>
  20. <el-submenu index="2">
  21. <template slot="title">我的工作台</template>
  22. <el-menu-item index="2-1">选项1</el-menu-item>
  23. <el-menu-item index="2-2">选项2</el-menu-item>
  24. <el-menu-item index="2-3">选项3</el-menu-item>
  25. <el-submenu index="2-4">
  26. <template slot="title">选项4</template>
  27. <el-menu-item index="2-4-1">选项1</el-menu-item>
  28. <el-menu-item index="2-4-2">选项2</el-menu-item>
  29. <el-menu-item index="2-4-3">选项3</el-menu-item>
  30. </el-submenu>
  31. </el-submenu>
  32. <el-menu-item index="3" disabled>消息中心</el-menu-item>
  33. <el-menu-item index="4"><a href="https://www.ele.me" target="_blank">订单管理</a></el-menu-item>
  34. </el-menu>
  35. </el-header>
  36. <el-main>
  37. <el-row>
  38. <el-col :span='12' :offset="6">
  39. <el-form ref="form" :model="form" label-width="80px">
  40. <el-form-item label="活动名称">
  41. <el-input v-model="form.name"></el-input>
  42. </el-form-item>
  43. <el-form-item label="活动区域">
  44. <el-select v-model="form.region" placeholder="请选择活动区域">
  45. <el-option label="区域一" value="shanghai"></el-option>
  46. <el-option label="区域二" value="beijing"></el-option>
  47. </el-select>
  48. </el-form-item>
  49. <el-form-item label="活动时间">
  50. <el-col :span="11">
  51. <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>
  52. </el-col>
  53. <el-col class="line" :span="2">-</el-col>
  54. <el-col :span="11">
  55. <el-time-picker format='HH:mm:ss' value-format='HH:mm:ss' placeholder="选择时间" v-model="form.date2" style="width: 100%;"></el-time-picker>
  56. </el-col>
  57. </el-form-item>
  58. <el-form-item label="即时配送">
  59. <el-switch v-model="form.delivery"></el-switch>
  60. </el-form-item>
  61. <el-form-item label="活动性质">
  62. <el-checkbox-group v-model="form.type">
  63. <el-checkbox label="美食/餐厅线上活动" name="type"></el-checkbox>
  64. <el-checkbox label="地推活动" name="type"></el-checkbox>
  65. <el-checkbox label="线下主题活动" name="type"></el-checkbox>
  66. <el-checkbox label="单纯品牌曝光" name="type"></el-checkbox>
  67. </el-checkbox-group>
  68. </el-form-item>
  69. <el-form-item label="特殊资源">
  70. <el-radio-group v-model="form.resource">
  71. <el-radio label="线上品牌商赞助"></el-radio>
  72. <el-radio label="线下场地免费"></el-radio>
  73. </el-radio-group>
  74. </el-form-item>
  75. <el-form-item>
  76. <el-upload
  77. class="upload-demo"
  78. action="http://localhost:8080/upload"
  79. name='file'
  80. :on-preview="handlePreview"
  81. :on-remove="handleRemove"
  82. :before-remove="beforeRemove"
  83. multiple
  84. :limit="3"
  85. :on-success="handleSuccess"
  86. :on-exceed="handleExceed"
  87. :file-list="form.fileList">
  88. <el-button size="small" type="primary">点击上传</el-button>
  89. <div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过500kb</div>
  90. </el-upload>
  91. </el-form-item>
  92. <el-form-item label="活动形式">
  93. <el-input type="textarea" v-model="form.desc"></el-input>
  94. </el-form-item>
  95. <el-form-item>
  96. <el-button type="primary" @click="onSubmit">立即创建</el-button>
  97. <el-button>取消</el-button>
  98. </el-form-item>
  99. </el-form>
  100. </el-col>
  101. </el-row>
  102. </el-main>
  103. <el-container>
  104. </div>
  105. <script src="https://unpkg.com/vue/dist/vue.js"></script>
  106. <!-- 引入组件库 -->
  107. <script src="https://unpkg.com/element-ui/lib/index.js"></script>
  108. <script>
  109. let app = new Vue({
  110. el:'#app',
  111. data:{
  112. form:{
  113. name: 'defaultName',
  114. region: '大中国',
  115. date1: '',
  116. date2: '',
  117. delivery: false,
  118. type: [],
  119. resource: '',
  120. desc: '',
  121. 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'}]
  122. },
  123. },
  124. methods:{
  125. onSubmit(){
  126. console.log(this.form);
  127. },
  128. handleRemove(file, fileList) {
  129. console.log(file, fileList);
  130. },
  131. handlePreview(file) {
  132. console.log(file);
  133. },
  134. handleExceed(files, fileList) {
  135. this.$message.warning(`当前限制选择 3 个文件,本次选择了 ${files.length} 个文件,共选择了 ${files.length + fileList.length} 个文件`);
  136. },
  137. beforeRemove(file, fileList) {
  138. return this.$confirm(`确定移除 ${ file.name }?`);
  139. },
  140. handleSuccess(response, file, fileList){
  141. console.log(file);
  142. let fileObj = {name:file.name,url:file.response.data};
  143. this.form.fileList.push(fileObj)
  144. }
  145. }
  146. });
  147. </script>
  148. </body>
  149. </html>

upload使用注意事项:

  1. name指定上传时的文件名
  2. action指定提交的目标地址
  3. 需要在成功回调on-success时手工添加到fileList中

作业:

  1. 前后端增查,按条件分页查询+查看详情+新增讲师

image.png