day69_Vue进阶

今日内容

零、 复习昨日

零、 复习昨日

nginx

  • 静态服务器(动静分离)
  • 反向代理服务器(代理后端服务器)
  • 负载均衡
  • 异步

前端工程化 —> java代码工程

一、使用Vue-Cli搭建Vue项目


1.1 什么是vue-cli

cli: Command Line 命令行工具,vue-cli就是vue的命令行工具,也称之为脚手架,使用vue-cli提供的各种命令可以拉取、创建、运行我们需要使用到的框架,比如webpack、Element UI、Element Admin等等。那么要想使用vue-cli命令,需要先安装node.js

1.2 node.js的介绍及安装

node.js的介绍

node.js提供了前端程序的运行环境,可以把node.js理解成是运行前端程序的服务器。

node.js的安装

从官网下载安装即可:
http://nodejs.cn/download/

image-20230630171746807 image-20230630171801300 image-20230630171838210 image-20230630171902451 image-20230630171935797

​ 不要勾选这个,否则会下载很多东西

image-20230630171950352
测试node.js是否安装成功: 在DOS窗口中输入“node -v” 查看版本,如果看到版本,就表示安装成功。(环境变量已经自动配置好)
image-20230630172915127

node -v 是 查看node的版本

npm -v 是 查看npm版本

npm是安装工具的工具包,类似于Linux中yum,Linux中安装软件 yum install ,node中安装软件使用npm install

设置npm源 , 配置镜像后,下载资源就会很快.

image-20230630173211116

npm config set registry https://registry.npm.taobao.org

1.3 使用node.js 安装 vue-cli

(管理员权限)使用如下命令安装vue-cli

npm install @vue/cli -g# 如果出错,可以卸载,重新执行上一步安装
npm uninstall @vue/cli -g
  • npm: 使用node.js的命令
  • install: 安装
  • @vue/cli: 要安装的vue-cli
  • -g: 全局安装
当出现以下界面,表示正在安装:
image-20230630174255457image-20230630174544138

安装vue-cli检测

image-20230630174643935

1.4 使用vue-cli命令创建项目

进入工作空间,执行命令创建

  • vue create 项目名

image-20230630180103755

选择具体features

image-20230630180251951

选择vue版本

image-20230630180445128

一般选择第一项,为的是将文件分离打包

image-20230630180546418

是否将此操作存储为模板,本例选择n,选择为y就会在下次创建时使用

image-20230630180626238

创建完毕

image-20230630180841197

运行项目

image-20230630181044188

image-20230630181126743

1.5 使用图形界面方式创建

打开命令行,输入vue ui

会自动打开浏览器,弹出页面

image-20230701130829566

创建项目

image-20230701134703173

image-20230701134835493

image-20230701134927540

选择插件

image-20230701134954698

选择版本

image-20230701135119621

开始创建

image-20230701135215555

创建成功后,跳转控制面板页面

image-20230701135337501

启动项目& 关闭

image-20230701135438284

1.6 项目结构

image-20230701141932969

文件名解释
buildwebpack的一些配置
config不同环境的配置,比如开发环境,生产环境等
node_modulesnpm install下载的依赖包
public用于存放公共js文件夹、json文件和图片等
dist存放项目打包后的文件
src项目的源码
src/assets存放静态资源文件,如图片等
src/components存放公共组件
src/router静态路由表
src/storevuex
src/views开发的页面资源,路由页面相关的
src/main.js对应App.vue创建vue实例,也是入口文件
src/App.vue入口页面
gitignoregit管理时,忽略的文件或文件夹
package.json项目的核心配置记录,可以查看当前安装依赖的版本号
index.html首页的入口
vue.config.js可选的配置文件,存放在根目录中,@vue/cli-service 启动的时候会自动加载

可以在package.json中修改端口

image-20230701143121782

image-20230701143202078

二、idea开发vue

idea中安装Vue插件

image-20230602163052107

然后使用idea打开之前创建的vue项目即可

ps: 也可使用idea直接创建vue项目,但是创建的vue版本默认为Vue3,无法改成vue2,暂时先不使用

三、单文件组件[重点]

3.1 介绍

以前

在很多 Vue 项目中,我们使用 Vue.component 来定义全局组件,紧接着用 new Vue({ el: '#app'}) 在每个页面内指定一个容器元素。

这种方式在很多中小规模的项目中运作的很好,在这些项目里 JavaScript 只被用来加强特定的视图。但当在更复杂的项目中,或者你的前端完全由 JavaScript 驱动的时候,下面这些缺点将变得非常明显:

  • 全局定义 (Global definitions) 强制要求每个 component 中的命名不得重复
  • 字符串模板 (String templates) 缺乏语法高亮,在 HTML 有多行的时候,需要用到丑陋的 \
  • 不支持 CSS (No CSS support) 意味着当 HTML 和 JavaScript 组件化时,CSS 明显被遗漏
  • 没有构建步骤 (No build step) 限制只能使用 HTML 和 ES5 JavaScript,而不能使用预处理器,如 Pug (formerly Jade) 和 Babel

现在

文件扩展名为 .vuesingle-file components (单文件组件) 为以上所有问题提供了解决方法,并且还可以使用 webpack 或 Browserify 等构建工具。

单文件组件的组成结构:

  • template 组件的模块区域

  • script 业务逻辑区域

  • style 样式区域

3.2 使用

在工程的src/components下创建一个TestSingeVuePage.vue单文件

ps: 命名规则 驼峰版TestSingeVuePage 或者 test-single-vue

image-20230701193211146

填入内容

image-20230701200506779

<template><div><h1 class="red">这是测试单vue文件组件</h1><h3>{{info}}</h3><button @click='show()'>show</button></div>
</template><script>
export default {name: "TestSingleVuePage",data:function (){return {info:"data-信息"}},methods:{show(){alert("单页面内弹出...")}}
}
</script><style scoped>.red {color: red;}
</style>

注册组件

  • 哪里注册? 哪个组件需要使用另一个组件,就在哪注册?

  • 例如: A.vue需要使用B.vue的组件内容

    • 就在V.vue中1)导入B组件,2)注册组件,3)使用组件
  • 在App.vue文件内注册组件

image-20230701201344985

使用组件

  • 在App.vue页面的template内使用组件

image-20230701200731630

启动测试

image-20230701200812767

3.3 练习

练习: 再创建一个单页面TestSingleVuePage2.vue页面,定义一些内容, 然后在TestSingleVuePage.vue页面内使用该页面

注意:

import Demo1 from "@/components/Demo1.vue";
import Demo2 from "./components/Demo2.vue";

其中./ 是相对路径,@是从根路径

四、Vue组件间的参数传递


4.1 父传子

通过子组件的props部分,来指明可以接收的参数,父组件通过在标签中写明参数的键值对来传递参数。

​ props是表示一个组件的参数部分,那么props的写法有两种:

​ 1)props:[参数列表]

​ 比如: props:[‘MyProp1’,‘MyProp2’,…]

​ 2)props:{参数名1:{type:String,required:true,default:‘XX’},参数名2:{…}}

演示

创建子组件,设置参数 等待父组件给其传值

<template>
<div><h1>这是 子组件</h1><span>{{name}}</span> --<span>{{age}}</span> --<span>{{sex}}</span>
</div>
</template><script>
export default {name: "MySon",props:{name: {// 类型type: String,// 默认值default: '无名'},age: Number,sex: Boolean}
}
</script><style scoped>
</style>

创建父组件,给子组件传值

<template><div><h1>这是 父组件 </h1><!-- 父组件使用子组件 --><!--可以通过 v-bind 动态赋值,比如 v-bind:name="",也可以简写:age=""也可以静态赋值,比如 messages="" , 注意没有冒号--><MySon v-bind:name="username" :age="age" sex="true"></MySon></div>
</template><script>
import MySon from "@/components/MySon";export default {name: "MyFather",components: {MySon},data: function () {return {username: "小儿砸",age: 18}}
}
</script><style scoped></style>

在App.vue注册父组件并使用父组件演示效果即可

image-20230701212133867

注意:props支持的类型:String、Number、Boolean、Array、Object、Date、Function、Symbol

4.2 子传父

使用组件中的props属性是无法完成子组件向父组件传值的,在Vue的设计中,props是单向数据流,只能是父组件通过props向子组件传递数据.

image-20230701212537907

那么,如果需要子组件向父组件传递值该如何做?

  • Vue提供了方案: 在子组件中使用自定义事件向父组件传递数据.

具体步骤

  • 子组件定义一个函数,通过事件触发函数,函数内通过$emit 函数将数据发给父组件

    this.$emit('父组件中的函数名', 数据)
    
  • 父组件在使用子组件的时候,通过@emit中的函数名绑定数据,然后再将接收到数据传递给父组件自己的函数即可

子组件

<template><div><h1>这是 子组件2</h1><button @click="sendNum">子组件将值num=10传递给父组件</button></div>
</template><script>
export default {name: "MySon2",props: {},data: function () {return {num: 10}},methods: {sendNum() {// 触发父组件的事件,同时给事件传参this.$emit('addFun', this.num)}}
}
</script><style scoped>
</style>

父组件

<template><div><h1>这是 父组件2 </h1><span>sum = {{sum}}</span><MySon2 @addFun="addSum"></MySon2></div>
</template><script>
import MySon2 from "@/components/MySon2";export default {name: "MyFather2",components: {MySon2},data: function () {return {sum: 0}},methods:{addSum(v){this.sum += v;}}
}
</script><style scoped></style>

在App.vue注册父组件并使用父组件演示效果即可

image-20230701214725152

image-20230701214751783

五、Vue-router 路由[重点]

5.1 介绍

路由的本质就是一种对应关系,比如说我们在url地址中输入我们要访问的url地址之后,浏览器要去请求这个url地址对应的资源。

那么url地址和真实的资源之间就有一种对应的关系,就是路由。

路由分为前端路由后端路由

1)后端路由是由服务器端进行实现,并完成资源的分发(我们之前的项目)

image-20230701221228697

2)前端路由是依靠hash值(锚链接)的变化进行实现 (vue官网就是使用这种)

image-20230701221239070

前端路由的基本概念:
根据不同的事件来显示不同的页面内容,即事件与事件处理函数之间的对应关系
前端路由主要做的事情就是监听事件并分发执行事件处理函数

5.2 vue的路由

Vue默认属于单页面的程序,主要通过URL中的hash来实现不同页面之间的切换。这种切换方式称作前端路由。

Vue Router的核心作用

  • 跳转/切换页面

    • 声明式(写标签)

      <router-link to="要跳转的组件名称">
      
    • 编程式(写代码)

      this.$router.push("要跳转的组件名称")
      
  • 跳转携带数据

    • 编程式导航实现传递参数
      • 传递 this.$router.push({path:‘路径’,params:{参数名:值,…}})
      • 接收 this.$router.params.参数名
  • 路由模式

    • hash模式:监听浏览器地址hash值变化,执行相应的js切换网页;
    • history模式:利用history API实现url地址改变,网页内容改变;
    • 它们最明显的区别就是hash会在浏览器地址后面增加#号

5.3 安装路由模块

介绍 | Vue Router (vuejs.org)

npm install vue-router
# 如果报错,可能是npm版本过高,存在兼容性问题,那么使用如下命令
npm install --legacy-peer-deps vue-router@3.5.2
npm install --legacy-peer-deps vue-router@3.1.3ps: 今天练习过一次以后,后续在创建项目时可以直接选择路由部分内容,创建出的项目直接就配置好了

5.5 路由初体验

在主页与个人中心直接切换显示

5.5.1 创建MyInfo.vue

路由页面建议创建在src/view/下

<template><div><h1>个人中心</h1></div>
</template><script>
export default {name: "MyInfo"
}
</script><style scoped></style>

5.5.2 创建静态路由表

在/src下创建router文件夹,

在/src/router/创建index.js文件

填充以下内容

import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '../components/HelloWorld'
import MyInfo from "../components/MyInfo";Vue.use(Router)
// export是导出路由对象,只有导出了
// main.js文件头上面才能 import 导入
export default new Router({routes: [{path: '/', // 匹配<router-link to="">中的路径name: 'HelloWorld', // 这个name属性可写可不写component: HelloWorld // 要跳转的组件对象},{path: '/MyInfo',name: 'MyInfo',component: MyInfo}],// mode: 'history'mode: 'hash'
})

5.5.3 引入路由模块并使用

在main.js中引入路由模块并使用

import Vue from 'vue'
import App from './App'
import router from './router' //引入上一步导出的路由模块,并设置名字为router
Vue.config.productionTip = falsenew Vue({render: h => h(App),router  // 使用路由
}).$mount('#app')

5.5.4 App.vue使用路由

<template><div id="app"><ul><li><!-- <router-link>用于导航,其实就是a标签to表示要跳转的资源的路径tag 将router-link渲染成想要的原生标签,默认是a标签,可以改成button--><router-link to="/" tag="button">首页</router-link></li><li><router-link to="/MyInfo">个人信息</router-link></li></ul><!-- router-view 路由填充位,要跳转的组件在此展示,位置任意 --><router-view/></div>
</template><script>
import HelloWorld from './components/HelloWorld.vue'export default {name: 'App',components: {HelloWorld}
}
</script><style>
#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;
}
</style>

启动测试

5.6 编程式路由

刚才演示的是声明式路由,也可以使用编程式路由

演示: 主页与公共页面切面

创建公告页Note.vue

<template>
<div><h1>网站公告</h1>
</div>
</template><script>
export default {name: "Note"
}
</script>
<style scoped>
</style>

src/router/index.js 注册路由

export default new Router({routes: [{path: '/',name: 'HelloWorld',component: HelloWorld},{path: '/MyInfo',name: 'MyInfo',component: MyInfo},{path: '/Note',name: 'Note',component: Note}],// mode: 'history'mode: 'hash'
})

App.vue设置标签,绑定事件,事件触发函数,函数内编写代码实现路由

image-20230701235337484

this.$router.push("/Note")
// 注意!!!!别写错,有个叫做this.$route

bug: 第一次点击跳转没事,再点一次报错

原因: vueRouter版本问题

解决:

  • 降低版本
  • 设置异常捕获 (推荐)
// 在router中的index.js中加上以下代码,注意加在use之前写
const routerPush = Router.prototype.push;
Router.prototype.push = function (location) {return routerPush.call(this, location).catch((err) => {});
};

5.7 参数的传递

5.7.1 声明式路由传参

演示App.vue中将数据传递给MyInfo.vue

在路由表中设参

export default new Router({routes: [...{path:'/MyInfo/:id', //设参component:MyInfo}]
})

在App.vue中传参

<template><div id="app"><ul><li><router-link to="/" tag="button">首页</router-link></li><li><!-- 跳转至MyInfo,并携带id 1001 -->  <router-link to="/MyInfo/1001">个人信息</router-link></li></ul><!-- router-view 用于显示匹配的组件,类似显示路由到的组件的区域,位置任意 --><router-view/></div>
</template><script>
...
</script><style>
...
</style>

在MyInfo.vue中接参

<template><div><h1>个人信息</h1><span>id-->{{id}}</span></div>
</template><script>
export default {name: "EmployeeList",data:function(){return {id:this.$route.params.id // 注意是$route不是$router}}
}
</script>
<style scoped>
</style>

5.7.2 编程式路由传参

演示App.vue中将数据传递给Note.vue

App.vue的编程跳转js中设置要传递的数据

  methods:{toNote(){//this.$router.push("/Note")this.$router.push({path:"/Note",query:{id:1002}})}}

Note.vue中接收参数

<template>
<div><h1>网站公告</h1><span>id --> {{id}}</span>
</div>
</template><script>
export default {name: "Note",data:function(){return {id:this.$route.query.id  // 注意是query,因为是按照路径方式发送,注意查看浏览器url}}
}
</script>

ps: 后续也可以通过VueX来完成传递数据

5.8 嵌套路由

image-20230705221149496

例如:

image-20230706093624132

5.9 其他

路由重定向,导航守卫等等信息,查看官网自查

重定向| Vue Router (vuejs.org)

六、 Vuex[重点]


6.1 什么是Vuex

Vuex 是什么? | Vuex (vuejs.org)

Vuex 是一个专为 Vue.js 应用程序开发的 状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

说人话: 实现多个组件的数据共享,即一个数据需要在多个组件中使用,那么久需要把这个数据存储在VueX中

Vuex五大核心要素

  • state:存放状态,比如需要全局共享的数据
  • getters:可以对state中的数据进行额外处理,类似计算属性的作用
  • mutations:通过提交mutations来改变state的状态
  • actions:异步的mutations,可以通过dispatch调用mutaitons,从而改变state
  • modules:模块化状态管理,每个模块拥有自己的 state、mutation、action、getter

vuex

Vue组件通过dispatch调用Vuex中actions的方法,进行异步操作。

actions中的方法中,通过commit,调用mutations中方法,以保证state中数据的同步。

如果没有异步操作,可以直接在组件通过commit调用mutations中的方法对state中共享的数据进行操作。

6.2 安装

在项目根目录执行如下命令来安装 Vuex

若失败,可使用cnpm

# 本例使用的vue2,所以安装vuex装的是vuex3
npm install vuex@3

image-20230702172304145

6.3 配置 vuex

在 src 目录下创建一个名为 store 的目录并新建一个名为 index.js 文件用来配置 Vuex,代码如下:

import Vue from 'vue'
import Vuex from 'vuex'Vue.use(Vuex)export default new Vuex.Store({state: {},mutations: {}
})

修改 main.js 增加刚才配置的 store/index.js,关键代码如下:

import Vue from 'vue'
import App from './App.vue'
// 引入路由模块
import router from './router'
// 引入Vuex模块
import store from './store'Vue.config.productionTip = false
// vue2 创建方式
new Vue({render: h => h(App),router,store  // 使用Vuex
}).$mount('#app')

6.2 6.3 安装配置也可以不做,那就是在创建项目时直接选这个依赖,创建好项目直接就配置好了

image-20230706100127943

  • 一个是路由Router,一个是状态管理Vuex

6.4 演示

6.4.1 存&取

  • 在Vuex中设置数据,在任何组件取出
// store/index.js文件的state中定义数据
export default new Vuex.Store({state: {username:"无名",count:443,tga:"tga"},mutations: {}
})

在任何组件中使用 以下命令取值

this.$store.state.username
// username是state中定义的key

6.4.2 计算属性使用state

<template>
<div>计算属性取值:{{num}}
</div>
</template><script>
export default {name: "TestVueX",computed:{  // 【注意: 计算属性的写法】num() { return this.$store.state.count}}
}
</script>

重要用法: state中的数据要放在组件的computed中而不是data中!

为什么?

这是因为data 中的内容只会在 created 钩子触发前初始化一次,具体来说就是data中设置count: this. s t o r e . s t a t e . c o u n t 则 c o u n t 的值是 c r e a t e d 钩子执行前 t h i s . store.state.count则count的值是created钩子执行前this. store.state.countcount的值是created钩子执行前this.store.state.count的值,赋值之后属性的值就是纯粹的字面量,之后this.$store.state.count 如何变化均影响不到count的取值。而 computed 则是通过依赖追踪实现的,计算属性在它的相关依赖发生改变时会重新求值。

简而言之就是说,Vuex存储的数据如果有变化,computed中的数据就会变化,但是data中的不会变化

6.4.3 mapState

当一个组件需要获取多个状态的时候,将这些状态都声明为计算属性会有些重复和冗余。为了解决这个问题,我们可以使用 mapState 辅助函数帮助我们生成计算属性

<template>
<div>计算属性取值:{{count}}|计算属性取值:{{tga}}|计算属性取值:{{username}}|
</div>
</template><script>
// 【注意】 是 {} 引入
// 使用 import mapState from 'vuex' 的方式会将整个 vuex 模块导入,并将其中的 mapState 函数赋值给 mapState 变量。
// 而使用 import { mapState } from 'vuex' 的方式则是只导入 vuex 模块中的 mapState 函数
import {mapState} from 'vuex'
export default {name: "TestVueX",// computed:mapState({//   count: function (state) {//       return state.count//     }// }),// 如果使用和状态名一样的计算属性名,还可以这样写// 映射 this.count 为 store.state.count// computed: mapState(['count','tga','username']),// 如果有其他的计算属性,并且需要将vuex的state与其混合使用// 可以使用对象展开运算符'...'computed: {// 使用对象展开运算符将此对象混入到外部对象中// 映射为当前组件的计算属性...mapState(['count','tga','username']),},}
</script><style scoped></style>

6.4.4 修改数据

  • 在任何组件中修改Vuex中的数据
// store/index.js文件的mutations中定义方法修改数据
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({state: {username:"无名"},mutations: {// 参数1 是Vuex-state对象// 参数2 是其他组件使用时传过来的值,这个参数叫做payloadupdateName(state,v){state.username = v  // 修改Vuex中的值}}
})

在其他组件中通过事件触发函数,在其中使用Vuex的方法修改数据

<template><div id="app"><!--  演示Vuex取值  --><h1>Vuex --> {{ username }}</h1><input v-model="username"><button @click="editName">修改vuex中的值</button></div>
</template><script>export default {name: 'App',methods: {editName(){// 修改Vuex数据// updateName是 src/store/index.js中mutations中定义的函数名this.$store.commit('updateName', this.username)}},data: function () {return {// 从Vuex中取出数据  username: this.$store.state.username}}
}
</script>

6.5.解决浏览器刷新后 Vuex 数据消失问题

  • 问题描述

Vuex 的状态存储是响应式的,当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。但是有一个问题就是:vuex 的存储的数据只是在页面的中,相当于我们定义的全局变量,刷新之后,里边的数据就会恢复到初始化状态。但是这个情况有时候并不是我们所希望的。

  • 解决方案

采用持久化,VueX整合插件实现持久化:vuex-persistedstate

  • 安装插件

    	npm install vuex-persistedstate
    

    image-20230702181913147

  • 配置

    在/src/store/index.js中实现配置

    import Vue from 'vue'
    import Vuex from 'vuex'
    // 引入持久化插件
    import vuexPersistedstate from "vuex-persistedstate";Vue.use(Vuex)
    export default new Vuex.Store({state: {username:"无名66"},mutations: {updateName(state,v){state.username = v}},plugins:[vuexPersistedstate()] // 加入插件
    })
    
  • 测试

    浏览器刷新测试效果

6.6 其他Vuex知识

七、Promise

主要解决异步深层嵌套的问题 ,promise 提供了简洁的API 使得异步操作更加容易,为后面学习axios提供基础

7.1 以前ajax中的问题

  • 异步请求外的代码,不能使用异步请求中的返回的数据
  • 多次异步调用结果顺序不确定
  • 异步调用的结果如果确实存在依赖关系,就需要嵌套处理

演示:

问题一: 异步请求外的代码,不能使用异步请求中的返回的数据

image-20230704232817410

像上面这样,下面的那个打印日志的结果是:

image-20230704232949139

并没有将ajax中请求的结果拼接,因为ajax是异步请求,即执行ajax时,会不等待回调执行就会去执行后续代码,也就是说,执行那个输出日志时,ajax的回调可能还没执行呢

问题二: 多次异步调用 结果顺序不确定

image-20230704233053371

分别多测试几次

imgimgimg

多次刷新,多次请求,会发现结果顺序跟代码的上下顺序并不一样.

问题三: 异步调用的结果如果确实存在依赖关系,就需要嵌套处理

假如,三个请求的结果确实需要等输出了hello1再输出hello2,最后输出hello3的话,就需要嵌套处理.

image-20230704233218191

image-20230704233228739

7.2 Promise

Promise 是一种用于处理异步操作的前端开发技术。它是 ECMAScript 6(ES6)规范中引入的一种对象,旨在解决 JavaScript 中的回调地狱问题,使异步操作更加优雅和可维护。

在传统的 JavaScript 开发中,异步操作通常使用回调函数来处理。然而,当嵌套多个异步操作时,回调函数的嵌套会导致代码结构复杂、难以理解和维护。Promise 提供了一种更好的解决方案。

image-20230704233613080

基本语法

- 创建Promise对象§,构造函数中传递函数,该函数中用于处理异步任务

- 该函数中resolve和reject两个参数用于处理成功和失败的两种情况,并通过实例对象p调用then方法获取处理的结果

image-20230704233655407

示例

<script type="text/javascript">var p = new Promise(function(resolve,reject){/*** resolve和reject都是方法* 成功是调用resolve([参数])函数* 失败时调用reject([参数])函数 */// 异步请求$.ajax({url:'http://localhost:8080/vue/hello',success:function(data) {resolve(data);},error:function(){reject("出错啦");}})});p.then(function(ret){console.log(ret);},function(ret){console.log(ret);})
</script>

将以上代码封装成一个函数,就可以将jQuery中ajax嵌套调用的那种情况变得优雅一点

<script type="text/javascript">function queryData(path){var p = new Promise(function(resolve,reject){/*** resolve和reject都是方法* 成功是调用resolve([参数])函数* 失败时调用reject([参数])函数 */// 异步请求$.ajax({url:path,success:function(data) {resolve(data);},error:function(){reject("出错啦");}})});return p;}queryData('http://localhost:8080/vue/hello1').then(function(ret){console.log(ret);})
</script>

八、Axios[重点]


8.1 什么是 Axios

Axios 是一个开源的可以用在浏览器端和 NodeJS 的异步通信框架,她的主要作用就是实现 AJAX 异步通信,其功能特点如下:

  • 从浏览器中创建 XMLHttpRequests

  • 从 node.js 创建 http 请求

  • 支持 Promise API

  • 拦截请求和响应

  • 转换请求数据和响应数据

  • 取消请求

  • 自动转换 JSON 数据

  • 客户端支持防御 XSRF(跨站请求伪造)

  • 官网基本用例 | Axios 中文文档 | Axios 中文网 (axios-http.cn)

由于 Vue.js 是一个 视图层框架 并且作者(尤雨溪)严格准守 SoC (关注度分离原则),所以 Vue.js 并不包含 AJAX 的通信功能,为了解决通信问题,作者单独开发了一个名为 vue-resource 的插件,不过在进入 2.0 版本以后停止了对该插件的维护并推荐了 Axios 框架

8.2 Axios的使用

8.2.1 安装vue axios

npm install --save axios vue-axios

image-20230702185555289

8.2.2 在需要使用的页面中引入

比如UserInfo.vue页面需要发请求,那就在页面的script中引入即可

import axios from 'axios'

8.2.3 发送ajax请求

<template>
<div><button @click="getInfo">查询数据</button><hr>{{deptList}}<hr><table><th>部门编号</th><th>部门名称</th><th>部门地址</th><tr v-for="dept in deptList"><td>{{dept.deptno}}</td><td>{{dept.dname}}</td><td>{{dept.loc}}</td></tr></table>
</div>
</template><script>
// 引入axios    
import axios from 'axios'
export default {name: "TestAxios",data(){return {deptList:null}},methods:{getInfo(){// axios.get('/api/dept').then(function(ret){//   console.log(ret)//   this.deptList = ret.data // 【有bug,因为this问题】// })axios.get('/api/dept').then((ret)=>{console.log(ret) // 【注意:这个返回值不一般】  // 可以查看官网https://www.axios-http.cn/docs/res_schemathis.deptList = ret.data.data   })}}
}
</script><style scoped>
</style>

8.2.4 服务端解决跨域问题

SpringBoot的controller层类上添加@CrossOrigin注解即可

8.2.5 BUG

在axios的回调中,无法使用this.数据 获得vuedata中的数据

造成axios取不到值得原因主要是this回调问题。当执行完函数function时,this指向放生变化。导致this指向函数体本身。这时this.data里的数据取不到。

简单直接的解决就是把function写成箭头函数形式,箭头函数不是构造函数,不会指定this,而是抓取上下文this作为自己的this

8.3 其他api演示

可以查看官网请求配置 | Axios 中文文档 | Axios 中文网 (axios-http.cn)

也可以看示例

<!-- get请求(1) 路径拼接参数 -->
axios.get('http://localhost:8080/vue/user?id=456').then(function(ret){console.log(ret.data); 
})<!-- get请求(2) Restful风格参数 -->
axios.get('http://localhost:8080/vue/user/123').then(function(ret){console.log(ret.data.); 
})<!-- get请求(3) 使用params传递参数 -->
axios.get('http://localhost:8080/vue/user',{params:{id:20001}
}).then(function(ret){console.log(ret.data); 
})
<!-- post请求,发送的是json,后台需要使用@RequestBody -->
axios.post('http://localhost:8080/vue/user/json',{username:'张三',password:'987654'
}).then(function(ret){console.log(ret.data); 
})
<!-- put请求 -->
axios.put('http://localhost:8080/vue/user/form',{username:'张三丰',password:'11111'
}).then(function(ret){console.log(ret.data); 
}).catch(function (err){console.log(err)
})

8.4 Axios的响应

官网: https://www.axios-http.cn/docs/res_schema

响应结果的主要属性:

  • data: 服务器响应回的数据
  • headers: 响应头信息
  • status: 响应状态码
  • statusText: 响应状态信息

需要特别注意,我们后台返回的数据在data中,即data中是后台返回的ResultObject,我们ret.data获得到的是ResultData,如果还有继续获得其中的数据,还需要再ret.data.data

8.5 axios的全局配置

官网: 默认配置 | Axios 中文文档 | Axios 中文网 (axios-http.cn)

我们讲一个特别实用的,我们在项目中调用数十次乃至百次接口是很常见的,后期一旦根域名发生改变,所有接口都需要修改,非常繁琐且容易出错。

axios提供了设置根域名的方法。
在main.js全局入口文件中,设置:

axios.defaults.baseURL = 'http://localhost:8888'

在其他vue页面中使用axios发请求的时候

axios.get('/api/dept').then((ret)=>{console.log(ret)this.deptList = ret.data.data})

8.6 响应拦截

还有请求拦截,暂时用不上先不讲

响应拦截可以拦截到axios发请求后的那个回调response对象,然后对其进行处理

  • 实战,将response数据简化后返回

    // 添加Axios响应拦截器
    axios.interceptors.response.use(function (response) {//console.log('响应拦截',response)return response.data;
    }, function (error) {console.log(error)
    });
    

    这样,在使用axios的页面,从回调中获得数据时,只需要ret.data,而不需要再ret.data.data

附录

对象展开运算符

对象展开运算符 ...(也称为扩展运算符)是一种用于展开对象或数组的语法,它允许将一个对象或数组拆分成单独的元素,并在其他对象或数组中使用。

在 JavaScript 中,... 运算符可以用在多种场景中,下面分别介绍它们的用法。

  1. 展开对象:
    可以使用对象展开运算符 ... 来创建一个新对象,并将另一个对象中的属性和值复制到新对象中。这可以用于对象浅拷贝或对象合并。

    示例:

    const obj1 = { name: 'John', age: 30 };
    const obj2 = { ...obj1, city: 'New York' };console.log(obj2);
    // 输出:{ name: 'John', age: 30, city: 'New York' }
    
  2. 合并对象:
    将多个对象合并成一个新对象的简便方法。如果有相同的属性,后面的对象的属性值会覆盖前面的对象的属性值。

    示例:

    const obj1 = { name: 'John', age: 30 };
    const obj2 = { city: 'New York' };
    const obj3 = { ...obj1, ...obj2 };console.log(obj3);
    // 输出:{ name: 'John', age: 30, city: 'New York' }
    
  3. 展开数组:
    在数组中使用 ... 可以将一个数组展开为独立的元素,可以用于创建一个新数组或者在函数调用时传递参数。

    示例:

    const arr1 = [1, 2, 3];
    const arr2 = [...arr1, 4, 5];console.log(arr2);
    // 输出:[1, 2, 3, 4, 5]
    
    const arr = [1, 2, 3];
    someFunction(...arr); // 将数组中的元素作为参数传递给函数
    

页面中使用axios发请求的时候

axios.get('/api/dept').then((ret)=>{console.log(ret)this.deptList = ret.data.data})

8.6 响应拦截

还有请求拦截,暂时用不上先不讲

响应拦截可以拦截到axios发请求后的那个回调response对象,然后对其进行处理

  • 实战,将response数据简化后返回

    // 添加Axios响应拦截器
    axios.interceptors.response.use(function (response) {//console.log('响应拦截',response)return response.data;
    }, function (error) {console.log(error)
    });
    

    这样,在使用axios的页面,从回调中获得数据时,只需要ret.data,而不需要再ret.data.data

附录

对象展开运算符

对象展开运算符 ...(也称为扩展运算符)是一种用于展开对象或数组的语法,它允许将一个对象或数组拆分成单独的元素,并在其他对象或数组中使用。

在 JavaScript 中,... 运算符可以用在多种场景中,下面分别介绍它们的用法。

  1. 展开对象:
    可以使用对象展开运算符 ... 来创建一个新对象,并将另一个对象中的属性和值复制到新对象中。这可以用于对象浅拷贝或对象合并。

    示例:

    const obj1 = { name: 'John', age: 30 };
    const obj2 = { ...obj1, city: 'New York' };console.log(obj2);
    // 输出:{ name: 'John', age: 30, city: 'New York' }
    
  2. 合并对象:
    将多个对象合并成一个新对象的简便方法。如果有相同的属性,后面的对象的属性值会覆盖前面的对象的属性值。

    示例:

    const obj1 = { name: 'John', age: 30 };
    const obj2 = { city: 'New York' };
    const obj3 = { ...obj1, ...obj2 };console.log(obj3);
    // 输出:{ name: 'John', age: 30, city: 'New York' }
    
  3. 展开数组:
    在数组中使用 ... 可以将一个数组展开为独立的元素,可以用于创建一个新数组或者在函数调用时传递参数。

    示例:

    const arr1 = [1, 2, 3];
    const arr2 = [...arr1, 4, 5];console.log(arr2);
    // 输出:[1, 2, 3, 4, 5]
    
    const arr = [1, 2, 3];
    someFunction(...arr); // 将数组中的元素作为参数传递给函数
    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/15398.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LeetCode[面试题17.14]最小的K个数

难度&#xff1a;中等 题目&#xff1a; 设计一个算法&#xff0c;找出数组中最小的k个数。以任意顺序返回这k个数均可。 示例&#xff1a; 输入&#xff1a; arr [1,3,5,7,2,4,6,8], k 4 输出&#xff1a; [1,2,3,4]提示&#xff1a; 0 < len(arr) < 1000000 <…

开源教育对话大模型 EduChat

文章目录 一、&#x1f680; 前言二、&#x1f916; 本地部署三、&#x1f468;‍&#x1f4bb; 使用示例四、&#x1f50e; 总结 &#x1f349; CSDN 叶庭云&#xff1a;https://yetingyun.blog.csdn.net/ 一、&#x1f680; 前言 教育是一项对人类身心发展产生影响的社会实践…

磁盘与文件系统管理

磁盘结构及分区表示 硬盘 Hard Disk Drive &#xff0c;简称 HDD 是计算机常用的存储设备之一。 1 磁盘基础 1.1 硬盘的结构 1.1.1 数据结构 ①扇区&#xff1a;磁盘上的每个磁道被等分为若干个弧段,这些弧段便是硬盘的扇区(Sector)。硬盘的第一个扇区&#xff0c;叫做引导…

easyupload

红框位置是上传后的提示 依次尝试上传&#xff0c;发现php,phtml.php3&#xff0c;php5&#xff0c;双写等都不行 .htaccess文件也不行 尝试.php. 绕过 (windows中会把后缀名最后的空格和. 省略&#xff0c;即上传.php.绕过后会变为.php) 加入图片头的php文件也不行 但是加入文…

100、基于STM32单片机自动跟随小车 红外遥控控制小车避障模式 跟随模式设计(程序+原理图+PCB源文件+流程图+硬件设计资料+元器件清单等)

绪 论 智能小车通过各种感应器获得外部环境信息和内部运动状态&#xff0c;实现在复杂环境背景下的自主运动&#xff0c;从而完成具有特定功能的机器人系统。而随着智能化电器时代的到来&#xff0c;它们在为人们提供的舒适的生活环境的同时&#xff0c;也提高了制造智能化电器…

Redis下载和安装(Windows系统)

本套教程中采用 Windows 系统对 Redis 数据库进行讲解。 虽然 Redis 官方网站没有提供 Windows 版的安装包&#xff0c;但可以通过 GitHub 来下载 Windows 版 Redis 安装包&#xff0c;下载地址&#xff1a;点击前往。 注意&#xff1a;Windows 安装包是某位民间“大神”根据 …

关于antdesign-vue的layout组件样式失效问题(#components-layout-demo-custom-trigger)

1.错误描述 使用antdesign vue 中的layout作为主要布局&#xff0c;https://www.antdv.com/components/layout-cn 正常引入后&#xff0c;跟期望的样子不一样 期望中的样子 实际的样子 logo没有了&#xff0c;而且此时也无法更改样式。 此时的样式是这样的 无论怎么修改都…

vue路由

目录 Vue路由 Vue Router 使用流程&#xff1a; Vue路由 前端路由&#xff1a;由URL中的hash&#xff08;#号&#xff09;于组件之间的对应关系 Vue Router 介绍&#xff1a;Vue Router是Vue官方路由组成&#xff1a; VueRouter&#xff1a;路由器类&#xff0c;根据路由请…

【从0开始离线数仓项目】——新能源汽车数仓项目介绍

目录 1、数据仓库概念 2、项目需求及架构设计 3、集群资源规划设计 4、车辆日志字段说明 1、数据仓库概念 数据仓库&#xff08;Data Warehouse&#xff09;是为企业提供数据支持&#xff0c;用以协助企业制定决策、改进业务流程和提高产品质量等方面的工具。它可以接收多种…

C语言中一维数组及二维数组的运用

1、int arr[] {12,3,4,5,6}; int * p arr; int * q &arr[1]; 其中arr是数组名&#xff0c;代表了整个数组的首元素地址&#xff0c;这个是一个常量&#xff0c;放在常量存储区&#xff0c;所以在给int*p赋值的时候可以不用带&&#xff0c;而下面的arr[1]则代表数…

操作系统8:存储器的层次结构及程序的装入和链接

目录 1、存储器的层次结构 &#xff08;1&#xff09;多层结构的存储器系统 1.1 - 存储器的多层结构 1.2 - 可执行存储器 &#xff08;2&#xff09;主存储器与寄存器 2.1 - 主存储器 2.2 - 寄存器 &#xff08;3&#xff09;高速缓存和磁盘缓存 3.1 - 高速缓存 3.2 …

Tauri 提供界面 + 使用 Rust 实现连接远程 Linux 服务器、发送文件、执行命令

Tauri 提供界面 使用 Rust 实现连接远程 Linux 服务器、发送文件、执行命令 文章目录 Tauri 提供界面 使用 Rust 实现连接远程 Linux 服务器、发送文件、执行命令一、Tauri 概述二、界面预览三、代码参考1、main.rs2、App.vue3、Greet.vue4、依赖 一、Tauri 概述 Tauri 是一…