苍穹外卖前端开发(Day1)

node.js安装

配置全局下载包地址和缓存地址

npm config set prefix "E:x\nodejs\node_global"
npm config set cache "E:\x\nodejs\node_cache"

最新的配置淘宝镜像的淘宝官方提供的方法

npm config set registry https://registry.npmmirror.com

安装Vue

npm i @vue/cli -g

创建Vue项目

命令行创建(只能在cmd, 不能用powershell)

vue create vue-demo-1

用网页的形式创建

vue ui

Vue目录结构

  • node_modules:当前项目依赖的js包
  • assets:静态资源存放目录
  • components:公共组件存放目录
  • App.vue:项目的主组件,页面的入口文件
  • main.js:整个项目的入口文件
  • package.json:项目的配置信息、依赖包管理
  • vue.config.js:vue-cli配置文件

启动Vue项目工程

在Vue项目文件夹中:

npm run serve

Vue的基本使用方式

Vue组件

Vue的组件文件以.vue结尾,每个组件由三部分组成

  • 结构 <template>
    • 只有一个根元素
    • 由它生成HTML代码
  • 样式 <style>
    • 编写CSS,控制页面展示效果
    • 全局样式:影响所有组件
    • 局部样式:只作用于当前组件
  • 逻辑 <script>
    • 编写JS代码
    • 控制模板的数据来源和行为

Vue基本使用方式

文本插值

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

先定义data()

<script>
export default {
  name: "HelloWorld",
  props: {
    msg: String,
  },
  data() {
    return {
      name: "张三",
      age: 30,
    };
  },
};
</script>

之后在template中使用

  <div class="hello">
    {{ name }}
    {{ age > 60 ? "老年" : "青年" }}
  </div>

属性绑定

  • 作用:为标签的属性绑定data方法中返回的属性
  • 用法:v-bind:xxx 简写为:xxx
    <input type="text" v-bind:value="name"/>
    <input type="text" :value="age"/>
    <img :src="src"/>

事件绑定

  • 作用:为元素绑定对应的事件
  • 用法:v-on:xxx,简写为@xxx
    <input type="button" value="保存" v-on:click="handleSave" />
    <input type="button" value="保存" @click="handleSave" />
<script>
export default {
  methods: {
    handleSave() {
      alert("你点击了保存按钮!")
    },
  },
};
</script>

双向绑定

  • 作用:表单输入项和data方法中的属性进行绑定,任意一方改变都会同步给另一方
  • 用法:v-model
    <input type="text" v-model="name"/>

条件渲染

  • 作用:根据表达式的值来动态渲染页面元素
  • 用法:v-if、v-else、v-else-if
    <div v-if="sex == 1"></div>
    <div v-else-if="sex == 2"></div>
    <div v-else>未知</div>

Vue的基本使用方式 - axios

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

安装命令

npm install axios

导入命令:

import axios from 'axios'

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:配置对象,可以设置查询参数,请求头信息
<script>
import axios from "axios";

export default {
  methods: {
    handleSendPOST() {
      // 通过axios发送HTTP请求
      axios
        .post("/api/admin/employee/login", {
          username: "admin",
          password: "123456",
        })
        .then((res) => {
          console.log(res.data);
        })
        .catch((error) => {
          console.log(error.response);
        });
    },
    handleSendGET() {
      // 通过 axios 发送get请求
      axios
        .get("/api/admin/shop/status", {
          headers: {
            token:
              "eyJhbGciOiJIUzI1NiJ9.eyJlbXBJZCI6MSwiZXhwIjoxNzI5OTMzMjU4fQ.JV9g9K6u4UPzdSIMzcX5crMM3VXImspm6PbvolDpkSg",
          },
        })
        .then((res) => {
          console.log(res.data);
        });
    },
  },
};
</script>

Vue的基本使用方式 - axios

axios 统一使用方式 axios(config)

<script>
import axios from "axios";

export default {
    handleSend() {
      // 通过 axios 发送get请求
      axios({
        url: "/api/admin/employee/login",
        method: "post",
        data: {
          //data表示通过请求体传参
          username: "admin",
          password: "123456",
        },
      }).then((res) => {
        console.log(res.data.data.token)
        axios({
          url:'api/admin/shop/status',
          method:'get',
          headers:{
            token: res.data.data.token
          }
        }
        )
      });
    },
  },
};
</script>

Vue-Router

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

创建Vue项目时勾选router选项

老项目中使用

npm install vue-router

路由配置

路由组成

  • VueRouter:路由器,根据路由请求在路由视图中动态渲染对应的视图组件
  • <router-link>:路由链接组件,浏览器会解析成<a>
  • <router-view>:路由视图组件,用来展示与路由路径匹配的视图组件

image-20241026154037692

router/index.js中指定路由表

image-20241026160311413

App.vue中指定路由的位置

image-20241026160352655

嵌套路由

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

image-20241026173705114

// 维护路由表,某个路由路径对应哪个视图组件
const routes = [
  {
    path: '/',
    name: 'home',
    component: HomeView
  },
  {
    path: '/about',
    name: 'about',
    component: () => import('../views/AboutView.vue')
  },
  {
    path: '/404',
    component: () => import('../views/404View.vue')
  },
  {
    path: '/c',
    component: () => import('../views/container/ContainerView.vue'),
    redirect: '/c/p1',
    // 嵌套路由(子路由)
    children:[
      {
        path:'/c/p1',
        component: () => import('../views/container/P1View.vue'),
      },
      {
        path: '/c/p2',
        component: () => import('../views/container/P2View.vue'),
      },
      {
        path: '/c/p3',
        component: () => import('../views/container/P3View.vue'),
      }
    ]
  },
  {
    //重定向到404
    path: '/*',
    redirect: '/404'
  },
]

状态管理vuex

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

vuex介绍

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

定义和展示共享数据

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

使用共享数据:

  <div id="app">
    欢迎你{{$store.state.name}}
    <img alt="Vue logo" src="./assets/logo.png">
    <HelloWorld msg="Welcome to Your Vue.js App"/>
  </div>

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

export default new Vuex.Store({
  state: {
  },
  getters: {
  },
  // 通过当前属性中定义的函数修改共享数据,必须都是同步操作
  mutations: {
    setName(state, newName){
      state.name = newName
    }
  },
  actions: {
  },
  modules: {
  }
})

在vue中调用mutations中的函数

<script>
import HelloWorld from './components/HelloWorld.vue'

export default {
  name: 'App',
  components: {
    HelloWorld
  },
  methods: {
    handleUpdate(){
      // mutations中定义的函数不能直接调用,必须通过这种方式来调用
      this.$store.commit("setName", "Kennem")
    }
  },
}
</script>

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

<script>
import HelloWorld from "./components/HelloWorld.vue";

export default {
  name: "App",
  components: {
    HelloWorld,
  },
  methods: {
    handleUpdate() {
      // mutations中定义的函数不能直接调用,必须通过这种方式来调用
      this.$store.commit("setName", "Kennem");
    },
    handleCallAction(){
      //调用actions中定义的函数,setNameByAxios为函数名称
      this.$store.dispatch('setNameByAxios')
    }
  },
};
</script>
// 集中管理多个组件共享的数据
export default new Vuex.Store({
  // 集中定义共享数据
  state: {
    name: '未登录游客'
  },
  getters: {
  },
  // 通过当前属性中定义的函数修改共享数据,必须都是同步操作
  mutations: {
    setName(state, newName) {
      state.name = newName
    }
  },
  actions: {
    setNameByAxios(context) {
      axios({
        url: '/api/admin/employee/login',
        method: 'post',
        data: {
          username: 'admin',
          password: '123456'
        }
      }).then(res=>{
        if(res.data.code == 1){
          // 异步请求后,需要修改共享数据
          // 在actions中调用mutations中定义的setName函数
          context.commit('setName', res.data.data.name)
        }
      })
    }
  },
  modules: {
  }
})

TypeScript

function hello(msg:string){
	console.log(msg)
}
hello("123")

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

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

如何理解TS?

  • 是JS的超集,兼容JavaScript
  • 扩展了JavaScript的语法,文件扩展名为ts
  • 可以编译成标准的JavaScript,并且可以在编译时进行类型检查
  • 全局安装npm install -g typescript
  • 使用tsc命令将ts文件编译成js文件
类型 备注
字符串类型 string
数字类型 number
布尔类型 boolean
数组类型 number[], string[], boolean[] 依此类推
任意类型 any 相当于又回到了没有类型的时代
复杂类型 type 与 interface
函数类型 () => void 对函数的参数和返回值进行说明
字面量类型 “a” | “b” | “c” 限制变量或参数的取值
class 类 class Animal

TypeScript常用类型

  • 类型标注的位置
    • 标注变量
    • 标注参数
    • 标注返回值
// 字符串类型
let username: string = 'Kennem'

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

// 布尔类型
let isTrue: boolean = true
  • 字面量类型
    • 类似Java中的枚举,限制变量的取值
// 字面量类型
function printText(s, alignment) {
    console.log(s, alignment);
}
printText('hello', 'center');
  • interface类型
interface Cat {
    name: string, 
    age?: number // 当前属性为可选
}

const c1: Cat = {name: 'Kennem', age:1}
const c2: Cat = {name: 'Kennem'}
  • class类-基本使用

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

//定义一个类
class User{
    name: string
    constructor(name: string){
        this.name = name
    }

    study(){
        console.log(this.name + ' is studying');
    }
}

const user = new User('Kennem')

console.log(user.name);

user.study();
  • class类-实现接口
interface Animal {
    name: string
    eat(): void
}

class Bird implements Animal {
    name: string

    constructor(name: string) {
        this.name = name
    }

    eat() {
        console.log(this.name + ' is eating');
    }
}

// 创建类型为bird的对象
const b1: Bird = new Bird('燕子')
console.log(b1.name);
b1.eat()
  • class类-类的继承
class Parrot extends Bird {
    fly() {
        console.log(this.name + ' is flying');
    }
}

const myParrot: Parrot = new Parrot('鹦鹉一号')
myParrot.fly()
myParrot.eat()