《苍穹外卖》前端课程知识点记录

作者 : admin 本文共25676个字,预计阅读时间需要65分钟 发布时间: 2024-06-17 共1人阅读

一、VUE基础知识

基于脚手架创建前端工程

1. 环境要求

《苍穹外卖》前端课程知识点记录插图

安装node.js:Node.js安装与配置(详细步骤)_nodejs安装及环境配置-CSDN博客
查看node和npm的版本号

《苍穹外卖》前端课程知识点记录插图(1)

安装Vue CLI:Vue.js安装与创建默认项目(详细步骤)_nodejs安装及环境配置-CSDN博客

《苍穹外卖》前端课程知识点记录插图(2)

查看vue版本

《苍穹外卖》前端课程知识点记录插图(3)

使用Vue CLI创建前端工程

  • 方式一:vue create项目名称

  ① 创建一个不带中文的文件夹,如下图:
《苍穹外卖》前端课程知识点记录插图(4)

② 创建工程—选择Vue 2
《苍穹外卖》前端课程知识点记录插图(5)
③ 选择npm
《苍穹外卖》前端课程知识点记录插图(6)

④ 如果中间有报错,如下:
npm ERR! code EPERM
npm ERR! syscall mkdir
npm ERR! path C:\Program Files
odejs
ode_cache\_cacache\index-v5\ee\aa
npm ERR! errno -4048
npm ERR! Error: EPERM: operation not permitted, mkdir ‘C:\Program Files
odejs
ode_cache\_cacache\index-v5\ee\aa’

找到nodejs的安装目录,右击属性->安全->编辑->把所有权限都勾选上
《苍穹外卖》前端课程知识点记录插图(7)

⑤ 结果:

《苍穹外卖》前端课程知识点记录插图(8)

《苍穹外卖》前端课程知识点记录插图(9)

  • 方式二:vue ui

①打开ui界面

《苍穹外卖》前端课程知识点记录插图(10)

② 点击创建

《苍穹外卖》前端课程知识点记录插图(11)

③ 填写项目信息

《苍穹外卖》前端课程知识点记录插图(12)

④ 选择vue2,创建项目

《苍穹外卖》前端课程知识点记录插图(13)

⑤结果:

《苍穹外卖》前端课程知识点记录插图(14)

项目结构

《苍穹外卖》前端课程知识点记录插图(15)

运行项目

npm run serve

命令的最后一个单词并不是固定的,与package.json下写的这一项相关,如下

《苍穹外卖》前端课程知识点记录插图(16)

如果8080端口号被占用,可以在vue.config.js中更改端口号

《苍穹外卖》前端课程知识点记录插图(17)

《苍穹外卖》前端课程知识点记录插图(18)

如果上面这种方式不起作用的,可以到项目对应文件夹用cmd试试

《苍穹外卖》前端课程知识点记录插图(19)

《苍穹外卖》前端课程知识点记录插图(20)

退出运行:Ctrl + C

vue基本使用方式

Vue组件(Vue2)

Vue的组件文件以.vue结尾,每个组件由三部分组成:结构、样式、逻辑。

《苍穹外卖》前端课程知识点记录插图(21)

示例

《苍穹外卖》前端课程知识点记录插图(22)

Vue 2:一个Vue组件的模板只能有一个根元素。这是因为Vue 2使用的是基于AST(抽象语法树)的模板编译方式,需要将模板编译为render函数,而render函数只能返回一个根节点。

Vue 3 : Vue的模板编译器进行了重大改进,支持多个根元素。Vue 3使用了基于编译器的模板编译方式,这意味着在Vue 3中,一个组件的模板可以有多个根元素,而不再需要包裹在一个单独的根元素内。

文本插值

作用:用来绑定 data 方法返回的对象属性

用法:{{}}

《苍穹外卖》前端课程知识点记录插图(23)

《苍穹外卖》前端课程知识点记录插图(24)

属性绑定

作用:为标签的属性绑定data方法中返回的属性

用法:v-bind:xxx,简写为 :xxx

《苍穹外卖》前端课程知识点记录插图(25)

事件绑定

作用:为元素绑定对应的事件

用法:v-on:xxx,简写为@xxx

《苍穹外卖》前端课程知识点记录插图(26)

双向绑定

作用:表单输入项和data方法中的属性进行绑定,任意一方改变都会同步给另一方

用法:v-model

《苍穹外卖》前端课程知识点记录插图(27)

条件渲染

作用:根据表达式的值来动态渲染页面元素

用法:v-ifv-elsev-else-if

《苍穹外卖》前端课程知识点记录插图(28)

axios

Axios是一个基于promise的网络请求库,作用于浏览器和node.js中

安装命令:npm install axios

导入命令:import axios from ‘axios’

《苍穹外卖》前端课程知识点记录插图(29)

axios的API列表:

请求备注
axios.get(url[, config])
axios.delete(url[, config])
axios.head(url[, config])
axios.options(url[, config])
axios.post(url[, data[, config]])
axios.put(url, data[, config]])
axios.patch(url[, data[, config]])

参数说明:

  • url:请求路径
  • data:请求体数据,最常见的是JSON格式数据
  • config:配置对象,可以设置查询参数、请求体信息

为了解决跨域问题,可以在vue.config.js文件中配置代理:

《苍穹外卖》前端课程知识点记录插图(30)

 axios统一使用方式:axios(config)

《苍穹外卖》前端课程知识点记录插图(31)

请求配置

网址:请求配置 | Axios中文文档 | Axios中文网 (axios-http.cn)

{
  // `url` 是用于请求的服务器 URL
  url: '/user',

  // `method` 是创建请求时使用的方法
  method: 'get', // 默认值

  // `baseURL` 将自动加在 `url` 前面,除非 `url` 是一个绝对 URL。
  // 它可以通过设置一个 `baseURL` 便于为 axios 实例的方法传递相对 URL
  baseURL: 'https://some-domain.com/api/',

  // `transformRequest` 允许在向服务器发送前,修改请求数据
  // 它只能用于 'PUT', 'POST' 和 'PATCH' 这几个请求方法
  // 数组中最后一个函数必须返回一个字符串, 一个Buffer实例,ArrayBuffer,FormData,或 Stream
  // 你可以修改请求头。
  transformRequest: [function (data, headers) {
    // 对发送的 data 进行任意转换处理

    return data;
  }],

  // `transformResponse` 在传递给 then/catch 前,允许修改响应数据
  transformResponse: [function (data) {
    // 对接收的 data 进行任意转换处理

    return data;
  }],

  // 自定义请求头
  headers: {'X-Requested-With': 'XMLHttpRequest'},

  // `params` 是与请求一起发送的 URL 参数
  // 必须是一个简单对象或 URLSearchParams 对象
  params: {
    ID: 12345
  },

  // `paramsSerializer`是可选方法,主要用于序列化`params`
  // (e.g. https://www.npmjs.com/package/qs, http://api.jquery.com/jquery.param/)
  paramsSerializer: function (params) {
    return Qs.stringify(params, {arrayFormat: 'brackets'})
  },

  // `data` 是作为请求体被发送的数据
  // 仅适用 'PUT', 'POST', 'DELETE 和 'PATCH' 请求方法
  // 在没有设置 `transformRequest` 时,则必须是以下类型之一:
  // - string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams
  // - 浏览器专属: FormData, File, Blob
  // - Node 专属: Stream, Buffer
  data: {
    firstName: 'Fred'
  },
  
  // 发送请求体数据的可选语法
  // 请求方式 post
  // 只有 value 会被发送,key 则不会
  data: 'Country=Brasil&City=Belo Horizonte',

  // `timeout` 指定请求超时的毫秒数。
  // 如果请求时间超过 `timeout` 的值,则请求会被中断
  timeout: 1000, // 默认值是 `0` (永不超时)

  // `withCredentials` 表示跨域请求时是否需要使用凭证
  withCredentials: false, // default

  // `adapter` 允许自定义处理请求,这使测试更加容易。
  // 返回一个 promise 并提供一个有效的响应 (参见 lib/adapters/README.md)。
  adapter: function (config) {
    /* ... */
  },

  // `auth` HTTP Basic Auth
  auth: {
    username: 'janedoe',
    password: 's00pers3cret'
  },

  // `responseType` 表示浏览器将要响应的数据类型
  // 选项包括: 'arraybuffer', 'document', 'json', 'text', 'stream'
  // 浏览器专属:'blob'
  responseType: 'json', // 默认值

  // `responseEncoding` 表示用于解码响应的编码 (Node.js 专属)
  // 注意:忽略 `responseType` 的值为 'stream',或者是客户端请求
  // Note: Ignored for `responseType` of 'stream' or client-side requests
  responseEncoding: 'utf8', // 默认值

  // `xsrfCookieName` 是 xsrf token 的值,被用作 cookie 的名称
  xsrfCookieName: 'XSRF-TOKEN', // 默认值

  // `xsrfHeaderName` 是带有 xsrf token 值的http 请求头名称
  xsrfHeaderName: 'X-XSRF-TOKEN', // 默认值

  // `onUploadProgress` 允许为上传处理进度事件
  // 浏览器专属
  onUploadProgress: function (progressEvent) {
    // 处理原生进度事件
  },

  // `onDownloadProgress` 允许为下载处理进度事件
  // 浏览器专属
  onDownloadProgress: function (progressEvent) {
    // 处理原生进度事件
  },

  // `maxContentLength` 定义了node.js中允许的HTTP响应内容的最大字节数
  maxContentLength: 2000,

  // `maxBodyLength`(仅Node)定义允许的http请求内容的最大字节数
  maxBodyLength: 2000,

  // `validateStatus` 定义了对于给定的 HTTP状态码是 resolve 还是 reject promise。
  // 如果 `validateStatus` 返回 `true` (或者设置为 `null` 或 `undefined`),
  // 则promise 将会 resolved,否则是 rejected。
  validateStatus: function (status) {
    return status >= 200 && status < 300; // 默认值
  },

  // `maxRedirects` 定义了在node.js中要遵循的最大重定向数。
  // 如果设置为0,则不会进行重定向
  maxRedirects: 5, // 默认值

  // `socketPath` 定义了在node.js中使用的UNIX套接字。
  // e.g. '/var/run/docker.sock' 发送请求到 docker 守护进程。
  // 只能指定 `socketPath` 或 `proxy` 。
  // 若都指定,这使用 `socketPath` 。
  socketPath: null, // default

  // `httpAgent` and `httpsAgent` define a custom agent to be used when performing http
  // and https requests, respectively, in node.js. This allows options to be added like
  // `keepAlive` that are not enabled by default.
  httpAgent: new http.Agent({ keepAlive: true }),
  httpsAgent: new https.Agent({ keepAlive: true }),

  // `proxy` 定义了代理服务器的主机名,端口和协议。
  // 您可以使用常规的`http_proxy` 和 `https_proxy` 环境变量。
  // 使用 `false` 可以禁用代理功能,同时环境变量也会被忽略。
  // `auth`表示应使用HTTP Basic auth连接到代理,并且提供凭据。
  // 这将设置一个 `Proxy-Authorization` 请求头,它会覆盖 `headers` 中已存在的自定义 `Proxy-Authorization` 请求头。
  // 如果代理服务器使用 HTTPS,则必须设置 protocol 为`https`
  proxy: {
    protocol: 'https',
    host: '127.0.0.1',
    port: 9000,
    auth: {
      username: 'mikeymike',
      password: 'rapunz3l'
    }
  },

  // see https://axios-http.com/zh/docs/cancellation
  cancelToken: new CancelToken(function (cancel) {
  }),

  // `decompress` indicates whether or not the response body should be decompressed 
  // automatically. If set to `true` will also remove the 'content-encoding' header 
  // from the responses objects of all decompressed responses
  // - Node only (XHR cannot turn off decompression)
  decompress: true // 默认值

}

示例——配置代理

记得要先运行后端服务,启动redis

HelloWorld.vue


  

    
    

    

  






h3 {
  margin: 40px 0 0;
}
ul {
  list-style-type: none;
  padding: 0;
}
li {
  display: inline-block;
  margin: 0 10px;
}
a {
  color: #42b983;
}

vue.config.js

const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
  transpileDependencies: true,
  devServer:{
    port:8082,
    proxy: {
      '/api' : {
        target: 'http://localhost:8081',
        pathRewrite: {
          '^/api' : ''
        }
      }
    }
  }
})

结果

《苍穹外卖》前端课程知识点记录插图(32)

《苍穹外卖》前端课程知识点记录插图(33)

《苍穹外卖》前端课程知识点记录插图(34)

二、VUE进阶(router、vuex、typescript)

路由 Vue-Router

Vue-Router介绍

vue属于单页面应用,所谓的路由,就是根据浏览器路径不同,用不同的视图组件替换这个页面内容。

vue应用中如何实现路由?

  • 通过vue-router实现路由功能,需要安装js库(npm install vue-router)

基于Vue CLI创建带有路由功能的前端项目

命令:vue ui

①包管理器选择:npm

《苍穹外卖》前端课程知识点记录插图(35)

②预设选择:手动

《苍穹外卖》前端课程知识点记录插图(36)

③功能添加:Router

《苍穹外卖》前端课程知识点记录插图(37)

④配置版本选择:2.x,linter config选择:ESLint with error prevention only

《苍穹外卖》前端课程知识点记录插图(38)

⑤选择创建项目,不保存预设

《苍穹外卖》前端课程知识点记录插图(39)

⑥查看创建结果

《苍穹外卖》前端课程知识点记录插图(40)

《苍穹外卖》前端课程知识点记录插图(41)

《苍穹外卖》前端课程知识点记录插图(42)

⑦运行项目

《苍穹外卖》前端课程知识点记录插图(43)

《苍穹外卖》前端课程知识点记录插图(44)

《苍穹外卖》前端课程知识点记录插图(45)

路由配置

路由组成

VueRouter:路由器,根据路由请求在路由视图中动态渲染对应的视图组件

:路由链接组件,浏览器会解析成

:路由视图组件,用来展示与路由匹配的视图组件

《苍穹外卖》前端课程知识点记录插图(46)

《苍穹外卖》前端课程知识点记录插图(47)

《苍穹外卖》前端课程知识点记录插图(48)

路由跳转

  • 标签式
  • 编程式

《苍穹外卖》前端课程知识点记录插图(49)

如果请求的路径不存在,应该如何处理?

①当上面的路径都匹配不到时,重定向到最后一项

《苍穹外卖》前端课程知识点记录插图(50)

《苍穹外卖》前端课程知识点记录插图(51)

《苍穹外卖》前端课程知识点记录插图(52)

嵌套路由

嵌套路由:组件内要切换内容,就需要用到嵌套路由(子路由)

实现步骤:

  • 安装并导入elementui,实现页面布局(Container布局容器)—ContainerView.vue
    npm i element-ui -S

    《苍穹外卖》前端课程知识点记录插图(53)
     

  • 提供子视图组件,用于效果展示 —P1View.vue、P2View.vue、P3View.vue
    view/container/ContainerView.vue
    
      
        Header
        
          Aside
          Main
        
      
    
    
    
    
    
      .el-header, .el-footer {
        background-color: #B3C0D1;
        color: #333;
        text-align: center;
        line-height: 60px;
      }
      
      .el-aside {
        background-color: #D3DCE6;
        color: #333;
        text-align: center;
        line-height: 200px;
      }
      
      .el-main {
        background-color: #E9EEF3;
        color: #333;
        text-align: center;
        line-height: 160px;
      }
      
      body > .el-container {
        margin-bottom: 40px;
      }
      
      .el-container:nth-child(5) .el-aside,
      .el-container:nth-child(6) .el-aside {
        line-height: 260px;
      }
      
      .el-container:nth-child(7) .el-aside {
        line-height: 320px;
      }
    

    《苍穹外卖》前端课程知识点记录插图(54)《苍穹外卖》前端课程知识点记录插图(55)

  • 在src/router/index.js中配置路由映射规则(嵌套路由配置)
    《苍穹外卖》前端课程知识点记录插图(56)
  • 在布局容器视图中添加,实现子视图组件展示
    《苍穹外卖》前端课程知识点记录插图(57)
  • 在布局容器视图中添加,实现路由请求
    《苍穹外卖》前端课程知识点记录插图(58)
    《苍穹外卖》前端课程知识点记录插图(59)

注意事项:子路由变化,切换的是【ContainerView组件】中‘’部分的内容。

思考

1. 对于前面的案例,如果用户访问的路由是/c,会有什么效果呢?

《苍穹外卖》前端课程知识点记录插图(60)

2. 如果实现在访问/c时,默认就展示某个子视图组件呢?

《苍穹外卖》前端课程知识点记录插图(61)

状态管理vuex

vuex介绍

  • vuex是一个专为Vue.js应用程序开发的状态管理库
  • vuex可以在多个组件之间共享数据,并且共享的数据是响应式的,即数据的变更能及时渲染到模板
  • vuex采用集中式存储管理所有组件的状态

安装

npm install vuex@next --save

核心概念

  • state:状态对象,集中定义各个组件共享的数据
  • mutations:类似于一个事件,用于修改共享数据,要求必须是同步函数
  • actions:类似于mutation,可以包含异步操作,通过调用mutation来改变共享数据

使用方式

①创建带有vuex功能的脚手架工程

《苍穹外卖》前端课程知识点记录插图(62)

②src/store/index.js

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

// 集中管理多个组件共享的数据
export default new Vuex.Store({
  state: {
  },
  getters: {
  },
  mutations: {
  },
  actions: {
  },
  modules: {
  }
})

③src/main.js

import Vue from 'vue'
import App from './App.vue'
import store from './store'

Vue.config.productionTip = false

new Vue({
  // 使用vuex功能
  store,
  render: h => h(App)
}).$mount('#app')

④定义和展示共享数据

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

// 集中管理多个组件共享的数据
export default new Vuex.Store({
  // 集中定义共享数据
  state: {
    name: '未登录游客'
  },
  getters: {
  },
  mutations: {
  },
  actions: {
  },
  modules: {
  }
})

⑤在mutations中定义函数,修改共享数据

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

// 集中管理多个组件共享的数据
export default new Vuex.Store({
  // 集中定义共享数据
  state: {
    name: '未登录游客'
  },
  getters: {
  },
  // 修改共享数据只能通过mutation实现,必须是同步操作
  mutations: {
    setName(state, newName) {
      state.name = newName
    }
  },
  // 通过actions可以调用mutations,在action中可以进行异步操作
  actions: {
  },
  modules: {
  }
})

  
    欢迎您,{{$store.state.name}}

    
    《苍穹外卖》前端课程知识点记录插图(63)
    
  





#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}

④在actions中定义函数,用于调用mutation

先安装axios

npm install axios
// src/store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import axios from 'axios'

Vue.use(Vuex)

// 集中管理多个组件共享的数据
export default new Vuex.Store({
  // 集中定义共享数据
  state: {
    name: '未登录游客'
  },
  getters: {
  },
  // 修改共享数据只能通过mutation实现,必须是同步操作
  mutations: {
    setName(state, newName) {
      state.name = newName
    }
  },
  // 通过actions可以调用mutations,在action中可以进行异步操作
  actions: {
    setNameByAxios(context) {
      axios ({
        url: '/api/admin/employee/login',
        method: 'post',
        data: {
          username: 'admin',
          password: '123456'
        }
      }).then(res => {
        if(res.data.code == 1) {
          // 异步请求后,需要修改共享数据
          // 调用mutation中定义的setName函数
          context.commit('setName', res.data.data.name)
        }
      })
    }
  },
  modules: {
  }
})
// App.vue

  
    欢迎您,{{$store.state.name}}

    
    
    《苍穹外卖》前端课程知识点记录插图(63)
    
  





#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}

// vue.config.js
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
  transpileDependencies: true,
  devServer: {
    port:8082,
    proxy: {
      '/api': {
        target: 'http://location:8081',
        pathRewrite: {
          '^/api': ''
        }
      }
    }
  }
})

《苍穹外卖》前端课程知识点记录插图(64)

思考

1. 如何理解vuex?

  • 实现多个组件之间的数据共享
  • 共享数据是响应式的,实时渲染到模板
  • 可以集中管理共享数据

2. 如何使用vuex?

  • 在store对象的state属性中定义共享数据
  • 在store对象的mutations属性中定义修改共享数据的函数
  • 在store对象的actions属性中定义调用mutation的函数,可以进行异或操作
  • mutations中的函数不能直接调用,只能通过store对象的commit方法调用
  • actions中定义的函数不能直接调用,只能通过store对象的dispatch方法调用

TypeScript

TypeScript介绍

  • TypeScript(简称:TS)是微软推出的开源语言
  • TypeScript是JavaScript的超集(JS有的TS都有)
  • TypeScript = Type + JavaScript(在JS基础上增加了类型支持)
  • TypeScript文件扩展名为ts
  • TypeScript可编译成标准的JavaScript,并且在编译时进行类型检查

安装typescript(全局安装)

如果安装失败,以管理员身份运行命令行窗口,可以在安装命令后加上 @5.0.2,以指定版本

npm install -g typescript

查看TS版本

tsc -v

示例

// 通过ts代码,指定函数的参数类型为string
function hello(msg:string) {
        console.log(msg)
}

// 传入的参数类型为number
hello(123)

编译:tsc + 文件名

《苍穹外卖》前端课程知识点记录插图(65)

改正后(传参为:’123’)

《苍穹外卖》前端课程知识点记录插图(66)

思考

1. TS为什么要增加类型支持?

  • TS属于静态类型编程语言,JS属于动态类型编程语言
  • 静态类型在编译期做类型检查,动态类型在执行期间做类型检查
  • 对于JS来说,需要等到代码执行的时候才可以发现错误(晚)
  • 对于TS来说,在代码编译的时候就可以发现错误(早)
  • 配合VSCode开发工具,TS可以提前在编写代码的同时就发现代码中的错误,减少找Bug、改Bug的时间

2. 如何理解TypeScript?

  • 是JavaScript的超集,兼容JavaScript
  • 扩展了JavaScript的语法,文件扩展名为ts
  • 可以编译成标准的JavaScript,并且可以在编译时进行类型检查
  • 全局安装npm install -g typescript
  • 视图tsc命令将ts文件编译成js文件
  • 使用node命令运行js文件

TypeScript常用类型

类型备注
字符串类型string
数字类型number
布尔类型boolean
数组类型number[], string[], boolean[]依此类推
任意类型any相当于又回到了没有类型的时代
复杂类型type与interface
函数类型() => void对函数的参数和返回值进行说明
字面量类型“a”|”b”|”c”限制变量或参数的取值
class类class Animal

类型标注的位置

  • 标注变量
  • 标注参数
  • 标注返回值

《苍穹外卖》前端课程知识点记录插图(67)

项目示例

1. 创建项目时勾选上TypeScript、Router、Vuex

《苍穹外卖》前端课程知识点记录插图(68)

2. 字符串类型、布尔类型、数字类型

// 字符串类型
let username: string = 'itcast'

// 数字类型
let age: number = 20

// 布尔类型
let isTrue: boolean = true

console.log(username)
console.log(age)
console.log(isTrue)

3. 字面量类型

// 字面量类型
function printText(s: string, alignment: 'left'|'right'|'center') {
    console.log(s, alignment)
}

printText('hello', 'left')
printText('hello', 'right')

4. 复杂类型——interface

小技巧:可以通过在属性名后面加上?,表示当前属性为可选

// 定义接口
interface Cat {
    name: string,
    age: number
}


// 定义变量为Cat类型
const c1: Cat = {name: '小白', age: 1}
// const c2: Cat = {name: '小白'}  // 错误:缺少age属性
// const c3: Cat = {name: '小白', age: 1, sex: '公'}  // 错误:多了sex属性

console.log(c1)

5. class类

注意:使用class关键字来定义类,类中可以包含属性、构造方法、普通方法

// 定义一个类,使用class关键字
class User {
    name: string;  // 属性
    constructor(name: string) {
        // 构造方法
        this.name = name
    }
    // 方法
    study() {
        console.log(this.name + '正在学习')
    }
}

// 使用User类型
const user = new User('张三')
// 输出类中的属性
console.log(user.name)
// 调用类中的方法
user.study()

6. Class类实现interface

interface Animal {
    name: string
    eat(): void
}

// 定义一个类Bird,实现上面的Animal接口
class Bird implements Animal {
    name: string
    constructor(name: string) {
        this.name = name
    }
    eat(): void {
        console.log(this.name + ' eat')
    }
}

// 创建类型为Bird的对象
const b1 = new Bird('杜鹃')
console.log(b1.name)
b1.eat()

7. class类——类的继承


// 定义一个类Bird,实现上面的Animal接口
class Bird implements Animal {
    name: string
    constructor(name: string) {
        this.name = name
    }
    eat(): void {
        console.log(this.name + ' eat')
    }
}


// 定义Parrot类,并且继承Bird类
class Parrot extends Bird {
    say():void {
        console.log(this.name + ' say hello')
    }
}
const myParrot = new Parrot('Polly')
myParrot.say()
myParrot.eat()

小结

1.TypeScript的常用类型有哪些?

  • string、number、boolean
  • 字面量、void
  • interface、class

2. TypeScript文件能直接运行吗?

  • 需要将TS文件编译为JS文件才能运行
  • 编译后的JS文件中类型会擦除

三、苍穹外卖前端项目环境搭建、员工管理

技术选型

  • node.js
  • vue
  • ElementUI
  • axios
  • vuex
  • vue-router
  • typescript

熟悉前端代码结构

1. 代码导入:直接导入课程资料中提供的前端工程,在此基础上开发即可

在苍穹外卖前端课程->资料->day02->资料->苍穹外卖前端初始工程

2. 重点文件/目录

《苍穹外卖》前端课程知识点记录插图(69)3. 通过登录功能梳理前端代码

①先运行后端服务

②下载前端中的依赖(不需要指定安装哪些包,会自动扫描):npm install

把nodejs的版本降级到12版本,如果出现安全性问题,代开cmd执行下面的命令

可以参考这篇文章:node.js安装配置详细介绍以及nodejs版本降级_nodejs低版本-CSDN博客

我是把node.js降级到了12.22.12

npm config set strict-ssl false

《苍穹外卖》前端课程知识点记录插图(70)

npm install

④修改后端服务的地址(如果前面课程中修改了后端服务的端口号)

《苍穹外卖》前端课程知识点记录插图(71)

⑤npm run serve,前端的端口号为8888

《苍穹外卖》前端课程知识点记录插图(72)

⑥通过登录功能梳理前端代码

  • 获得登录页面路由地址
  • 从main.ts中找到路由文件
  • 从路由文件中找到登录视图组件
  • 从登录视图组件中找到登录方法
  • 跟踪登录方法的执行过程

员工分页查询

需求分析和接口设计

业务规则

根据页码展示员工信息

每页展示10条数据

分页查询可以根据需要,输入员工姓名进行查询

接口设计

《苍穹外卖》前端课程知识点记录插图(73)

代码开发

①从路由文件router.ts中找到员工管理页面(组件)

《苍穹外卖》前端课程知识点记录插图(74)

②初始页面

《苍穹外卖》前端课程知识点记录插图(75)

③制作页面头部效果

《苍穹外卖》前端课程知识点记录插图(76)

    
      
        
        
        查询
         + 添加员工
      
    

注意

  • 输入框和按钮都是使用ElementUI提供的组件
  • 对于前端的组件只需要参考ElementUI提供的文档,进行修改即可

链接:Element – The world’s most popular Vue UI framework

④员工分页查询

src/api/employee.ts

// 分页查询
export const getEmployeeList = (params: any) =>
  request({
    'url': `/employee/page`,
    'method': 'get',
    'params': params
  })

src/view/employee/index.vue


  
    
      
        
        
        查询
         + 添加员工
      

      
        
        
        
        
         
        
          
            {{ scope.row.status === 0 ? '禁用' : '启用' }}
          
        
        
        
        
          
            修改
            {{
              scope.row.status === 1 ? '禁用' : '启用'
            }}
          
        
      

      
      
    
  





.disabled-text {
  color: #bac0cd !important;
}

功能测试

《苍穹外卖》前端课程知识点记录插图(77)

启用、禁用员工账号

需求分析和接口设计

业务规则

可以对状态为“启用”的员工账号进行“禁用”操作

可以对状态为“禁用”的员工账号进行“启用”操作

状态为“禁用”的员工账号不能登录系统

接口设计

《苍穹外卖》前端课程知识点记录插图(78)

代码开发

①src/api/employee.ts

// 启用禁用员工账号
export const enableOrDisableEmployee = (params: any) =>
  request({
    'url': `/employee/status/${params.status}`,
    'method': 'post',
    'params': {id: params.id}
  })

②src/view/employee/index.vue


  
    
      
        
        
        查询
         + 添加员工
      

      
        
        
        
        
         
        
          
            {{ scope.row.status === 0 ? '禁用' : '启用' }}
          
        
        
        
        
          
            修改
            {{scope.row.status === 1 ? '禁用' : '启用'}}
          
        
      

      
      
    
  





.disabled-text {
  color: #bac0cd !important;
}

功能测试

《苍穹外卖》前端课程知识点记录插图(79)

添加员工

需求分析和接口设计

产品原型

《苍穹外卖》前端课程知识点记录插图(80)

接口设计

《苍穹外卖》前端课程知识点记录插图(81)

代码开发

添加员工操作步骤

  • 点击“添加员工”按钮,跳转到新增页面
  • 在新增员工页面录入员工相关信息
  • 点击“保存”按钮完成新增操作

①为“添加员工”按钮绑定单击事件:src/views/employee/index.vue

《苍穹外卖》前端课程知识点记录插图(82)

②提供handleAddEmp方法,进行路由跳转

《苍穹外卖》前端课程知识点记录插图(83)

《苍穹外卖》前端课程知识点记录插图(84)

③src/api/employee.ts

  // 新增员工
export const addEmployee = (params: any) =>
  request({
    'url': '/employee',
    'method': 'post',
    'data': params
  })

④src/views/employee/addEmployee.vue


  
    
      
        
          
        
        
          
        
        
          
        
        
            男
            女
        
        
          
        
        
          保存
          保存并继续添加员工
          
           this.$router.push('/employee')">返回
        
      
    
  





.addBrand {
  &-container {
    margin: 30px;
    margin-top: 30px;
    .HeadLable {
      background-color: transparent;
      margin-bottom: 0px;
      padding-left: 0px;
    }
    .container {
      position: relative;
      z-index: 1;
      background: #fff;
      padding: 30px;
      border-radius: 4px;
      // min-height: 500px;
      .subBox {
        padding-top: 30px;
        text-align: center;
        border-top: solid 1px $gray-5;
      }
    }
    .idNumber {
      margin-bottom: 39px;
    }

    .el-form-item {
      margin-bottom: 29px;
    }
    .el-input {
      width: 293px;
    }
  }
}

功能测试

《苍穹外卖》前端课程知识点记录插图(85)

修改员工

需求分析和接口设计

产品原型

《苍穹外卖》前端课程知识点记录插图(86)

编辑员工功能涉及到两个接口:

  • 根据id查询员工信息
  • 编辑员工信息

《苍穹外卖》前端课程知识点记录插图(87)

《苍穹外卖》前端课程知识点记录插图(88)

代码开发

修改员工操作步骤:

  • 点击“修改”按钮,跳转到修改页面
  • 在修改员工页面录入员工相关信息
  • 点击“保存”按钮完成修改操作

注意

  • 由于添加员工和修改员工的表单项非常类似,所以添加和修改操作可以共用同一个页面addEmployee.vue
  • 修改员工设计原数据回显,所以需要传递员工id作为参数

①src/views/employee/index.vue,在员工管理页面中,为“修改”按钮绑定单击事件,用于跳转到修改页面

《苍穹外卖》前端课程知识点记录插图(89)

    // 跳转到修改员工页面(组件)
    handleUpdateEmp(row) {
      if(row.username === 'admin') {
        // 如果是内置管理员账号,不允许修改
        this.$message.error('admin为系统的管理员账号,不能修改!')
        return
      }
      // 跳转到修改页面,通过地址栏传递参数
      this.$router.push({
        path: '/employee/add',
        query: {id: row.id}
      })
    }

②由于addEmployee.vue为新增和修改共用页面,需要能够区分当前操作:

  • 如果路由中传递了id参数,则当前操作为修改
  • 如果路由中没有传递id参数,则当前操作为新增

《苍穹外卖》前端课程知识点记录插图(90)

③根据id查询员工,src/api/employee.ts

  // 根据id查询员工
export const queryEmployeeById = (id: number) =>
  request({
    'url': `/employee/${id}`,
    'method': 'get'
  })

④数据回显,src/views/employee/addEmployee.vue

《苍穹外卖》前端课程知识点记录插图(91)

⑤修改员工信息,src/api/employee.ts

// 修改员工
export const updateEmployee = (params: any) =>
  request({
    'url': '/employee',
    'method': 'put',
    'data': params
  })

⑥src/views/employee/addEmployee.vue

import { addEmployee, queryEmployeeById, updateEmployee} from '@/api/employee'
export default {
  data() {
    return {
      optType: '', // 当前新增的类型为新增或者修改
      ruleForm: {
        name: '',
        username: '',
        sex: '1',
        phone: '',
        idNumber: '',
      },
      rules: {
        name: [{ required: true, message: '请输入员工姓名', trigger: 'blur' }],
        username: [
          { required: true, message: '请输入员工账号', trigger: 'blur' },
        ],
        phone: [
          {
            required: true,
            trigger: 'blur',
            validator: (rule, value, callback) => {
              if (value === '' || !/^1(3|4|5|6|7|8)\d{9}$/.test(value)) {
                callback(new Error('请输入正确的手机号!'))
              } else {
                callback()
              }
            },
          },
        ],
        idNumber: [
          {
            required: true,
            trigger: 'blur',
            validator: (rule, value, callback) => {
              if (
                value === '' ||
                !/(^\d{15}$)|(^\d{18}$)|(^\d{17}(X|x)$)/.test(value)
              ) {
                callback(new Error('请输入正确的身份证号!'))
              } else {
                callback()
              }
            },
          },
        ],
      },
    }
  },
  // 页面加载完成执行的代码
  created() {
    // 获取路由参数{id},如果有则为修改操作,否则为新增操作
    this.optType = this.$route.query.id ? 'update' : 'add'
    if (this.optType === 'update') {
      // 修改操作,需要根据id查询员工信息用于页面回显
      queryEmployeeById(this.$route.query.id).then((res) => {
        if (res.data.code === 1) {
          this.ruleForm = res.data.data
        }
      })
    }
  },
  methods: {
    submitForm(formName, isContinue) {
      // 进行表单校验
      this.$refs[formName].validate((valid) => {
        if (valid) {
          // alert('所有表单项都符合要求')
          // 表单校验通过,发起Ajax请求,将数据提交到后端

          if (this.optType === 'add') {
            // 新增操作
            addEmployee(this.ruleForm).then((res) => {
              if (res.data.code === 1) {
                this.$message.success('员工添加成功!')
                if (isContinue) {
                  // 保存并继续添加
                  this.ruleForm = {
                    name: '',
                    username: '',
                    sex: '1',
                    phone: '',
                    idNumber: '',
                  }
                } else {
                  this.$router.push('/employee')
                }
              } else {
                this.$message.error(res.data.msg)
              }
            })
          } else {
            // 修改操作
            updateEmployee(this.ruleForm).then(res => {
              if(res.data.code == 1) {
                this.$message.success('员工信息修改成功!')
                this.$router.push('/employee')
              }
            })
          }
        }
      })
    },
  },
}

功能测试

《苍穹外卖》前端课程知识点记录插图(92)

四、套餐管理

套餐分页查询

需求分析和接口设计

产品原型

《苍穹外卖》前端课程知识点记录插图(93)

业务规则

  • 根据页码展示套餐信息
  • 每页展示10条数据
  • 分页查询时可以根据需要输入套餐名称、套餐分类、售卖状态进行查询

接口设计

  • 套餐分页查询接口
  • 分类查询接口(用于下拉框中分类数据显示)

《苍穹外卖》前端课程知识点记录插图(94)

《苍穹外卖》前端课程知识点记录插图(95)

代码开发

①从路由文件router.ts中找到套餐管理页面(组件)

《苍穹外卖》前端课程知识点记录插图(96)

②制作页面头部效果,src/views/setmeal/index.vue


  
    
      
        
          
          
          
          
          
            
            
          

          
          
            
            
          

          查询

          
            批量删除
            +新建套餐
          
        
      

    
  




.el-table-column--selection .cell {
  padding-left: 10px;
}


.dashboard {
  &-container {
    margin: 30px;

    .container {
      background: #fff;
      position: relative;
      z-index: 1;
      padding: 30px 28px;
      border-radius: 4px;

      .tableBar {
        margin-bottom: 20px;
        .tableLab {
          float: right;
          span {
            cursor: pointer;
            display: inline-block;
            font-size: 14px;
            padding: 0 20px;
            color: $gray-2;
          }
        }
      }

      .tableBox {
        width: 100%;
        border: 1px solid $gray-5;
        border-bottom: 0;
      }

      .pageList {
        text-align: center;
        margin-top: 30px;
      }
      //查询黑色按钮样式
      .normal-btn {
        background: #333333;
        color: white;
        margin-left: 20px;
      }
    }
  }
}

《苍穹外卖》前端课程知识点记录插图(97)

注意

  • 输入框、按钮、下拉框都是使用ElementUI提供的组件
  • 对于前端的组件只需要参考ElementUI提供的文档,进行修改即可

③导入查询套餐分类的JS方法,动态填充套餐分类下拉框,src/views/setmeal/index.vue

《苍穹外卖》前端课程知识点记录插图(98)

《苍穹外卖》前端课程知识点记录插图(99)

完整代码(做了一些小调整)


  
    
      
        
          
          
          
          
          
            
            
          

          
          
            
            
          

          查询

          
            批量删除
            +新建套餐
          
        
      

    
  




.el-table-column--selection .cell {
  padding-left: 10px;
}


.dashboard {
  &-container {
    margin: 30px;

    .container {
      background: #fff;
      position: relative;
      z-index: 1;
      padding: 30px 28px;
      border-radius: 4px;

      .tableBar {
        margin-bottom: 20px;
        .tableLab {
          float: right;
          span {
            cursor: pointer;
            display: inline-block;
            font-size: 14px;
            padding: 0 20px;
            color: $gray-2;
          }
        }
      }

      .tableBox {
        width: 100%;
        border: 1px solid $gray-5;
        border-bottom: 0;
      }

      .pageList {
        text-align: center;
        margin-top: 30px;
      }
      //查询黑色按钮样式
      .normal-btn {
        background: #333333;
        color: white;
        margin-left: 20px;
      }
    }
  }
}

src/api/category.ts

// 根据类型查询分类:1为菜品分类 2为套餐分类
export const getCategoryByType = (params: any) => {
  return request({
    url: `/category/list`,
    method: 'get',
    params: params
  })
}

④为查询按钮绑定事件,发送Ajax请求获取分页数据

src/api/setMeal.js

//套餐分页查询
export const getSetmealPage = (params: any) => {
    return request({
        url: '/setmeal/page',
        method: 'GET',
        params: params
    })
}

src/views/setmeal/index.vue

《苍穹外卖》前端课程知识点记录插图(100)

⑤分页查询,src/views/setmeal/index.vue

        
          
          
          
            
              
            
          
          
          
          
            
              
                {{ scope.row.status === 0 ? '停售' : '启售' }}
              
            
          
          
          
            
               修改 
              
                {{ scope.row.status == '1' ? '停售' : '启售' }}
              
               删除 
            
          
        
        

《苍穹外卖》前端课程知识点记录插图(101)

功能测试

《苍穹外卖》前端课程知识点记录插图(102)

启售停售套餐

需求分析和接口设计

产品原型

《苍穹外卖》前端课程知识点记录插图(103)

业务规则

  • 可以对状态为“启售”的套餐进行“停售:操作
  • 可以对状态为”停售“的套餐进行”启售“操作

接口设计

《苍穹外卖》前端课程知识点记录插图(104)

代码开发

①为启售、停售按钮绑定单击事件,src/views/setmeal/index.vue

《苍穹外卖》前端课程知识点记录插图(105)

import {getSetmealPage, enableOrDisableSetmeal, deleteSetmeal } from '@/api/setMeal'
    handleStartOrStop(row) {
      // alert(`id=${row.id} status=${row.status}`) 
       this.$confirm('确认调整该套餐的售卖状态?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      }).then(() => {
        enableOrDisableSetmeal({ id: row.id, status: !row.status ? 1 : 0 })
          .then((res) => {
            if (res.status === 200) {
              this.$message.success('套餐售卖状态更改成功!')
              this.pageQuery()
            }
          })
          .catch((err) => {
            this.$message.error('请求出错了:' + err.message)
          })
      })
    }

src/api/setMeal.ts

//套餐启售停售
export const enableOrDisableSetmeal = (params: any) => {
    return request({
        url: `/setmeal/status/${params.status}`,
        method: 'POST',
        params: {id: params.id}
    })
}

注意:这里测试时要运行redis-server,否则会出现下面的错误

《苍穹外卖》前端课程知识点记录插图(106)

功能测试

《苍穹外卖》前端课程知识点记录插图(107)

删除套餐

需求分析和设计

产品原型

《苍穹外卖》前端课程知识点记录插图(108)

业务规则

  • 点击删除按钮,删除指定的一个套餐
  • 勾选需要删除的套餐,点击批量删除按钮,删除选中的一个或多个套餐

接口设计

《苍穹外卖》前端课程知识点记录插图(109)

代码开发

①在src/api/setMeal.ts中封装删除套餐方法,发送Ajax请求

//删除套餐
export const deleteSetmeal = (ids: string) => {//1,2,3
    return request({
        url: '/setmeal',
        method: 'DELETE',
        params: {ids: ids}
    })
}

②在src/views/setmeal/index.vue书写删除按钮单击事件

    // 删除套餐
    handleDelete(type:string, id:string) {
        deleteSetmeal(id).then(res => {
          if(res.data.code === 1) {
            this.$message.success('删除成功!')
            this.pageQuery()
          } else {
            this.$message.error(res.data.msg)
          }
        })
    }

③批量删除

在src/views/setmeal/index.vue中添加模型数据

《苍穹外卖》前端课程知识点记录插图(110)

为批量删除按钮绑定单击事件

《苍穹外卖》前端课程知识点记录插图(111)

    // 删除套餐
    handleDelete(type:string, id:string) {

      this.$confirm('确认删除当前指定的套餐,是否继续?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      }).then(() => {
        let param = ''
        if(type == 'B') {
          // 批量删除
          // alert(this.multipleSelection.length)
          const arr = new Array
          this.multipleSelection.forEach(element => {
            arr.push(element.id)
          })
          param = arr.join(',')
        } else {
          // 单一删除
          param = id
        }
        deleteSetmeal(param).then(res => {
          if(res.data.code === 1) {
            this.$message.success('删除成功!')
            this.pageQuery()
          } else {
            this.$message.error(res.data.msg)
          }
        })
      })
    },

功能测试

《苍穹外卖》前端课程知识点记录插图(112)

新增套餐

需求分析和接口设计

产品原型

《苍穹外卖》前端课程知识点记录插图(113)

接口设计

  • 根据类型查询分类接口
    《苍穹外卖》前端课程知识点记录插图(114)
  • 根据分类查询菜品接口
    《苍穹外卖》前端课程知识点记录插图(115)
  • 文件上传接口
    《苍穹外卖》前端课程知识点记录插图(116)
  • 新增套餐接口
    《苍穹外卖》前端课程知识点记录插图(117)

代码解读

新增套餐操作步骤

①点击”新建套餐“按钮,跳转到新增页面,src/views/setmeal/index.vue

《苍穹外卖》前端课程知识点记录插图(118)

《苍穹外卖》前端课程知识点记录插图(119)

src/router.ts

《苍穹外卖》前端课程知识点记录插图(120)

②在套餐页面录入套餐相关信息,src/views/setmeal/addSetmeal.vue


  
    
      
        
          
            
          
          
            
              
            
          
        
        
          
            
          
        
        
          
            
              
                
                  + 添加菜品
                
                  
                    + 添加菜品
                  
                  
                    
                      
                      
                        
                          {{ (Number(scope.row.price).toFixed(2) * 100) / 100 }}
                        
                      
                      
                        
                          
                        
                      
                      
                        
                          
                            删除
                          
                        
                      
                    
                  
                
              
            
          
        
        
          
            
              图片大小不超过2M
仅能上传 PNG JPEG JPG类型图片
建议上传200*200或300*300尺寸的图片 $router.back()"> 取消 保存 保存并继续添加 取 消 添 加 .avatar-uploader .el-icon-plus:after { position: absolute; display: inline-block; content: ' ' !important; left: calc(50% - 20px); top: calc(50% - 40px); width: 40px; height: 40px; background: url('./../../assets/icons/icon_upload@2x.png') center center no-repeat; background-size: 20px; } // .el-form-item__error { // top: 90%; // } .addBrand-container { .avatar-uploader .el-upload { border: 1px dashed #d9d9d9; border-radius: 6px; cursor: pointer; position: relative; overflow: hidden; } .avatar-uploader .el-upload:hover { border-color: #ffc200; } .avatar-uploader-icon { font-size: 28px; color: #8c939d; width: 200px; height: 160px; line-height: 160px; text-align: center; } .avatar { width: 200px; height: 160px; display: block; } // .el-form--inline .el-form-item__content { // width: 293px; // } .el-input { width: 293px; } .address { .el-form-item__content { width: 777px !important; } } .el-input__prefix { top: 2px; } .addDish { .el-input { width: 130px; } .el-input-number__increase { border-left: solid 1px #fbe396; background: #fffbf0; } .el-input-number__decrease { border-right: solid 1px #fbe396; background: #fffbf0; } input { border: 1px solid #fbe396; } .table { border: solid 1px #ebeef5; border-radius: 3px; th { padding: 5px 0; } td { padding: 7px 0; } } } .addDishList { .seachDish { position: absolute; top: 12px; right: 20px; } .el-dialog__footer { padding-top: 27px; } .el-dialog__body { padding: 0; border-bottom: solid 1px #efefef; } .seachDish { .el-input__inner { height: 40px; line-height: 40px; } } } } .addBrand { &-container { margin: 30px; .container { position: relative; z-index: 1; background: #fff; padding: 30px; border-radius: 4px; min-height: 500px; .subBox { padding-top: 30px; text-align: center; border-top: solid 1px $gray-5; } .el-input { width: 350px; } .addDish { width: 777px; .addBut { background: #ffc200; display: inline-block; padding: 0px 20px; border-radius: 3px; line-height: 40px; cursor: pointer; border-radius: 4px; color: #333333; font-weight: 500; } .content { background: #fafafb; padding: 20px; border: solid 1px #d8dde3; border-radius: 3px; } } } } }

src/views/setmeal/components/AddDish.vue


  
    
      
        {{ item.name }}
      
      
        
          
            
          
           0"
                             v-model="checkedList"
                             @change="checkedListHandle">
            
              
                
                  {{
                    item.dishName
                  }}
                  {{ item.status == 0 ? '停售' : '在售' }}
                  {{ (Number(item.price) ).toFixed(2)*100/100 }}
                
              
            
          
        
      
    
    
      
        已选菜品({{ checkedListAll.length }})
      
      
        
          {{ item.dishName || item.name }}
          ¥ {{ (Number(item.price) ).toFixed(2)*100/100 }} 
          
            《苍穹外卖》前端课程知识点记录插图(121)
          
        
      
    
  




.addDish {
  .el-checkbox__label {
    width: 100%;
  }
  .empty-box {
    margin-top: 50px;
    margin-bottom: 0px;
  }
}


.addDish {
  padding: 0 20px;
  display: flex;
  line-height: 40px;
  .empty-box {
    img {
      width: 190px;
      height: 147px;
    }
  }

  .borderNone {
    border: none !important;
  }
  span,
  .tit {
    color: #333;
  }
  .leftCont {
    display: flex;
    border-right: solid 1px #efefef;
    width: 60%;
    padding: 15px;
    .tabBut {
      width: 110px;
      font-weight: bold;
      border-right: solid 2px #f4f4f4;
      span {
        display: block;
        text-align: center;
        // border-right: solid 2px #f4f4f4;
        cursor: pointer;
        position: relative;
      }
    }
    .act {
      border-color: $mine !important;
      color: $mine !important;
    }
    .act::after {
      content: ' ';
      display: inline-block;
      background-color: $mine;
      width: 2px;
      height: 40px;
      position: absolute;
      right: -2px;
    }
    .tabList {
      flex: 1;
      padding: 15px;
      height: 400px;
      overflow-y: scroll;
      .table {
        border: solid 1px #f4f4f4;
        border-bottom: solid 1px #f4f4f4;
        .items {
          border-bottom: solid 1px #f4f4f4;
          padding: 0 10px;
          display: flex;
          .el-checkbox,
          .el-checkbox__label {
            width: 100%;
          }
          .item {
            display: flex;
            padding-right: 20px;
            span {
              display: inline-block;
              text-align: center;
              flex: 1;
              font-weight: normal;
            }
          }
        }
      }
    }
  }
  .ritCont {
    width: 40%;
    .tit {
      margin: 0 15px;
      font-weight: bold;
    }
    .items {
      height: 338px;
      padding: 4px 15px;
      overflow: scroll;
    }
    .item {
      box-shadow: 0px 1px 4px 3px rgba(0, 0, 0, 0.03);
      display: flex;
      text-align: center;
      padding: 0 10px;
      margin-bottom: 20px;
      border-radius: 6px;
      color: #818693;
      span:first-child {
        text-align: left;
        color: #20232a;
        flex: 70%;
      }
      .price {
        display: inline-block;
        flex: 70%;
        text-align: left;
      }
      .del {
        cursor: pointer;
        img {
          position: relative;
          top: 5px;
          width: 20px;
        }
      }
    }
  }
}

src/api/setMeals.ts

// 修改数据接口
export const editSetmeal = (params: any) => {
    return request({
        url: '/setmeal',
        method: 'put',
        data: { ...params }
    })
}

// 新增数据接口
export const addSetmeal = (params: any) => {
    return request({
        url: '/setmeal',
        method: 'post',
        data: { ...params }
    })
}

// 查询详情接口
export const querySetmealById = (id: string | (string | null)[]) => {
    return request({
        url: `/setmeal/${id}`,
        method: 'get'
    })
}

src/api/dish.ts

import request from '@/utils/request'
/**
 *
 * 菜品管理
 *
 **/
// 查询列表接口
export const getDishPage = (params: any) => {
  return request({
    url: '/dish/page',
    method: 'get',
    params
  })
}

// 删除接口
export const deleteDish = (ids: string) => {
  return request({
    url: '/dish',
    method: 'delete',
    params: { ids }
  })
}

// 修改接口
export const editDish = (params: any) => {
  return request({
    url: '/dish',
    method: 'put',
    data: { ...params }
  })
}

// 新增接口
export const addDish = (params: any) => {
  return request({
    url: '/dish',
    method: 'post',
    data: { ...params }
  })
}

// 查询详情
export const queryDishById = (id: string | (string | null)[]) => {
  return request({
    url: `/dish/${id}`,
    method: 'get'
  })
}

// 获取菜品分类列表
export const getCategoryList = (params: any) => {
  return request({
    url: '/category/list',
    method: 'get',
    params
  })
}

// 查菜品列表的接口
export const queryDishList = (params: any) => {
  return request({
    url: '/dish/list',
    method: 'get',
    params
  })
}

// 文件down预览
export const commonDownload = (params: any) => {
  return request({
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
    },
    url: '/common/download',
    method: 'get',
    params
  })
}

// 起售停售---批量起售停售接口
export const dishStatusByStatus = (params: any) => {
  return request({
    url: `/dish/status/${params.status}`,
    method: 'post',
    params: { id: params.id }
  })
}

//菜品分类数据查询
export const dishCategoryList = (params: any) => {
  return request({
    url: `/category/list`,
    method: 'get',
    params: { ...params }
  })
}

③点击”保存“按钮完成新增操作

功能测试

《苍穹外卖》前端课程知识点记录插图(122)

完结!!!

本站无任何商业行为
个人在线分享-虚灵IT资料分享 » 《苍穹外卖》前端课程知识点记录
E-->