03-修饰符-监听属性-发送Ajax请求-生命周期钩子

人のエゴで造られた 虚にだけはなりたくはなくて / 2024-04-28 / 原文

事件修饰符

事件修饰符 作用
.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元素传递,由内而外,依次触发。

img

stop (停止冒泡) 一般添加到子元素使用

当使用 .stop 事件修饰符时就能很简单的阻止冒泡了,用法如下,直接给子盒子的点击事件后加上.stop即可:

<div class="outer" @click="outerEvent">
    <div class="inner" @click.stop="innerEvent">不要点我啊 >_<</div>
</div>

img

self (点击自己才会执行) 一般加到父元素

<div class="outer" @click.self="outerEvent">
    <div class="inner" @click="innerEvent">不要点我啊 >_<</div>
</div>

img

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>

img

事件只执行一次 .once

抽奖页面大概率都是使用了这个

<div class="outer" @click.self="outerEvent">
    <div class="inner" @click.once="innerEvent">不要点我啊 >_<</div>
</div>

img

用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>

img

表单控制

在Vue.js中,:valuev-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>

img

购物车案例

需要留意的几个问题:

  1. 全选/全不选和下面的复选框并不是一起的,所以需要单独起一个函数去控制。

  2. 一般情况下true和false事件第一事件想到的就应该是change事件。

  3. 只要下面复选框不是全部选中,那么全选复选框应该是非选中状态。

    判断长度,只要下面商品选中的长度之和等于列表长度,那么全选设置为true,否则设置为false

  4. 在JavaScript中,字符串是可以和数字进行乘法操作的,但是不建议,还是建议严谨一些,使用number类型。

  5. 传递的时候,传递对象才可以同步去修改,传递数字不可以,就相当于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>

img

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>

img

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>

image-20240426203231069

<!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>

img

排序问题

如果要排序,是前端发送排序请求给后端,后端去完成排序请求,然后拿到数据渲染到页面,而不是前端去完成排序。(虽然前端也可以)

监听属性

监听住一个属性,只要这个属性发生变化,就执行函数.

这种自动更新是通过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>

img

组件的使用

# 组件就是:扩展 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>

img

生命周期钩子案例(启动计时器,销毁计时器)

<!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>

img