栈内存:存放基本数据类型的变量名和变量值;复杂(引用)数据类型的变量名和引用地址
堆内存:复杂数据类型的变量值
1.let命令
var 和 let的区别(var的三大bug):
2.const命令
是一个只读的常量,声明时,必须赋初值,一旦声明,栈值就不能改变,
3.变量的结构赋值
包括数组和对象的结构赋值
数组: let [a, b, c] = [10, 20, 30];
对象:let { name1, age1 } = { name1: ‘李四’, age1: 29 };
4.对象的扩展
包括属性的简写,方法的简写,扩展运算符,模版字符串
属性的简写::当属性名和值的变量名相同时,触发对象的属性简写let name = ‘张三’; const person ={name}
方法的简写:去掉冒号和function,
eat() {
return ‘三顿’
}
扩展运算符:三个点(…).可遍历属性。.三个点放在对象前,用于对象的合并等
let z = { a: 10, b: 20 }
let n = { …z, c: 30 };
console.log(n) // {a: 10, b: 20, c: 30}
模版字符串:模板字符串用反引号()表示,嵌入变量用${}表示 let idCard = '360424198612121539'; let str =
身份证号码${idCard} `
5.箭头函数
主要针对的是函数变量,即带有函数名的函数;使用箭头( => )连接参数列表和函数体
箭头函数的简化:
参数只有一个时,括号可以省略
const say = msg => {
函数体
}
无参数时,括号不能省略
const say = () => {
函数体
}
参数多个时,括号不能省略
const say = (x,y) => {
函数体
}
可变参数,括号不能省略
const say = (…args) => {
函数体
}
函数体只有一条return时,可以省略大括号和return关键字
const say2 = x =>x+1
函数体包含多条语句时,不可以省略大括号和return关键字
函数体中有一个对象时,省略大括号和return关键字后需要用小括号
-const student2 = () => ({ name: ‘张三’, age: 25 })
6.模块语法
export:规定模块的对外接口,如果希望外部能够获取模块内的某个变量/函数/类,就必须在模块中使用export输出该变量/函数/类
const PI = 3.1415
const add = (a, b) => a + b
export { PI as pi, add } //可以合在一起导出,也可以分别导出
import:引入模块
//import { pi as PI, add } from ‘./demo1.js’
import * as abc from ‘./demo1.js’ // 导入全部
console.log(‘pi的值为:’, abc.pi)
console.log(‘调用add函数:’, abc.add(40, 50))
export default:每个模块【只能够使用一次】,可以导出变量,常量,函数,类,匿名函数
export default (a, b) => a + b //默认导出的是匿名函数
对于export default导出的,导入时,不需要{},并且变量名可以随意
import 你家的孩子 from ‘./demo2.js’
console.log(‘变量值为:’, 你家的孩子(3, 6))
7.Promise异步编程
Promise对象要点:
原理:异步执行,当接口请求后,可以去做其他事情,等接口返回成功再渲染页面,接口返回失败也会有相应的提示
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>8-1 promise对象.html</title>
</head>
<body>
<script>
/*
Promise对象要点:
1.Promise对象是用于执行异步操作的
2.可以使用Promise构造函数来创建实例对象
3.Promise对象的.then方法调用后,返回的还是一个Promise对象
4.Promise对象的.catch方法调用后,返回的还是一个Promise对象
*/
/*
步骤1:创建Promise对象
1.调用构造函数,来创建Promise对象
2.构造函数的参数,是一个函数【参数是函数】,它负责执行业务
3.该函数接受2个参数作为参数
4.第一个参数:是resolve(成功的)函数,可以是其他
5.第二个参数:是reject(拒绝的)函数
*/
const p1 = new Promise((resolve, reject) => {
console.log('1.异步请求开始,异步讨债开始')
// 去讨债开始......
// ......漫长的过程,....可以去干其它事情....
// 讨债结束.....
const flag = false
if (flag) { //resolve方法执行后,则执行then的第一个参数
return resolve('还钱成功!')//异步调用,只支持一个参数(可以是一个对象)
} else {
return reject('还钱失败!')//它们前面加上return语句,这样就不会有意外。
}
})
/*
要点:
1.then方法,也接收2个函数作为参数,但第二个参数是可选的
2.当resolve方法调用时,会触发then的第一个参数
3.当rreject方法调用时,会触发then的第二个参数
*/
//步骤2:调用异步执行.then方法
const p2 = p1.then((a) => {
// throw new Error('4.人为模拟异常,还的钱是假钱...')
console.log('3.进来了then的第一个方法,还钱成功了,用钱干什么,买手机。。。', a)
}
// , () => {//第二个参数是可选的
// console.log('3.进来了then的第二个方法,,还钱失败了,怎么办。。。')
// }
)//还可以继续.then
/*
要点:
1.catch方法,也接收1个函数作为参数
2.当【前面】的方法中有异常时,才会触发catch的参数
*/
// 步骤3.调用catch方法,then方法有效
const p3 = p2.catch((e) => {
console.log(`catch方法被调用了${e}`)
}).finally(() => { //无论如何都会执行
console.log('finally')
})
console.log('2.底部的代码调用了,将在当前脚本所有同步任务执行完才会执行点then异步代码')
//Promise 新建后立即执行,所以首先输出的是Promise。
//然后,then方法指定的回调函数,将在当前脚本所有同步任务执行完才会执行,所以resolved最后输出。
</script>
</body>
</html>
1.在本地电脑创建一个文件夹
2.终端进入文件夹,创建项目:npm create vue@3,命名项目名称,出现如下界面
3.VSCode编辑器中,在终端执行一下命令,初始化并启动项目
4.页面执行顺序
创建一个vue组件,main.js中导入该vue组件,挂载文件index.html 就可以找到该组件并运行在浏览器中
//main.js文件
import { createApp } from 'vue' //不是路径的话,必须package.json中定义,dependencies
import { createPinia } from 'pinia'//{}是采用export形式导出的
//import App from './App.vue'//export default导出的,App这个名字可以任意取。
import App from './components/CaoQing.vue'
import router from './router' //会找router文件下的index.js
import './assets/main.css'
//创建vue实例化对象
const app = createApp(App) //app名字上随便的
//使用第三方插件/库
app.use(createPinia())
app.use(router)
//把创建的vue实例,挂载到 index.html
app.mount('#app') //括号里的app要和index.html里的<div id="app"></div>的id一致
//总结:把开发的vue组件放到index.html里运行
//main.js:入门文件/主文件
//App.vue :根组件
//index.html ://挂载文件
//.vue结尾的都叫一个组件,打包工具会把组件打包成一个js,js会加上export default
//三个地方可以放组件:components:公共组件 views:业务组件 App.vue:src根目录下
//index.html文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vite App</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>
创建组件,组件名首字母要大写,以.vue后缀表示组件,装的插件有自动补全功能,所以只需要输入vbase,选择弹出的含有reactive的模版。Vue3的基本指令都是在template模版中使用,以下是模版简介
<template>
<!-- 第一部分:template模版,相当于html的body部分,是必须的 -->
<!-- 在模版中可以【直接使用】返回对象中的属性/方法 -->
<div>响应式对象计数:{{ count }}</div>
<div>普通对象计数:{{ count1 }}</div>
<div>响应式变量计数:{{ age }}</div>
</template>
<script>
//第二部分:js部分
import { onMounted, reactive, ref, toRefs } from 'vue'
export default {
//1.setup函数,是一个生命周期函数,是组合式API的起点
//它比较特殊,无需从vue中导入,其他的周期函数都需要导入才能使用,而且其他生命周期函数都需要在setup函数使用
setup() {
//2.定义一个【响应式】对象 =》页面会变化
const state = reactive({
count: 0
})
//定义一个【普通】对象 =》页面不会变化
const state1 = {
count1: 0
}
//2.【响应式】变量 =》页面会变化
const age = ref(0)
//3.定义一个函数,方法不存在收否响应
const addOne = () => {
state.count += 1
state1.count1 += 1
age.value += 1
}
//4.生命周期函数:当页面加载完成后,才会执行
onMounted(() => {
//5.每隔多久执行某个代码/函数
setInterval(addOne, 1000)
})
//以上定义的属性和方法必须返回,模板中才能使用
//注意:如果是响应式对象里的变量,就不需返回模版里也可以使用
return {
age,
//toRefs:把一个【响应式】对象,转换成普通对象,该普通对象的每一个属性值都是ref类型
//三个点是扩展运算符,取出对象的所有可遍历属性
...toRefs(state),
...state1
}
}
}
</script>
<style lang="scss" scoped>
</style>
(1)文本插值
数据绑定最常见的形式就是使用双大括号的文本插值,基本语法:{{ 变量/数组/对象等 }}
(2)v-text指令 和 v-html指令
键盘常用事件:
v-on用于:基本语法 <标签 v-on:事件名=“事件的处理方法或脚本”><标签/>
缩写是@:<标签 @事件名=“事件的处理方法或脚本”><标签/>
(8)v-model(表单输入绑定)
所谓表单,指的是html的input ,select,textarea等表单的元素,v-model实现和这些标签数据的双向绑定,监听用户的输入事件来更新数据。它本质上是一个语法糖,实际上就是v-bind:value + v-on:input的组合。
双向绑定:用javascript命令改变数据的值时,会在页面中自动重新渲染内容,改变文本框的内容也会自动修改绑定的数据(可在控制台看,以便于存放修改后的数据到数据库)。
可用于文本框,单选框,复选框,下拉列表,多行文本框的绑定
基本语法:<标签 v-model=“响应式数据”><标签/>输入框可以.number 限制只输入数字,.trim 去除左右空格。例如v-model.number和v-model.trim
1.计算属性:
使用computed方法实现,方法参数是一个函数,它必须有return返回值,在该函数中,任意一个响应式数据发生变化,computed方法都将自动重新运算,视图也会同步更新,默认第一次就会调用。
2.侦听属性:
使用watch方法实现,该方法有三个参数:
3.watchEffect:
和watch功能类似,不同的是 它会自动监听其内部回调函数使用到的数据,其中任意一个数据发生了变化,它都会执行回调函数,首次加载就会执行一次。
只有一个参数,该参数是一个函数
4.总结
计算属性:
watchEffect
和watch功能类似,不同的是:
1.组件的常用的生命周期
创建-》挂载-》更新-》销毁
以下代码说明:
<template>
<div class="about">
<h1>This is an about page(生命周期)</h1>
<div>
<input type="radio" name="xb" value="1" v-model="sex" />男
<input type="radio" name="xb" value="2" v-model="sex" />女
</div>
</div>
</template>
<style>
@media (min-width: 1024px) {
.about {
min-height: 100vh;
display: flex;
align-items: center;
}
}
</style>
<script>
import {
onBeforeMount,
onBeforeUnmount,
onBeforeUpdate,
onMounted,
onUnmounted,
onUpdated,
reactive,
toRefs
} from 'vue'
export default {
setup() {
//第一阶段:创建
console.log('1~2.setup()函数开始了!!!!相当于vue2的(BeforeCreate、Created)')
const state = reactive({
count: 0,
sex: 1
})
//阻塞的睡眠函数(delay参数:N毫秒)
//普通函数
function sleep2(delay) {
//当前时间
const start = new Date().getTime()
//执行的时间4 小于 设定的等待时间5 就继续等待,如果6大于等待的时间5,则跳出循环不再等待执行下一步骤
while (new Date().getTime() - start < delay) {
//继续,调用while
continue
}
}
//箭头函数
const sleep = (delay) => {
//当前时间
const start = new Date().getTime()
//执行的时间4 小于 设定的等待时间5 就继续等待,如果6大于等待的时间5,则跳出循环不再等待执行下一步骤
while (new Date().getTime() - start < delay) {
//继续,调用while
continue
}
}
//第二阶段:挂载,组件被挂载到index.html上
//2。挂载前
onBeforeMount(() => {
console.log('3.onBeforeMount被调用了!(挂载前。。。。)')
// 在组件挂载到index.html之前,睡大觉。睡5秒
sleep(3000)
})
onMounted(() => {
console.log('4.onMounted被调用了!(挂载后。。。。)')
})
//第三阶段:数据更新
onBeforeUpdate(() => {
console.log('5.onBeforeUpdate被调用了!(更新前。。。。)')
})
onUpdated(() => {
console.log('6.onUpdated被调用了!(更新后。。。。)')
})
//第四阶段:销毁阶段,vue组件被销毁,即点击其他组件时,当前组件被销毁
onBeforeUnmount(() => {
console.log('7.onBeforeUnmount被调用了(组件失效了。。。)!')
})
onUnmounted(() => {
console.log('8.onUnmounted被调用了!(组件失效且销毁了。。。)')
})
return {
...toRefs(state)
}
}
}
</script>
2.组件的使用步骤
<template>
<div>
<h2>组件的使用步骤</h2>
<h3>这里是父组件-FatherComp.vue</h3>
<!-- 步骤3:使用子组件 -->
<!-- 单标签 -->
<!-- <ChildComp /> -->
<!-- 标签对 -->
<child-comp></child-comp>
<!-- <ChildComp></ChildComp> -->
</div>
</template>
<script>
import { reactive, toRefs } from 'vue'
//步骤2-1:导入子组件
import ChildComp from './ChildComp.vue'
export default {
//步骤2-2:注册子组件
components: { ChildComp },
setup() {
const state = reactive({
count: 0
})
return {
...toRefs(state)
}
}
}
</script>
<style lang="scss" scoped>
</style>
3.父组件传递数据给子组件(80%以上用这个)
前提是:父子组件已经关联,参考2进行关联
<child-comp v-bind:ccount="count" v-bind:cname="name" :clistObj="listObj"></child-comp>
<template>
<div>
<h4 style="color: red">这里是子组件-ChildComp.vue</h4>
<!-- 子组件渲染 -->
<h5>这里是从父组件传递过来的ccount的值:{{ ccount }}</h5>
<p>这里是从父组件传递过来的cname的值: {{ cname }}</p>
<p>这里是从父组件传递过来的clistObj的值: {{ clistObj }}</p>
<ul>
<li v-for="(obj, index) in clistObj" :key="index">{{ obj.id }}-{{ obj.realName }}</li>
</ul>
</div>
</template>
<script>
import { reactive, toRefs, ref, watch, watchEffect } from 'vue'
export default {
// props: ['ccount', 'cname', 'clistObj'],
//Number、String、Array、Object等等
//导入父组件模版中定义的值
props: { ccount: Number, cname: String, clistObj: Array },
setup(props) {
const state = reactive({
count: 0,
ccount: 0 //定义一个响应式变量,接收父组件传过来的变更的值
})
//因为只执行一次,所以值一直不变
// console.log('拿到的props的值为:', props.ccount)
// 如果ccount 在setup中,也需要有响应式,怎么办?
// 可以采用:侦听器
watch(
() => props.ccount,
() => {
console.log('调用了watch方法。')
state.ccount = props.ccount
console.log('拿到的props的值为:', state.ccount)
},
{ immediate: true }
)
//父组件值改变,子组件值跟着改变,方便存储到数据库
// watchEffect(() => {
// console.log('进来了watchEffect')
// state.ccount = props.ccount
// console.log('拿到的props的值为:', state.ccount)
// })
return {
// result,
...toRefs(state)
}
}
}
</script>
<style lang="scss" scoped>
</style>
4.子组件传递数据给父组件(用的比较少)
前提是:父子组件已经关联,参考2进行关联
/*
setup接收2个参数,第一个是props,它为响应式对象。第二个参数context,它是非响应式对象
context对象包括三个属性:emit(方法)、slots(插槽对象)、attrs(attribute对象)
context:{ emit:()=>{}, slots:{}, attrs:{} }
我们也可以对它进行解构
*/
setup(props, { emit }) {
const state = reactive({
count: 10000,
name: '小马云',
obj: { name: '张三', age: 29 },
objList: [
{ id: 1, name: '张三', age: 22 },
{ id: 2, name: '李四', age: 23 },
{ id: 3, name: '王五', age: 25 },
{ id: 4, name: '李世民', age: 27 },
{ id: 5, name: '朱元璋', age: 30 }
]
})
const sendMsg = () => {
console.log('调用了子组件的传值方法。。。')
//传给父组件
//两个参数:1.事件名,由父组件的模版调用;2.要传递的数据
emit('caoqq', state.count, state.name, state.obj, state.objList)
}
<template>
<div>
<h2 style="color: pink">【子组件传递数据给父组件】</h2>
<h3 style="color: green">这里是父组件-FatherComp.vue</h3>
<!-- 步骤3:使用子组件 -->
<!-- 标签对 -->
<!-- caoqq是子组件中emit函数的事件名 -->
<child-comp @caoqq="getData"></child-comp>
</div>
</template>
<script>
import { reactive, toRefs } from 'vue'
//步骤2-1:导入子组件
import ChildComp from './ChildComp.vue'
export default {
//步骤2-2:注册子组件
components: { ChildComp },
setup() {
const state = reactive({
count: 0
})
//方法里的参数要和子组件中emit的一致,也可以用可变参数接收
const getData = (data, name, obj, objList) => {
console.log(
'父组件接受了子组件传过来的值:count的值为:',
data,
'name的值:',
name,
'obj的值:',
obj,
'objList的值:',
objList
)
// state.count = data
}
1.动态组件
场景:在一个父组件中同时引用三个子组件,我们想一次只显示一个组件,当点击某个按钮时,切换显示不同的组件,要实现这种组件动态显示效果,vue提供了 compoent标签,语法如下:
<compoent :is="要显示的组件名" ></compoent> //采用v-bind指令绑定is属性
<template>
<div>
<h3>这里是父组件</h3>
<!-- 使用动态使用子组件 -->
<!-- component:is ,is的值是哪个组件的名称就显示哪个组件 -->
<component :is="selectTab"></component>
<!-- 选择需要显示的组件 -->
<select v-model="selectTab">
<option value="TabOne">选项卡一</option>
<option value="TabTwo">选项卡二</option>
<option value="TabThree">选项卡三</option>
</select>
<div>选项内容:{{ selectTab }}</div>
</div>
</template>
<script>
import { reactive, toRefs } from 'vue'
//导入子组件
import TabOne from './TabOne.vue'
import TabTwo from './TabTwo.vue'
import TabThree from './TabThree.vue'
export default {
//注册子组件
components: { TabOne, TabTwo, TabThree },
setup() {
const state = reactive({
count: 0,
selectTab: 'TabOne'
})
return {
...toRefs(state)
}
}
}
</script>
2.插槽的使用
分为默认插槽(不具名插槽)和具名插槽
插槽:在子组件中留插槽,想让内容显示在什么位置,就把插槽放在哪里,插槽显示的内容是在父组件中写的。如果子组件定义了默认插槽,其他内容将显示在默认插槽中,如果定义了具名插槽具名插槽的内容将显示在具名插槽中,如果没有定义默认插槽,其他内容将不会显示
:
其中name,是父组件中定义的插槽名
,父组件模版中需要定义以下格式: 具名插槽内容-章三, v-slot: 可以缩写成 #
<!-- 在父组件中添加内容,这些内容将展示在子组件的插槽中 -->
<child-comp>
<!-- 这是不具名(默认)插槽要显示的内容 -->
这里是父组件传给子组件展示的默认插槽内容11: {{ count }}
<!-- 这是具名插槽要显示的内容 -->
<!--需要用到template标签, -->
<template v-slot:zhangsan>具名插槽内容-章三</template>
<!--需要用到template标签, -->
<template #lisi>简写具名插槽内容-李四
</child-comp>
3.响应式变量的定义
三种方式定义响应式变量
setup() {
//定义响应式变量state,但是state里的属性是没有响应式的
const state = reactive({
count: 0,
name: '张三'
})
//toRef接收两个参数:源响应式对象 和 该对象的属性名(指定属性),返回一个ref数据
// 采用toRef函数,为响应式对象的某个属性,添加响应式
const conut2 = toRef(state, 'count')
setInterval(() => {
state.count += 1
}, 1000)
//return中的变量在模版中可以直接用
return {
age: 22, //也属性响应式变量,可直接使用
conut2,
count3: toRef(state, 'count'),
// 1.toRefs,用来把响应式对象中的属性,变成响应式
...toRefs(state)
// ...state //count就没有响应式了
}
}
5.模版引用
可以获取元素的具体信息
//...1.从vue-router中导入createRouter, createWebHistory
import { createRouter, createWebHashHistory, createWebHistory } from 'vue-router'
//。。。2.导入HomeView组件
import Home from '../views/Home.vue'
//。。。。。3,使用createRouter方法创建一个路由器对象
const router = createRouter({
//路由模式1:history模式(参数:导入环境变量中的基础URL),也可以不写括号里的内容
// history: createWebHistory(import.meta.env.BASE_URL),
history: createWebHistory(),
//路由模式2:hash模式
// history: createWebHashHistory(),
routes: [
//每一个路由,都是一个对象,它包括三个属性:path,【name】,[component/redirect二选一]
{
path: '/',//根路由,路由的路径
name: 'home', //路由的名称 可以省略
component: Home
},
{
path: '/login',
// route level code-splitting 路由级代码拆分
//这将为此路由生成一个单独的模块(About.4543054354dfgdf.js)
// this generates a separate chunk (About.[hash].js) for this route
// 当访问路由时,是懒加载的
// which is lazy-loaded when the route is visited.
// 总结:路由懒加载方式,项目打包时,一个组件打包为一个js文件。访问时才加载组件。
// component: () => import('../views/AboutView.vue')
component: () => import('../views/Login.vue')
}
]
})
export default router //导出路由器
路由是用来实现页面导航的,导航分为两种:
声明式导航:在模板中声明路由链接,最终形成a标签导航
编程式导航:通过调用 JavaScript 形式的API实现导航,适合页面重定向,比 如登录成功后重定向到主页
(1)路由链接的代码如下(声明式导航的实现):
<!-- 作用:RouterLink会被渲染成一个a标签,它的to属性,会被渲染成a元素的href属性 -->
<!-- 好处:可以给to属性绑定变量(对象),to的值等于路由配置中的path -->
<RouterLink to="/about">About</RouterLink>
<RouterLink :to="{ path: '/', query: { a: '123', b: '456' } }">Home</RouterLink>
(2)路由填充位(路由占位符 )
通过路由规则匹配到的组件后,将组件的内容 渲染到路由占位符所在的位置(想在哪个组件里显示内容就在该组件留路由占位符,比如点击A组件中的【按钮】希望A组件内容在B组件展示,那么A组件和B组件就需要有关系,在同一Web网友中)。路由占位符的代码如下:
<RouterView />
或
<router-view />
或
<router-view></router-view>
总结:前端页面访问的路由在根组件App.vue里找,找到后去index.js,找到对应的组件,将组件的内容在路由占位符中显示
官网:https://element-plus.gitee.io/
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css' //样式
import zhCn from 'element-plus/es/locale/lang/zh-cn'
const elementConfig = { size: 'default', local: zhCn, zIndex: 3000 }
app.use(ElementPlus, elementConfig)
main.js中全局导入自定义样式:import ‘./assets/css/common.scss’
import * as Icons from '@element-plus/icons-vue'
// 1.注册全局elementplus icon组件 Object.keys(Icons).forEach((key) => {
app.component(key, Icons[key])
})
<el-icon><CirclePlus /></el-icon >
import { ElMessage } from 'element-plus'
# 用法一
ElMessage.type('消息内容')
// 其中:type可替换为:success、warning、info、error
# 用法二 ElMessage({
message: '消息内容',
type: 'success',// 其中:type值可为:success、warning、info、 error
})
跟缓存类似,本地存储(新增、获取、删除、清空全部)
在浏览器的Applicationd的Local Storage下的地址中查看
// A.新增
// localStorage.setItem('userName', 'caoqq')
// localStorage.setItem('userId', '123')
// localStorage.setItem('token', 'wfffdsfd')
// B.获取
// console.log('userId====', localStorage.getItem('userId'))
// C.删除
// localStorage.removeItem('userName')
// // D.清空所有
// localStorage.clear()
Axios是一个基于Promise的HTTP库,可以用在浏览器和node.js中。用于向服 务器后端发起Ajax请求,并在请求的过程中可以进行很多控制,其主要特性如下:
Axios的安装:$ npm install axios
Axios的使用:两种方式,代码如下:
// 第一步:导入axios库
import axios from 'axios'
// 第二步:编写请求配置
const config = {
url: '/token/',
method: 'post',
baseURL: 'http://地址/api',
data: {
username: "账号",
password: "密码",
captcha: "9999",
captchaKey: 1157
}
}
//第三步:发送网络请求
axios(config).then((res) => {
console.log('res的值为:', res)
console.log('res对象中的data为:', res.data)
}).catch((e) => {
console.log('异常响应对象为:', e.response)
console.log('异常响应状态码为:', e.response.status)
console.log('请求异常')
})
// 第一步:导入axios库
import axios from 'axios'
// 第二步:编写请求配置
const config = {
baseURL: 'http://地址/api',
}
// 第三步:采用别名的方式发送请求
//语法格式:axios.post(url[, data[, config]])
axios.post('/token/',
{
username: "账号",
password: "密码",
captcha: "9999",
captchaKey: 1157
}, config
).then((rep) => {
console.log('res对象中的data为.data', rep.data)
}).catch()
总结:在实际应用中会封装Axios
定义一个js文件,包括
通过调用 JavaScript 形式的API实现导航,适合页面重定向
//...1.参数为路径字符串
router.push('/about')
//...2.参数为对象-path属性
router.push({ path: '/about' }) //...3.参数为对象-name属性
router.push({ name: 'About' }) //...4.参数为对象-带查询参数
router.push({ name: 'About', query: { a: 'Hello' } })
1.主页布局
引用Element Plus布局,主页布局我们采用 左右结构 ,右边采用 上下结构
效果图如下:
3.左侧边栏组件注意内容
点击接口自动化下的各子组件时MutiTabs.vue组件会展示对应的内容
//父子路由
children: [
{
path: '/cases', // 根路由,路由的路径
name: '测试用例',
component: () => import('../views/sqtp/Cases.vue')
},
{
path: '/requests',
name: 'web接口',
component: () => import('../views/sqtp/Requests.vue')
},
{
path: '/plans',
name: '测试计划',
component: () => import('../views/sqtp/Plans.vue')
},
{
path: '/reports',
name: '测试报告',
component: () => import('../views/sqtp/Reports.vue')
}
pinia 都是状态管理库,用于跨组件(页面)进行状态共享,应用中,存在某些变量需要跨组件共享时,应该使用状态管理库。一个 Store 是一个存储实体,它有 state 、 getters 和 actions ,相当于组件中的 响应式数据 、 计算属性 和 方法 。
import { createPinia } from 'pinia'
app.use(createPinia())
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
// Setup方式定义Store
export const useUserStore = defineStore('user2', () => {
// 1.定义响应式变量
const count = ref(40)
const name = ref('张三')
// 2.定义计算属性
const doubleCount = computed(() => count.value * 2)
// 3.定义方法
const addOne = () => { count.value++ }
// 4.返回
return { count, name, doubleCount, addOne }
})
import { useUserStore } from '@/stores/user' // 1.导入一个store
export default {
setup() {
const store = useUserStore()
return {
} }
}
// 采用storeToRefs()、toRefs()函数解构,保留响应式 。记得要导出
const { count, name, doubleCount, addOne } = toRefs(store)
// $patch()方法修改(批量修改)
store.$patch({
count: store.count + 1,name: '李四' })
需求:根据当前登录的用户,从后端动态获取对应的菜单,进行格式转换后,存到本地存储中
(1)menuTree:左侧菜单数据
2)menuList: 按钮权限数据,类似:
“menuPermission”:
[“Retrieve”, “Update”, “Search”,“Create”, “Build”, “Delete”]
碰到的问题:用户在未登录的情况下,仍然可以访问Home主页。这在实际项 目中是不允许的。如何在请求每条路由链接前,判断用户是否登录呢? Vue-rout提供了全局路由守卫来监听路由的进入与离开。程序员可以通过 Vue-router 提 供的 beforeEach (前置守卫)、 afterEach (后置守卫)两个钩子函数,来搞事 情。它们分别在路由改变前和改变后触发
在项目的 router/index.js 中,添加前置路由守卫,代码如下:
/* 前置路由守卫
to表示要跳转到哪里
from 表示从哪里来
next表示动作 让进入
*/
router.beforeEach((to, from, next) => {
// 进度条开始
NProgress.start()
const userId = localStorage.getItem('userId')
if (to.path === '/login') {//1.跳转到登录界面,放行
next(true) //或者next()
} else if (userId) { // 2.有登录的,放行
next()
} else {//其他情况(无登录,且非登录界面)都跳转到登录界面
next('/login') //进入登陆界面
}
})
// 后置路由守卫
router.afterEach(() => {
// 进度条结束
NProgress.done()
})
// 进度条的配置项:ease可以设置css3动画,如ease,linear;speed是进度条从开始到结束的耗时
NProgress.configure({ ease: 'linear', speed: 500 })
xe-utils 提供了一套实用的基础函数、任意格式的日期转换函数,浏览器相 关操作函数等。提供了100多个函数,应有尽有。总之,如果你有判断、处理、转 换的一些需求,尽管来这里找找看。
官网地址:https://toscode.gitee.com/x-extends/xe-utils api
文档:https://x-extends.github.io/xe-utils/
npm install xe-utils
import XEUtils from 'xe-utils'
XEUtils.cookie('name') // 根据name获取
XEUtils.cookie('name', 'value', {expires: '7d'}) //指定7天后期
XEUtils.cookie('name', null, {expires: -1}) // 删除 XEUtils.cookie.remove(name) // 删除
思路:
利用状态管理,定义两个变量,左边菜单栏点击菜单,重复点击的菜单不重复展示
// 1.当前激活的选项卡
const activeName = ref('')
// 2.当前打开的选项卡数组
const openTabs = ref([])
系统中,业务功能菜单展示的内容,大部分布局是:上、中、下三栏布局,即顶部搜索区、中间数据表格、底部数据分页。这三个组件是通用组件
因此,我们可以单独创建一个内容页组件( MainLayout )。在该组件中,再单 独引入 Search 、 Tables 、 Paginator 三个子组件
布局采用:vh+ calc() ( 我们采用 ),即后面会在 Tables 组件中,添加了 height=“calc(100vh - 250px)”
使用 Provide (提供)和 Inject (注入)进行数据传递,父组件可以作为所有子组件的依赖项提供数据,而不管组件层次结构有多深。 这种特性有两个部分:父组件有一个 Provide 选项用于提供数据;子组件有一个 I nject 选项用于接收这个数据。例如:
在测试用例组件中利用Provide
provide('searchForm', searchForm)
provide('queryParam', queryParam)
provide('columns', columns)
provide('tableData', tableData)
provide('total', total)
provide('pageSize', pageSize)
provide('pageIndex', pageIndex)
provide('multiple', multiple)
provide('getData', getData)
const tableData = inject('tableData')
const columns = inject('columns')
const multiple = inject('multiple', false)