day02
一、异步数据
1、封装ajax:(第一天已写,这个很重要)
- 要学会promise+axios封装ajax请求的函数
- 要能封装每个接口对应的请求函数(根据接口定义ajax请求函数)
- 解决ajax的跨域问题:配置代理,对代理的理解。
- 配置--config--index.js
proxyTable: {
'/api': { // 匹配所有以 '/api'开头的请求路径
target: 'http://localhost:3000', // 代理目标的基础路径
changeOrigin: true, // 支持跨域
pathRewrite: {// 重写路径: 去掉路径中开头的'/api'
'^/api': ''
}
}
}
2、vuex编码:
- 创建所有相关的模块: store/index|state|mutations|actions|getters|mutations-types
- 设计state:也就是从后台获取的数据存储在state中
- 出现问题:对于暴露导入的理解
const state = {}
export default state
import state from './xxx.js'
//暴露时没有加{},在import时也不需要加{}
const state = {}
export default {state}
//export default {} 导出的是对象,那么引入的时候就要 import {state} from './xxx.js'
- 实现actions,此文件是用来异步获取数据的
- 定义异步action: async/await
- 流程: 发送ajax获取数据,commit提交给mutation
- 实现mutation:给状态赋值,也就是更新state数据
- 实现index:创建store对象(固定的模式)
- main.js: 配置store
3、组件异步显示数据,解决swiper动态加载数据问题
- 异步获取数据,解决swiper动态加载数据问题
参考网址: https://www.jianshu.com/p/128f3c53b66f- 在mounted()通过$store.dispatch('actionName')来异步获取后台数据到state中
- mapActions(['getAddress'])以数组形式映射模块中的方法,在mounted中调用也可以异步获取后台数据
import { mapActions } from "vuex";
methods: {
//TODO: 方法2.以数组形式映射模块中的方法
...mapActions(['getAddress'])
},
mounted () {
//TODO: 方法1.含有异步操作,例如向后台提交数据
// this.$store.dispatch('getAddress')
this.getAddress();
}
- 读取数据
- mapState(['...'])读取state中数据到组件中
- 显示数据
- 在模板中显示xxx数据
4、模板中显示数据的来源
- data:自身的数据(内部改变)
- props:外部传入的数据(外部改变)
- computed: 根据data/props/别的compute/state/getters(计算的数据)
5、异步显示轮播图
- 通过vuex获取foodCategorys数据(发请求,读取)
- 对获取的数据进行整合计算(一维变特定的二维数据)
computed: {
...mapState(["categorys"]),
/*
根据categorys一维数组生成一个2维数组
小数组中的元素个数最大是8
*/
categorysArr() {
//解构赋值
const { categorys } = this;
// 准备空的2维数组
const arr = [];
// 准备一个小数组(最大长度为8)
let minArr = [];
categorys.forEach(c => {
// 如果当前小数组已经满了, 创建一个新的
if (minArr.length === 8) {
minArr = [];
}
// 如果minArr是空的, 将小数组保存到大数组中
if (minArr.length === 0) {
arr.push(minArr);
}
// 将当前分类保存到小数组中
minArr.push(c);
});
return arr;
}
},
- 通过双循环对二维数组进行遍历显示,如果没有数据时,显示预加载图片
<nav class="msite_nav">
<!-- 判断是否有数据 -->
<div class="swiper-container" v-if="categorys.length">
<div class="swiper-wrapper">
<!-- 第一层遍历二维数组 -->
<div class="swiper-slide" v-for="(categorys, index) in categorysArr" :key="index">
<!-- 第二层遍历,对二维数组中的一维数组遍历 -->
<a href="javascript:" class="link_to_food" v-for="(category, index) in categorys" :key="index">
<div class="food_container">
<img :src="baseImageUrl+category.image_url">
</div>
<span>{{category.title}}</span>
</a>
</div>
</div>
<!-- Add Pagination -->
<div class="swiper-pagination"></div>
</div>
<!-- 没有数据时显示预加载svg -->
<img src="./images/msite_back.svg" alt="back" v-else >
</nav>
- 使用Swiper显示轮播图,如何在界面更新之后创建Swiper对象?
- 使用watch+$nextTick(),监视显示的数据,如果数据有值立即更新
watch: {
categorys(value) {
// categorys数组中有数据了, 在异步更新界面之前执行
// 使用setTimeout可以实现效果, 但不是太好
/*setTimeout(() => {
//创建一个Swiper实例对象,实现轮播
new Swiper(".swiper-container", {
loop: true, // 循环模式选项,可以循环轮播
// 如果需要分页器
pagination: {
el: ".swiper-pagination"
}
});
}, 100);*/
// 界面更新就立即创建Swiper对象
this.$nextTick(() => {// TODO: 一旦完成界面更新, 立即调用(此条语句要写在数据更新之后)
// 创建一个Swiper实例对象, 来实现轮播
new Swiper('.swiper-container', {
loop: true, // 可以循环轮播
// 如果需要分页器
pagination: {
el: '.swiper-pagination',
},
})
})
}
}
二、登录/注册:界面相关效果
- 切换登录方式
- 初始化一个boolean值(longinWay),true为短信登录,false为密码登录
- 使用@click方法设置boolean值
- 定义一个class类绑定此布尔值控制表单显示选择
loginWay: true //true代表短信登陆, false代表密码
- 手机号合法检查,发送验证码倒计时
- 通过计算属性验证输入的手机号是否正确,正确时可以点击发送获取验证码,
right_phone
类改变字的颜色
<section class="login_message">
<input type="tel" maxlength="11" placeholder="手机号" v-model="phone">
<!-- 计算属性验证输入的手机号是否正确,正确则能点击获取验证码,添加显示状态。 -->
<!-- 表单里面的button默认行为是提交表单,要取消默认行为 -->
<!-- 三目运算,模板字符串,如果时间大于0则显示当前秒数 -->
<button
:disabled="!rightPhone"
class="get_verification"
:class="{right_phone: rightPhone}"
@click.prevent="getCode"
>{{computeTime>0? `已发送(${computeTime}s)` :'获取验证码'}}</button>
</section>
data() {
return {
phone: "", // 手机号
computeTime: 0, //计时时间
}
},
computed: {
rightPhone() {
//使用计算属性测试输入的手机号是否正确,正确则显示类名
return /^1\d{10}$/.test(this.phone);
}
},
methods: {
//异步获取验证码
getCode() {
//如果当时没有计时
if (!this.computeTime) {
//启动倒计时
this.computeTime = 30;
//TODO: 间歇调用
const intervalId = setInterval(() => {
this.computeTime--;
if (this.computeTime <= 0) {
clearInterval(intervalId);
}
}, 1000);
}
}
}
- 切换显示或隐藏密码
- 通过两个输入框,一个按钮,改变密码的显示与隐藏状态
showPwd: false, //是否显示密码
<section class="login_verification">
<!-- 切换密码显示隐藏状态,改变按钮选择状态,默认为隐藏 -->
<input type="text" maxlength="8" placeholder="密码" v-if="showPwd" v-model="pwd">
<input type="password" maxlength="8" placeholder="密码" v-if="!showPwd" v-model="pwd">
<!-- 点击改变类的状态和圆圈的移动 -->
<div class="switch_button" :class="showPwd?'on': 'off'" @click="showPwd = !showPwd">
<div class="switch_circle" :class="{right:showPwd}"></div>
<span class="switch_text">{{showPwd?'abc':'...'}}</span>
</div>
</section>
- 前台验证提示
- 学会如何使用模板组件
- 调用--components-AlertTip-AlertTip.vue组件,使用提示框组件
<!-- 提示模板组件 -->
<template>
<div class="alert_container">
<section class="tip_text_container">
<div class="tip_icon">
<span></span>
<span></span>
</div>
<p class="tip_text">{{alertText}}</p>
<div class="confrim" @click="closeTip">确认</div>
</section>
</div>
</template>
<script>
export default {
props: {
alertText: String //传入的参数
},
methods: {
closeTip() {
// 分发自定义事件(事件名: closeTip)
this.$emit('closeTip')
}
}
}
</script>
<form @submit.prevent="login">
</form>
<!-- 调用组件,@closeTip自定义事件 -->
<AlertTip :alertText="alertText" v-show="alertShow" @closeTip="closeTip"/>
import AlertTip from "../../components/AlertTip/AlertTip.vue";
data() {
return {
alertText: "", //提示文本
alertShow: false //是否显示警告框
}
}
methods: {
//展示提示框
showAlert(alertText) {
this.alertShow = true;
this.alertText = alertText;
},
//关闭警告框
closeTip() {
this.alertShow = false;
this.alertText = '';
},
//异步登录
login() {
//前台表单验证
if (this.loginWay) {
//短信登录
const { phone, code } = this;
if (!this.rightPhone) {
//手机号不正确
this.showAlert("手机号不正确");
} else if (!/^\d{6}$/.test(code)) {
alert(this.code)
//验证码必须是6位数字
this.showAlert("验证码必须是6位数字");
}
} else {
//密码登录
const { name, pwd, captcha } = this;
if (!this.name) {
//用户名必须指定
this.showAlert("用户名必须指定");
} else if (!this.pwd) {
//密码必须指定
this.showAlert("密码必须指定");
} else if (!this.captcha) {
//图形验证码必须指定
this.showAlert("图形验证码必须指定");
}
}
}
}
三、前后台交互相关问题
- 如何查看你的应用是否发送某个ajax请求?
-
浏览器的network
-
- 发ajax请求404怎么办
- 查看请求路径的对错
- 单利是否生效(配置和重启)
- 服务器应用是否运行
- 后台返回了数据,但页面没有显示?
- vuex中是否有数据
- 组件是否读取了数据