目录
vue学习过程中问题点记录。
1.created()和mounted()的区别及其用法
在Vue.js中,created()和mounted()是两个常见的生命周期钩子函数。具体用法和区别如下:
created()方法:在Vue实例被创建之后立即执行。在这个阶段,Vue实例的数据观测和事件配置已完成,但尚未挂载到DOM上。通常在这个阶段执行一些数据初始化、事件监听、异步请求等逻辑,但不涉及DOM操作。
mounted()方法:在Vue实例挂载到DOM之后执行。在这个阶段,Vue实例已经完成了数据观测、编译渲染、创建虚拟DOM和真实DOM等所有过程,可以进行DOM操作。通常在这个阶段执行一些需要依赖DOM元素的逻辑,如获取元素尺寸、绑定事件、设置定时器等。
<script>
export default {
data() {
return {
message: 'Hello, World!'
}
},
created() {
console.log('created:', this.message); // 'created: Hello, World!'
// 执行一些数据初始化、事件监听等逻辑
},
mounted() {
console.log('mounted:', this.$el.textContent); // 'mounted: Hello, World!'
// 执行一些需要依赖DOM元素的逻辑,如获取元素尺寸、绑定事件、设置定时器等
}
}
</script>
总结:需要注意的是,created()和mounted()只有在Vue实例被成功创建和挂载后才会执行,如果中间发生了错误或中止,那么这两个函数也不会执行。在使用这两个函数时,要避免过多的依赖全局状态或其他模块,以保证逻辑的灵活性和可重用性。
2.vue生命周期函数
1.什么是生命周期
vue的生命周期是指:从vue实例产生开始到vue实例被销魂这段时间所经历的过程。
vue实例的创建和销毁过程好比人的一生从出现到死亡过程。在其中一些重大经历,也就是特殊时间点,我们可以做什么事情。
在vue的一生中,从vue组件创建开始一直到其被销毁时的时间段中,也被建立了几个特殊的时间点,为了方便开发者实现在特定的时候让vue在特定的时间做特定的事情。通过一个叫做“生命周期钩子函数”的方法进行设置。在vue中,vue的一生被8个生命周期钩子函数给支配着。
也可以理解为回调函数,当我们写了周期函数后,在规定的时间点,vue会自动执行这个函数。
钩子函数:可以简单理解为是一种系统在不同的阶段自动执行、用户无须干预的函数。
2.生命周期简介
vue的生命周期事件主要被分为2个钩子:事件之前和事件之后调用。具体来说,可分为4种类型的事件:
● 创建–在组件创建时执行 。
● 挂载–DOM被挂载时执行 。
● 更新–当响应数据被修改时执行 。
● 销毁–在元素被销毁之前立即执行。
函数 | 简介 |
---|---|
beforeCreate | 在 VUE 实例生成之前会自动执行的函数。 |
created | 在 VUE 实例生成之后会自动执行的函数。 |
beforeMount | 在组件内容被渲染到页面之前自动执行的函数。 |
mounted | 在组件内容被渲染到页面之后自动执行的函数。 |
beforeUpdate | 当data中的数据发生变化前执行的函数。 |
updated | 当data中的数据发生变化后执行的函数。 |
beforeUnmount | VUE实例与元素解除绑定前执行的函数。 |
unmounted | VUE实例与元素解除绑定后执行的函数。 |
代码举例:
<script src="../vue.global.js"></script>
</head>
<body>
<div id="myDiv"></div>
</body>
<script>
// 生命周期函数:在某一时刻会自动执行的函数
const app = Vue.createApp({ // 创建一个vue应用实例
data() {
return {
message : "hello"
}
},
//在实例生成之前会自动执行的函数
beforeCreate() {
alert("beforeCreate")
},
//在实例生成之后会自动执行的函数
created() {
alert("created")
},
// 在组件内容被渲染到页面之前自动执行的函数
beforeMount() {
alert("beforeMount:" + document.getElementById("myDiv").innerHTML)
},
// 在组件内容被渲染到页面之后自动执行的函数
mounted() { // 绑定后自动执行
alert("mounted:" + document.getElementById("myDiv").innerHTML)
},
// 当data中的数据发生变化前执行
beforeUpdate() {
alert("beforeUpdate:" + document.getElementById("myDiv").innerHTML);
},
// 当data中的数据发生变化后执行
updated() {
alert("updated:" + document.getElementById("myDiv").innerHTML);
},
// 解除绑定前执行的函数
beforeUnmount() {
alert("beforeUnmount:" + document.getElementById("myDiv").innerHTML);
},
// 解除绑定后执行的函数
unmounted() {
alert("unmounted:" + document.getElementById("myDiv").innerHTML);
},
// 如果没有 template ,则取绑定元素下面的子元素作为 template
template : "<div>{{message}}</div>"
});
// vm 就是vue应用的根组件
const vm = app.mount('#myDiv'); // 绑定id为myDiv的元素
// 更新数据
vm.$data.message = 'hello world!!!';
// 解除绑定
app.unmount();
</script>
3.vue中动态添加的元素点击事件失效
今天遇到了个问题,经过查找资料,排查了3个小时才解决,功夫不负有心人,记录下问题和解决方法。
在vue的mounted方法中,有这样一段动态插入元素并设置点击事件的方法:
mounted(){
var td = document.createElement("td")
td.innerHTML = `<a class="delA" @click="Delete" style="padding:0 30px">删除<a> <a class="mdfA" herf="#" @click="Modify" style="padding:0 30px">修改<a>`
}
vue的methods方法定义了Delete方法和Modify方法,如下:
methods: {
Detete(){
consolg.log("删除了");
},
Modify(){
consolg.log("修改了");
}
但是,奇怪的是,2个a标签里的点击事件并没有生效,即点击删除和修改标签的时候,Delete方法和Modify方法没有被调用。
vue中动态添加的元素点击事件之所以不能被触发是因为,vue中动态生成的页面元素,是在Vue文件编译之后插入到页面中的,不会被Vue编译,只会作为普通的html代码被插入,所以无法识别vue事件。既然是普通的html代码,那我们可以使用原生的事件去代替vue事件,原生事件一定会被触发,但此时又出现一个新问题,那就是原生事件被触发后,无法访问到vue实例的data中的数据和methods中的方法,究其原因还是由于没有被vue编译的问题。
既然问题出现了,那就想办法解决问题。既然访问不到vue实例中的数据和方法,那么我们可以将事件所需要使用的数据和方法,挂载在window对象上,这样就可以被原生事件访问到了。
解决方法:
- 在vue的created方法中添加如下代码来挂载Delete方法和Modify方法:
created() {
let _this = this;
window.Delete = _this.Delete;
window.Modify = _this.Modify;
},
- mounted方法更新为:
mounted(){
var td = document.createElement("td")
td.innerHTML = `<a class="delA" οnclick="Delete()" style="padding:0 30px">删除<a> <a class="mdfA" herf="#" οnclick="Modify()" style="padding:0 30px">修改<a>`
}
这样就可以实现,动态添加的元素并绑定点击事件的效果了。
4.vue如何获取数据值
Vue提供了一系列的方法来获取数据值,包括获取data中的值、获取computed中的值和获取props中的值。
1.获取data中的值
在Vue实例中,可以通过this.$data来访问data对象。例如:
<template>
<div>
<p>{{msg}}</p>
<button @click="getData">获取数据</button>
</div>
</template>
<script>
export default {
data() {
return {
msg: 'Hello World!'
}
},
methods: {
getData() {
console.log(this.$data.msg)
}
}
}
</script>
上述代码中,在data中定义了msg属性,并且通过this.$data.msg来访问它。通过这种方式,我们可以获取data对象中所有的属性值。
2.获取computed中的值
computed在Vue中是一个十分有用的概念。computed属性是响应式的,当它所依赖的属性发生变化时,它会自动重新计算。在获取computed属性的值时,我们可以直接访问它们。例如:
<template>
<div>
<p>{{msg}}</p>
<button @click="getData">获取数据</button>
</div>
</template>
<script>
export default {
data() {
return {
name: 'Lucy',
age: 18
}
},
computed: {
msg() {
return `我的名字是${this.name},我今年${this.age}岁了。`
}
},
methods: {
getData() {
console.log(this.msg)
}
}
}
</script>
在上述代码中,定义了一个computed属性msg,用来计算一段字符串。可以直接通过this.msg来访问这个计算属性的值。
3.获取props中的值
在使用Vue开发组件时,可以在组件中定义props属性,并通过它来传递数据。在获取props中的值时,我们可以直接通过props对象访问。例如:
<template>
<div>
<p>{{msg}}</p>
</div>
</template>
<script>
export default {
props: {
name: String,
age: Number
},
computed: {
msg() {
return `我的名字是${this.name},我今年${this.age}岁了。`
}
}
}
</script>
在上述代码中,我们定义了两个props属性name和age,分别是字符串和数字类型。我们通过this.name和this.age来访问它们的值。
4.总结
在Vue中,获取数据值是非常重要的一个概念。可以通过this.$data来访问data对象中的所有属性值,通过直接访问computed属性来获取计算属性的值,通过props对象来获取父组件传递过来的数据。这些方法可以帮助我们更方便地获取数据值。
5.动态 import
以前我们import导入模块是在一开始的时候就全部导入了,这样在模块很多的时候,会显得网页速度加载很慢,在ES11中就提供了一种动态import,案例演示如下:
m1.js:
//分别暴露
export let school = "西北工业大学";
export function study() {
console.log("我们要学习!");
}
index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<button id="btn">点击我,加载m1.js模块</button>
<!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
<script type="module">
const btn = document.getElementById("btn");
btn.onclick = function(){
import("./m1.js").then(module => {
module.study();
});
};
</script>
</body>
</html>
6.关于let和var的区别
- 作用域不同:
- let定义的变量作用域仅限于定义该变量的代码块中。比如:if … else,for…in…,switch…case…等等。
- var定义的变量作用域为定义该变量的函数范围中(当在函数中定义时),或者为全局的范围(当定义为全局变量时)。
比如以下面一段if条件判断代码为例:
(function(){
if (true) {
var a = 13
}
console.log(a) //控制台输出:13
})()
在if代码块内使用var定义的变量a,在代码块外仍然可以访问,控制台打印出了a的值。
(function(){
if (true) {
let a = 13
}
console.log(a) //控制台输出:ReferenceError: a is not defined
})()
当我们将var替换成let时,在if代码块外访问时,会直接报错。
- 访问顺序的要求不同:
- var定义变量,可以在未定义前访问。
- let定义变量,必须先定义,后访问。
(function(){
console.log(a)
console.log(b)
var a = 10
let b = 11
})()
控制台输出:
undefined
ReferenceError: Cannot access 'b' before initialization
a可以在var未定义前访问,值为undefined,b在let未定义前访问直接报错。
- 是否可被重复定义:
- let:同一代码块中,同名变量不可被重复定义。
- var:同一作用域下,同名变量可以被重复定义。
还是以if条件语句为例:
let:
(function(){
if (true) {
let a = 11
let a = 12
console.log(a) // 控制台:SyntaxError: Identifier 'a' has already been declared
}
})()
var:
(function(){
if (true) {
var a = 11
var a = 12
console.log(a) // 控制台:12
}
})()
js中的let相比var更严谨,也更符合我们的编程思维和习惯。应更偏向使用let而不是var。
7.js中dom元素的classList.toggle(“”)方法
classList.toggle()方法用于在元素的class属性中添加或删除指定的类名。具体来说,该方法会检查元素的class属性中是否含有指定的类名,如果没有则添加该类名,如果有则删除该类名。
方法的语法:element.classList.toggle(“classname”);
其中,element为要操作的元素,classname为要添加或删除的类名。执行该方法后,如果元素中已经包含了该类名,则该方法会将该类名从元素的class属性中删除;如果元素中不包含该类名,则该方法会将该类名添加到元素的class属性中。例如:
HTML代码:
<div id="myDiv" class="box"></div>
JS代码:
var myDiv = document.getElementById("myDiv");
myDiv.classList.toggle("box"); //删除box类名
myDiv.classList.toggle("container"); //添加container类名
执行后,HTML代码为:
<div id="myDiv" class="container"></div>
可以看到,原先元素中的box类名已经被删除,同时添加了container类名。如果再次执行该方法,container类名将被删除,恢复原先的状态。