03-修饰符-监听属性-发送Ajax请求-生命周期钩子
事件修饰符
| 事件修饰符 | 作用 |
|---|---|
| .stop | 只处理自己的事件,父控件冒泡的事件不处理(阻止事件冒泡),一般用在子元素类上 |
| .self | 只处理自己的事件,子控件冒泡的事件不处理,一般用在父元素上 |
| .prevent | 阻止a连接的跳转 |
| .once | 事件只会触发一次(适用于抽奖页面) |
使用修饰符时,顺序很重要;相应的代码会以同样的顺序产生
- 用
v-on:click.prevent.self会阻止所有的点击 - 而
v-on:click.self.prevent只会阻止对元素自身的点击
冒泡的概念
什么是冒泡呢?以下面这个例子,比如有一个蕃茄色父盒子,里面包裹了一个白色子盒子,分别绑定点击事件将输出不同内容:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>模板</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
<style>
.outer {
width: 300px;
height: 300px;
padding: 10px;
border: 2px solid black;
margin: auto;
background-color: tomato;
}
.inner {
width: 150px;
height: 50px;
margin: auto;
text-align: center;
line-height: 50px;
background-color: snow;
}
</style>
</head>
<body>
<div id="app">
<div class="outer" @click="outerEvent">
<div class="inner" @click="innerEvent">不要点我啊 >_<</div>
</div>
</div>
</body>
<script>
let vm = new Vue({
el: "#app",
methods: {
outerEvent(){
console.log("父亲");
},
innerEvent(){
console.log("儿子");
}
},
})
</script>
</html>
效果如下,可以发现,当点击子盒子时,不仅子盒子事件被触发,连同父盒子的事件也被触发了。而只点父盒子时,只有父盒子事件触发。这就是冒泡,事件会向上级DOM元素传递,由内而外,依次触发。

stop (停止冒泡) 一般添加到子元素使用
当使用 .stop 事件修饰符时就能很简单的阻止冒泡了,用法如下,直接给子盒子的点击事件后加上.stop即可:
<div class="outer" @click="outerEvent">
<div class="inner" @click.stop="innerEvent">不要点我啊 >_<</div>
</div>

self (点击自己才会执行) 一般加到父元素
<div class="outer" @click.self="outerEvent">
<div class="inner" @click="innerEvent">不要点我啊 >_<</div>
</div>

prevent (阻止默然行为)
阻止默认事件触发。默认事件指对DOM的操作会引起自动执行的动作,比如点击a标签超链接的时候会进行默认进行页面的跳转等等。
- a连接的自动跳转。
- 表单的自动提交等。
<!-- 正常HTML代码 -->
<p><a href="#" @click.prevent="handleA">点我选壁纸</a></p>
<script>
// vue
let vm = new Vue({
el: "#app",
methods: {
handleA(){
console.log("处理完成,允许访问。");
location.href = "https://snake.timeline.ink/home"
}
},
})
</script>

事件只执行一次 .once
抽奖页面大概率都是使用了这个
<div class="outer" @click.self="outerEvent">
<div class="inner" @click.once="innerEvent">不要点我啊 >_<</div>
</div>

用capture后,是从上到下的。
按键修饰符
keyup
vue2写法:keyup.具体的键位
vue3写法:keyup.键位对应的数字
推荐
在Vue.js中,keyup是一个按键修饰符,它可以用来监听键盘的keyup事件。当您在模板中使用@keyup时,您可以指定一个键盘按键,以便在用户释放该按键时触发相应的事件处理函数。例如,您可以这样使用:
<input @keyup.enter="submitForm">
Keycode对照表(键码对照表):https://segmentfault.com/a/1190000005828048
<!-- vue2中 -->
<input type="text" @keyup.enter="showMsg" v-model="text"> --- <span>{{text}}</span>
<!-- vue2中 -->
<input type="text" @keyup.13="showMsg" v-model="text"> --- <span>{{text}}</span>
如果要获取具体的按键 可以通过下面的方式
<body>
<div id="app">
<input type="text" @keyup="showMsg" v-model="text"> --- <span>{{text}}</span>
</div>
</body>
<script>
let vm = new Vue({
el: "#app",
data: {
text: ""
},
methods: {
showMsg(e){
console.log(`你刚刚按下了 ${e.key} `);
}
},
})
</script>

表单控制
在Vue.js中,
:value和v-model之间的关系是这样的::value用于向v-model绑定的数据传递值。当使用:value时,它决定了输入元素(比如input或checkbox)的值,而这个值会影响到v-model绑定的数据。换句话说,:value提供了输入元素的值,而v-model则负责将这个值与数据进行双向绑定。
| input属性 | v-model绑定 | 完整案例 | 说明 |
|---|---|---|---|
| checkbox | 单选:布尔值remember:true, 多选:数组 hobby:[] 需要指定value |
<label>欺负小满<input type="checkbox" v-model="hobby" value="qfxm"></label> |
单选:data里面设置布尔值,多选,设定数组。 |
| radio | 字符串 gender: "" 需要指定value |
<label>女<input type="radio" v-model="gender" value="girl"></label> |
data里面设置字符串 |
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>模板</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
<style>
span {
color: tomato;
}
</style>
</head>
<body>
<div id="app">
<h3>checkbox单选就是true和false</h3>
<label>用户名:<input type="text" v-model="username"></label><br>
<label>密码:<input type="password" v-model="password"></label><br>
<label>记住密码:<input type="checkbox" v-model="remember"></label><br>
<p>用户信息:username: <span>{{username}}</span> password: <span>{{password}}</span> 记住密码: <span>{{remember}}</span>
</p>
<hr>
<h3>checkbox多选就是选value,v-model是数组</h3>
爱好:
<label>逃课<input type="checkbox" v-model="hobby" value="tk"></label>
<label>抢人头<input type="checkbox" v-model="hobby" value="qrt"></label>
<label>欺负小满<input type="checkbox" v-model="hobby" value="qfxm"></label>
<p>爱好:<span>{{hobby}}</span></p>
<hr>
<h3>raido单选也是value,v-model是字符串</h3>
性别:
<label for="">男<input type="radio" v-model="gender" value="boy"></label>
<label for="">女<input type="radio" v-model="gender" value="girl"></label>
<p>性别:<span>{{gender}}</span></p>
</div>
</body>
<script>
let vm = new Vue({
el: "#app",
data: {
username: '',
password: '',
remember: false,
hobby: [],
gender: ""
},
})
</script>
</html>

购物车案例
需要留意的几个问题:
-
全选/全不选和下面的复选框并不是一起的,所以需要单独起一个函数去控制。
-
一般情况下true和false事件第一事件想到的就应该是change事件。
-
只要下面复选框不是全部选中,那么全选复选框应该是非选中状态。
判断长度,只要下面商品选中的长度之和等于列表长度,那么全选设置为
true,否则设置为false -
在JavaScript中,字符串是可以和数字进行乘法操作的,但是不建议,还是建议严谨一些,使用
number类型。 -
传递的时候,传递对象才可以同步去修改,传递数字不可以,就相当于python中的可变数据类型。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>模板</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
<style>
table {
border: 1px solid black;
border-collapse: collapse;
}
tr, th, td {
border: 1px solid black;
padding: 10px;
}
.to-center {
text-align: center;
align-items: center;
}
</style>
</head>
<body>
<div id="app">
<table>
<caption>峡谷商品清单</caption>
<tr>
<th>id</th>
<th>名称</th>
<th>数量</th>
<th>价格</th>
<!--
全选 全不选,需要绑定一个change事件,v-model需要设置成一个布尔值,因为这是单个复选框
核心点:这个复选框和下面的复选框并不是一起的,所以是需要单独去控制
-->
<th>全选/全不选 <input type="checkbox" @change="changeEvent" v-model="checkAll"></th>
</tr>
<tr v-for="item in good_list">
<td>{{item.id}}</td>
<td>{{item.name}}</td>
<td><button @click="minus(item)">-</button> {{item.count}} <button @click="item.count++">+</button></td>
<td>{{item.price}}</td>
<td class="to-center"><input type="checkbox" @change="changeOnce" v-model="checkGoods" :value="item"></td>
</tr>
</table>
<p>全选:<span style="color:red">{{checkAll}}</span></p>
<p>商品的总价格为:<span :style="{color: 'red'}">{{totalPrice}}</span> 元</p>
<!-- {{checkGoods}} -->
</div>
</body>
<script>
let vm = new Vue({
el: "#app",
data: {
good_list: [
{ id: 1001, name: '红buff', price: 273, count: 25 },
{ id: 1002, name: '蓝buff', price: 237, count: 23 },
{ id: 1003, name: '人头', price: 5999, count: 2 },
{ id: 1004, name: '摸鱼手环', price: 1002, count: 3 },
{ id: 1005, name: '野怪', price: 249, count: 11 },
{ id: 1005, name: '河蟹', price: 308, count: 45 },
],
// 循环出来的对象放进去数组里面
checkGoods: [],
// 全选的复选框
checkAll: false,
},
methods: {
// 控制商品数量的减少 小于0 alert
minus: function(item){
if (item.count > 1){
return item.count--
}else{
alert("不能再减啦!")
}
},
// 全选/不选商品
changeEvent(){
if (this.checkAll){
this.checkGoods = this.good_list
}else{
this.checkGoods = []
}
},
// 修复全选全部选的bug
// 只要全部商品的总长度,等于列表的长度,那么全选就设置成true,除开这种情况都是false
changeOnce(){
if (this.checkGoods.length === this.good_list.length){
this.checkAll = true
}else{
this.checkAll = false
}
}
},
computed: {
// 返回选择商品的价格
totalPrice: function(){
let total = 0
for (let good of this.checkGoods) {
total += good.price * good.count
}
return total
},
}
})
</script>
</html>

v-model进阶用法(也是修饰符)
| 修饰符 | 说明 |
|---|---|
| v-model.trim | 同JavaScript语法,它用于自动过滤用户输入的首尾空格。 |
| v-model.lazy | 将输入事件从默认的 input 事件改为 change 事件。即输入框的值不会实时更新到数据,而是在失去焦点或按下回车键时才会更新到绑定的数据中。 |
| v-model.number | 如果是按数字开头,保留全部数字,放弃英文字符。如果是英文开头,都保留。 |
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>模板</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
<style>
span {
border: 1px solid black;
}
</style>
</head>
<body>
<div id="app">
<h3>常规写法(未使用lazy)</h3>
<input type="text" v-model="t0"> -- <span>{{t0}}</span>
<h3>演示v-mode.lazy</h3>
<input type="text" v-model.lazy="t1"> -- <span>{{t1}}</span>
<h3>演示v-mode.trim</h3>
<input type="text" v-model.trim="t2"> -- <span>{{t2}}</span>
<h3>演示v-mode.number</h3>
<input type="text" v-model.number="t3"> -- <span>{{t3}}</span>
</div>
</body>
<script>
let vm = new Vue({
el: "#app",
data: {
t0: "",
t1: "",
t2: "",
t3: ""
}
})
</script>
</html>

vue与Ajax
# 1 后端---》提供接口--》json形式--》给前端--》前端拿到再做处理
-后端接口
-ajax 发送请求
# 2 vue中使用ajax
-1 jquery的ajax
-2 js原生的fetch
-XMLHTTPRequest--》需要做浏览器兼容
-fetch方案
-3 第三方axios(最多)
# 3 写个后端接口--》django----》flask简单
# 4 前后端交互---》跨越问题---》后端处理
-Access-Control-Allow-Origin
因为后续用的最多的是fetch和axios,所以只列出这两种。
网友的文章:https://developer.baidu.com/article/details/2766440
解决跨域
// 响应头中添加,服务端设置 'Access-Control-Allow-Origin' = "*"
fetch发送Ajax请求
在第一个
.then中,应该返回response.json(),以便将其传递给下一个.then。此外,在第二个
.then中,应该接收到data参数,而不是直接从response对象中获取数据。
# 后端代码
from flask import Flask, jsonify, make_response
app = Flask(__name__)
@app.route("/")
def index():
data = {"name": "小满", "age": 3}
response = make_response(jsonify(data))
# 解决跨域用的
response.headers['Access-Control-Allow-Origin'] = "*"
return response
if __name__ == "__main__":
app.run(debug=True)
<script>
// 复杂的写法
fetch("http://127.0.0.1:5000/")
.then(function(response){
return response.json()
}).then(
function(data){
console.log(data);
}
).catch(function(error){
console.log(["Error", error]);
})
</script>
<script>
// 通过fetch发送Ajax请求 简单的写法
fetch("http://127.0.0.1:5000/")
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.log(['Error', error]))
</script>

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>模板</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
</head>
<body>
<div id="app">
<button @click="loadData">获取个人信息</button>
<p>姓名:{{name}}</p>
<p>年龄:{{age}}</p>
</div>
</body>
<script>
let vm = new Vue({
el: "#app",
data: {
name: "",
age: ""
},
methods: {
loadData(){
fetch("http://127.0.0.1:5000/")
.then(response => response.json())
.then((data)=>{
this.name = data.name
this.age = data.age
})
.catch(error => console.log(['Error', error]))
}
},
})
</script>
</html>
axios发送Ajax请求
<script>
// 通过axios发送请求
axios.get("http://127.0.0.1:5000/")
.then((response)=>{
// 数据从 response.data 中获取
data = response.data
console.log(data);
})
.catch(error => console.log(["Error", error]))
</script>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>模板</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/axios/1.5.0/axios.js"></script>
</head>
<body>
<div id="app">
<button @click="loadData">查看个人信息</button>
<p>姓名:{{name}}</p>
<p>年龄:{{age}}</p>
<p>爱好:{{hobby}}</p>
</div>
</body>
<script>
let vm = new Vue({
el: "#app",
data: {
name: "",
age: "",
hobby: ""
},
methods: {
loadData(){
axios.get("http://127.0.0.1:5000/")
.then((response)=>{
data = response.data
this.name = data.name
this.age = data.age
this.hobby = data.hobby
})
.catch(error => alert('发生了一些错误', error))
}
},
})
</script>
</html>
通过axios发送Ajax请求接口案例(获取电影数据)
# 后端
import json
from flask import Flask, jsonify, make_response
app = Flask(__name__)
with open("./movies.json", "rt", encoding="utf-8") as file:
data = json.load(file)
@app.route("/")
def index():
response = make_response(jsonify(data))
# 解决跨域问题
response.headers['Access-Control-Allow-Origin'] = "*"
return response
if __name__ == "__main__":
app.run(debug=True)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>模板</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/axios/1.5.0/axios.js"></script>
<style>
ul {
list-style: none;
}
</style>
</head>
<body>
<div id="app">
<button @click="loadFilm">加载电影数据</button>
<ul v-for="item in films">
<li>名称:{{item.name}}</li>
<li>类型:{{item.category}}</li>
<li>简介:{{item.synopsis}}</li>
<li>导演:{{item.director}}</li>
<li>评分:{{item.grade}}</li>
<li>地址:{{item.nation}}</li>
<li><img :src="item.poster" width="100"></li>
<hr>
</ul>
</div>
</body>
<script>
let vm = new Vue({
el: "#app",
data: {
films: null
},
methods: {
loadFilm(){
let url = "http://127.0.0.1:5000/"
axios.get(url).then((response)=>{
let dataObj = response.data.result
let filmArr = []
for (const item of dataObj) {
let filmData = {
name: item.name,
synopsis: item.synopsis,
director: item.director,
nation: item.nation,
poster:item.poster,
grade: item.grade,
category: item.category
}
filmArr.push(filmData)
}
this.films = filmArr
})
}
},
computed: {
}
})
</script>
</html>

排序问题
如果要排序,是前端发送排序请求给后端,后端去完成排序请求,然后拿到数据渲染到页面,而不是前端去完成排序。(虽然前端也可以)
监听属性
监听住一个属性,只要这个属性发生变化,就执行函数.
这种自动更新是通过Vue.js的响应式系统实现的,它会追踪每个属性的变化,并在属性值发生变化时,自动更新相关的视图。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>模板</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/axios/1.5.0/axios.js"></script>
<style>
.box {
display: flex;
justify-content: center;
}
.box-course {
width: 200px;
height: 50px;
background-color: tomato;
text-align: center;
line-height: 50px;
margin: 10px;
border: 2px solid yellow;
outline: 2px solid black;
}
</style>
</head>
<body>
<div id="app">
<div class="box">
<!-- 我这里使用的是鼠标滑动事件 mousemove 你也可以使用click点击事件 -->
<div @mousemove="courseType='Python'" class="box-course">Python</div>
<div @mousemove="courseType='JavaScript'" class="box-course">JavaScript</div>
<div @mousemove="courseType='Dart'" class="box-course">Dart</div>
</div>
<p>选中的课程是:<span :style="{color:'red'}">{{content}}</span></p>
</div>
</body>
<script>
let vm = new Vue({
el: "#app",
data: {
courseType: "",
content: ""
},
watch: {
// 可以放两个参数,第一个是老参数,第二个是新参数
// 打印的时候,新参数在前面
courseType(oldvalue, newValue){
this.content = this.courseType
console.log(oldvalue, newValue);
}
}
})
</script>
</html>

组件的使用
# 组件就是:扩展 HTML 元素,封装可重用的代码,目的是复用
例如:有一个轮播图,可以在很多页面中使用,一个轮播有js,css,html
组件把js,css,html放到一起,有逻辑,有样式,有html
# 局部组件和全局组件
-局部组件:只能在当前页面中使用
-全局组件:全局都可以用
# 定义全局组件
全局组件 component
全局组件是指在Vue应用程序中注册的组件,可以在应用程序的任何地方使用。这意味着一旦注册了全局组件,它就可以在整个应用程序范围内的任何Vue实例中使用,而不需要在每个实例中单独注册或导入。这样可以使组件在整个应用程序中变得可用,提高了组件的复用性和可维护性。
注意:组件也需要放在根组件管理的DOM中
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>模板</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/axios/1.5.0/axios.js"></script>
</head>
<body>
<div id="app">
<h2>组件首页</h2>
<hr>
<!-- 这个Child 就是我们自己定义的全局组件 -->
<Child></Child>
<hr>
</div>
</body>
<script>
// 定义全局组件 Vue.component
// 给组件起一个名字 就是第一个参数
Vue.component("Child",{
// 第二个参数是一个对象
// 对象里面必须包含几个东西 1. template 2.data 3. methods
// template 放HTML内容,这里只做一个简单的演示,后续写入到文件的vue后直接引用就行了。 这里的template和根组件的el是一个意思
// 这个组件有自己的HTML内容
template: `<div>
<button @click="handleClick">{{name}}</button>
</div>`,
// data就是之前的data,只不过并不是是直接放一个对象,而是放一个函数,返回一个对象
data(){
return {
name: "小满"
}
},
methods: {
handleClick(){
alert(this.name)
}
}
})
let vm = new Vue({
el: "#app",
})
</script>
</html>
生命周期钩子
无论是自己定义的组件,还是vue实例,都会有这几个生命周期钩子。
| 函数 | 调用时间 | 其他说明 |
|---|---|---|
| beforeCreate | vue实例初始化之前调用 | |
| created | vue实例初始化之后调用 | 这里常用于跟后端交互,因为组件已经渲染完成了,因为这个时候变量已经有了,就发送Ajax请求加载数据,然后给变量后续处理。 |
| beforeMount | 挂载到DOM树之前调用 | |
| mounted | 挂载到DOM树之后调用 | |
| beforeUpdate | 数据更新之前调用 | |
| updated | 数据更新之后调用 | |
| beforeDestroy | vue实例销毁之前调用 | 这个用的也比较多,比如组件创建后创建一个定时器,组件销毁之前清除定时器。 |
| destroyed | vue实例销毁之后调用 |

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>模板</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/axios/1.5.0/axios.js"></script>
</head>
<body>
<!-- <div id="app">
<h2>组件的使用</h2>
<button @click="handleShow">显示/隐藏组件</button>
<hr>
<child v-if="isShow"></child>
<hr>
</div> -->
<div id="app">
<h2>组件的使用</h2>
<button @click="handleShow">显示/隐藏组件</button>
<hr>
<child v-if="isShow"></child>
<hr>
</div>
</body>
<script>
let baseAssembly = {
template: `<div>
<button @click="clickEvent">{{title}}</button>
</div>`,
data(){
return {
title: "点我",
name: '小满'
}
},
methods: {
clickEvent(){
this.title = "看到大乔了吗?"
alert("小满三岁啦!")
}
},
// 加载之前
beforeCreate() {
console.log('beforeCreate'); // beforeCreate
console.log(this.name); // undefined 因为是创建之前,所以还拿不到数据
console.log(this.$el) // undefined 注意取模板需要通过 $el去取
},
//
created() {
console.log('created'); // created
console.log(this.name); // 小满
console.log(this.$el) // undefined
},
// 挂载之前
beforeMount() {
console.log('beforeMount'); // beforeMount
console.log(this.name); // 小满
console.log(this.$el) // 有数据了,就是body中自己定义的DOM
},
mounted() {
console.log('mounted'); // mounted
console.log(this.name); // 小满
console.log(this.$el) // 有数据了,就是body中自己定义的DOM
},
// 数据发生变化才会执行
beforeUpdate() {
console.log("beforeUpdate");
},
//
updated() {
console.log("updated");
},
// 删除之前
beforeDestroy() {
console.log("beforeDestroy");
},
// 删除之后
destroyed() {
console.log("destroyed");
console.log("组件已被销毁");
},
}
// 调用全局组件,实际是变量的传参
Vue.component("child", baseAssembly)
let vm = new Vue({
el: "#app",
data: {
isShow: true
},
methods: {
handleShow: function(){
this.isShow = !this.isShow
}
}
})
</script>
</html>

生命周期钩子案例(启动计时器,销毁计时器)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>模板</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/axios/1.5.0/axios.js"></script>
</head>
<body>
<div id="app">
<button @click="handleClick">销毁组件</button>
<child v-if="isShow"></child>
</div>
</body>
<script>
let baseAssembly = {
template: `<div>
<p>{{title}}</p>
</div>`,
data() {
return {
timer: null,
title: "一切都是最好的安排"
}
},
created() {
this.timer = setInterval(function () {
console.log("小满最棒啦!");
}, 1000)
},
beforeDestroy() {
clearInterval(this.timer)
this.timer = null
console.log("计时器已被销毁!");
},
}
Vue.component("child", baseAssembly)
// 根组件
let vm = new Vue({
el: "#app",
data: {
isShow: true
},
methods: {
handleClick(){
this.isShow = !this.isShow
}
},
})
</script>
</html>
