文章目录
前言
咳咳! o( ̄ヘ ̄o#),大学生做开发,基本上都是严格执行软件复用的原则(๑ˉ∀ˉ๑),除了学校里教过的语言,其他的基本上都没有系统学习过,就像VUE这种,所以开发过程中会有很多小BUG,这都是由于基础知识欠缺导致的,本博客呢,主要记录我在开发VUE前端时经常碰到的问题或者需要了解的知识点。持续更新…w(゚Д゚)w
提示:以下是正文内容,其中多为个人总结,若有问题希望大家批评指正
一、全局变量、局部变量与this
1. 全局变量、局部变量的定义
参考博客《搞懂JavaScript全局变量与局部变量,看这篇文章就够了》
省流:
全局变量:四种方式
<script>
text1 = "无关键字声明的全局变量";
var text2 = "有关键字声明的全局变量";
window.test3 = 'window全局对象声明全局变量';
function bl() {
text4 = "定义在函数内部的全局变量,必须没有关键字";
}
</script>
局部变量:唯一的方式
<script>
function bl() {
var text2 = "局部变量";
}
</script>
2. this关键字与全局、局部变量
this作用域:当前函数的拥有者 / 当前函数所在上下文
以下是个人瞎总结:
- 定义在methods中的方法,拥有者是export default;export default所定义的变量放在data(){}中;所以methods中的方法调用this.变量,都是来自于data(){}中的变量。
- methods中的方法调用无this关键字的变量,都是定义的全局变量。
二、@…=“” 其实很灵活!
在vue的组件中多有@系列来触发各种事件,如@click、@change等等,而等号后面不一定要写一个函数,对于简单的赋值语句是可以直接写的,其实不是@…=“” 很灵活,而是俺太愚钝了,如下例子
@click=”this.Dialog=true“
针对打开一个dialog,是可以直接在对应按钮写个click进行赋值的。
三、axios与异步操作
直接看个例子,可以猜猜控制台打印的this.data输出内容是什么。
function (){
this.data=[];
this.$axios({
url:'http://...',
method:'post',
data:this.$qs.stringify({
userPhone:this.userPhone,
})
}).then(rst=>{
this.data=rst.data;
}).catch(ex=>{
console.log(ex);
});
console.log(this.data);
}
答案揭晓:输出的是[ ],而非rst.data。
根本原因:
这不是bug,而是对于axios了解不够。vue为了更快的运行速度,执行与后端交互的axios代码块时会进行异步操作,分为两支线程,一支执行axios,另一支执行axios之后的后续代码,而后端交互肯定没有console.log的执行速度快,所以then里的代码还没执行,console.log就优先执行了。
如何让console.log输出的是rst.data?
方式1: 将需要在axios之后执行的代码,写在axios.then里。then中的代码是必须在axios与后端交互后才能执行的,是一条线程,所以修改代码如下即可:
function (){
this.data=[];
this.$axios({
url:'http://...',
method:'post',
data:this.$qs.stringify({
userPhone:this.userPhone,
})
}).then(rst=>{
this.data=rst.data;
}).catch(ex=>{
console.log(ex);
console.log(this.data);
});
}
方式2: 添加async、await关键字,让整个function()方法严格按照同步执行,在axios处也不进行异步操作,即按照一条线程执行(这里推荐方式1)
async function (){
this.data=[];
await this.$axios({
url:'http://...',
method:'post',
data:this.$qs.stringify({
userPhone:this.userPhone,
})
}).then(rst=>{
this.data=rst.data;
}).catch(ex=>{
console.log(ex);
});
console.log(this.data);
}
总结:
所以若有关于axios与前端数据修改的操作,一定要警惕axios异步操作行为,往往遇到 “数据已经更新,但是页面没有动态渲染” 的问题,可能是axios异步操作导致的。
四、方法死锁与解决方案
背景:
题型筛选和输入搜索的兼容关系。简言之,使用输入搜索时,需要考虑之前是否进行了题型筛选,如果进行了题型筛选,则输入搜索应当在题型筛选后的基础上进行搜索;题型筛选时同理,需要考虑输入搜索。
代码编写:
- 执行输入搜索方法时,需要优先调用题型筛选,在筛选的结果上执行搜索;
- 而执行题型筛选方法时,要优先执行输入搜索,在搜索的结果上执行筛选。
死锁:
题型筛选和输入搜索两个方法,二者方法的代码中都优先互相调用了对方,导致了死锁。
思考:
从正常逻辑上讲,当执行输入搜索时,会优先执行题型筛选,且应当只执行题型筛选,但是如果采用调用题型筛选方法的策略,在执行题型筛选时,又会优先执行输入搜索,形成了死锁;对于当执行题型筛选时也是面临同理问题。所以两个方法-互相调用的策略,不能得到想要的结果。
解决方案:
- 将两个方法做筛选/搜索的关键代码块分别独立成方法,并设计judge输入参,在执行输入搜索/题型筛选时按照需求按序调用即可。
- 对于judge主要用于控制是否恢复原值再做筛选/搜索
- 举例:对于执行输入搜索,则优先调用题型筛选模块(judge=true),恢复原值做筛选。然后调用输入搜索模块(judge=false),不恢复原值做搜索,实现了基于之前筛选的结果进行搜索的效果;反之也是如此。
代码如下:
// 题型筛选块
chooseTypeBlock(judge){
// 是否恢复原值
if(judge){
this.problemDatasPart=JSON.parse(JSON.stringify(this.problemDatas));
}
// 进行筛选
if(this.queType!='全部题型'){
var i=0;
while(i<this.problemDatasPart.length){
if(this.problemDatasPart[i].problemKind!=this.queType){
this.problemDatasPart.splice(i,1);
continue;
}
i++;
}
}
},
// 输入搜索模块
selectQueBlock(judge){
// 是否恢复原值
if(judge){
this.problemDatasPart=JSON.parse(JSON.stringify(this.problemDatas));
}
// 进行搜索
if(this.selectQueContent!='' &&this.selectQueContent!=null&&this.selectQueContent!=undefined){
// 搜索内容->字符数组
var selectList=this.selectQueContent.split('');
// 查询数据
for(var i=0;i<this.problemDatasPart.length;i++){
this.problemDatasPart[i].matchDegree=0; // 建立匹配度
// 匹配
for(var k=0;k<selectList.length;k++){
// 题目字符串中有该字符,则匹配度+1
var index = this.problemDatasPart[i].problemText.indexOf(selectList[k]);
while(index!=-1){
this.problemDatasPart[i].matchDegree++;
index=this.problemDatasPart[i].problemText.indexOf(selectList[k],index+1);
}
}
}
// 根据匹配度排序
this.problemDatasPart.sort(function(a, b){return b.matchDegree - a.matchDegree});
// 删除匹配度为0的试题、删除matchDegree属性
var k=0;
while (k<this.problemDatasPart.length){
if(this.problemDatasPart[k].matchDegree==0){
this.problemDatasPart.splice(k,1);
continue;// 跳过k++,直接进入下一个循环
}
Reflect.deleteProperty(this.problemDatasPart[k],'matchDegree');
k++;
}
}
},
chooseType(){
// 在搜索的基础上,执行题型筛选
this.selectQueBlock(true); // 先搜索
this.chooseTypeBlock(false); // 保留搜索的基础,执行筛选
},
selectQue(){
// 在筛选的基础上,执行输入搜索
this.chooseTypeBlock(true); // 先筛选
this.selectQueBlock(false); // 保留筛选的基础,执行搜索
},
五、el-table 数据居中
- 表头居中::header-cell-style=“{‘text-align’:‘center’}”
- 该列数据居中:align=“center”
<el-table :header-cell-style="{'text-align':'center'}">
<el-table-column align="center"></el-table-column>
</el-table>
六、el-menu之灵活激活菜单
- default-acive:默认激活按钮,可以用变量赋值控制,可以灵活控制
- this.$route.path:获取当前路径
灵活激活当前菜单的方法如下:
<el-menu :default-active= "this.$route.path">
<el-menu-item index="/ExamList">
<span>考试列表</span>
</el-menu-item>
<el-menu-item index="/MarkTestPaper">
<span>批阅试卷</span>
</el-menu-item>
</el-menu>
七、@click绑定多个事件
- this.teacherMark=0 是赋值操作
- sumScore()是调用methods里定义的方法
一个控件的click通过分号,可以绑定多个事件。
<button @click="this.teacherMark=0;sumScore();">
</button>
八、获取v-for当前元素的index
<div v-for="(item,index) in dataList">
<span>{{item}}</span>
<span>{{index}}</span>
</div>
- item 当前元素
- index 当前元素在dataList中的索引
九、关于await的个人理解
await只能对axios和调用方法起作用,无法对普通的代码起作用。
async deleteGroup(groupId){
// axios 可行
await this.$axios({
url:'http://172.24.40.78:8088/exam/test/deleteTestGroup',
method:'post',
data:this.$qs.stringify({
userPhone:this.userPhone,
groupId:groupId
})
}).then(rst=>{
}).catch(ex=>{
console.log(ex);
});
// 调用方法 可行
await this.getGroupInfo();
// 无法用:await this.name='zzz';
},
十、for、while与continue
continue:从当前位置跳过后续代码,进入下个循环
-
for循环中使用continue,不会跳过i++(可能是for循环中i++总是最优先执行)
for(var i=0;i<10;i++){ if(i<10){ console.log(i); continue; } }
输出:0 1 2 3 4 5 6 7 8 9
-
while循环使用continue可以自由控制,取决于continue的位置(或者说取决于i++的位置)
var i=0; while(i<10){ if(i<10){ console.log(i); continue; } i++; }
输出:0 0 0 0 0…
var i=0; while(i<10){ if(i<10){ console.log(i); i++; continue; } }
输出:1 2 3 4 5 6 7 8 9
十一、el-dialog的一次性问题
el-dialog组件存在的问题:只会在第一次触发时执行相关的方法(例如数据获取等等)
解决方案: 添加v-if作为判断,可使得el-dialog每次打开时都重新执行相关方法
el-dialog通过this.flag的值作为判断来决定是否触发弹框,则添加v-if=“this.flag”,即可实现每次都重新执行的效果
<el-dialog
v-model="this.flag"
v-if="this.flag"
>
<div></div>
</el-dialog>