VUE前端开发-区区小事(持续更新...)


前言

咳咳! 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:从当前位置跳过后续代码,进入下个循环

  1. 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

  2. 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>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值