前端小白的学习之路(Vue2 三)

提示:学习vue2的第三天,笔记记录:生命周期,组件(注册,传值)

目录

一、生命周期

二、组件 

1.注册组件

1)全局注册

2)局部注册 

2.组件传值

1)父传子

2)子传父

3)兄弟传值


一、生命周期

在 Vue.js 2 中,每个组件实例都具有生命周期钩子函数,允许你在组件的不同阶段执行特定的操作。

  1. beforeCreate:在实例初始化之后,数据观测(data observer) 和事件配置之前被调用。在这个阶段,实例的选项属性还未被初始化。

  2. created:在实例创建完成后被立即调用。在这个阶段,实例已经完成了数据观测(data observer) 和属性的初始化,但是挂载还未开始,$el 属性还不存在。

  3. beforeMount:在挂载开始之前被调用,相关的 render 函数首次被调用。

  4. mounted:在挂载完成后被调用,el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用该钩子函数。如果根实例挂载到了一个文档内的元素上,当 mounted 被调用时 vm.$el 也在文档内。

  5. beforeUpdate:数据更新时调用,发生在虚拟 DOM 重新渲染和打补丁之前。

  6. updated:由于数据更改导致的虚拟 DOM 重新渲染和打补丁后调用。

  7. beforeDestroy:在实例销毁之前调用。在这个阶段,实例仍然完全可用。

  8. destroyed:在实例销毁之后调用。调用后,所有的事件监听器被移除,所有的子实例也被销毁

<!DOCTYPE html>
<html lang="zh-cn">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Vue</title>
    
</head>
<body>
    <div id="app">
        <h2>数字: <span>{{num}}</span></h2>
        <div ref="box">hello world</div>
        
    </div>
    <script src="./libs/vue@2.7.16/vue.js"></script>
    <script>
        //禁止控制台输出日志信息
        Vue.config.productionTip = false;
        const vm = new Vue({
            //挂载容器
            el: "#app",
            // 设置数据
            data: {
                num: 0,
                timer: null
            },
            // 生命周期: 程序从创建到销毁的过程。注意回调函数先后顺序....
            // 钩子函数: 指的是回调函数,生命周期的钩子函数(在vue@2中有8个生命周期的钩子函数)
            // 1) 创建阶段
            // 创建之前执行的钩子函数
            beforeCreate(){
                console.log("1:",this.num);//undefine
            },
            // 创建后执行的钩子函数  (初始化数据)
            created(){
                console.log("2:",this.num);//0
                console.log(this.$refs.box);// undefined
                // 初始化
                //创建一个定时器观察update(数据更新)钩子函数的执行
                this.timer = setInterval(()=> {
                    if(this.num == 5) {
                       clearInterval(this.timer);
                       return ;
                    }
                    ++ this.num;
                },1000)
            },

            // 2)挂载阶段
            // 挂载之前执行的钩子函数
            beforeMount(){
                console.log("3:",this.num);//0
                console.log(this.$refs.box);// undefined
            },
            // 挂载后执行的钩子函数 (DOM操作)
            mounted(){
                console.log("4:",this.num);//0
                console.log(this.$refs.box);// <div>hello world</div>
                // 为了让dom操作更加稳定,可以在此处执行$nextTick回调函数
                // 为了减少报错,所以调用$nextTick回调函数
                 仅在整个视图都被渲染之后才会运行的代码
                this.$nextTick(()=>{
                    // 判断程序中是否存在这个标签
                    if(this.$refs.box){
                        // 进行dom操作
                        this.$refs.box.style.color = "red";
                        this.$refs.box.style.fontSize = "20px";
                    }                   
                })
            },

            // 3)更新阶段
            // 要数据发生改变才执行的回调函数
            beforeUpdate(){
                console.log("5:",this.num);//1 ~ 5
            },
            updated(){
                console.log("6:",this.num);//1 ~ 5
            },

            // 4)销毁阶段
            // 程序不存在了,或者以后卸载组件,(显示|隐藏 v-if="false")
            beforeDestroy(){
                console.log("7:",this.num);// 0
            },
            destroyed(){
                console.log("8:",this.num);// 0
            }

        })

        // 为了看得见销毁阶段的钩子函数被执行,可以调用销毁方法
        // vm.$destroy();

    </script>
</body>
</html>

二、组件 

组件是可复用的 Vue 实例,它可以封装特定的功能和界面,并可以在应用程序中多次使用。组件使得代码更加模块化、可维护,并且提高了代码的复用性。

1.注册组件

组件只有被注册才能使用,在哪注册就只能在哪里使用

1)全局注册

通过Vue中的component方法注册组件,此方法注册的组件在任何地方都能使用

<!DOCTYPE html>
<html lang="zh-cn">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Vue</title>
    <style></style>
</head>

<body>

    <div id="app">
        <el-button></el-button>
    </div>

    <hr>

    <div id="app2">
        <el-button></el-button>
    </div>

    <script src="./libs/vue@2.7.16/vue.js"></script>
    <script>

        // 一) 全局组件
        // 1. 定义按钮组件 (template选项在vue2版本中必须有根节点)
        const ElButton = {
            // 设置数据
            data() {
                return {
                    message: "这是一个按钮123"
                }
            },
            // 渲染模板
            template: `
                <div>
                    <div>{{message}}</div>
                   <button @click="foo" style="padding: 10px 20px; border: 0; background-color: skyblue; color: white;">
                      点击按钮
                    </button>   
                </div>
            `,
            // 设置方法
            methods: {
                // 提示
                foo() {
                    alert("您好,触发事件。。。")
                }
            }
        }
        // 2. 注册组件(此处表示全局注册)
        Vue.component("el-button", ElButton);



        //禁止控制台输出日志信息
        Vue.config.productionTip = false;
        // 创建vue实例
        new Vue({
            //挂载容器
            el: "#app",
        })
        new Vue({
            //挂载容器
            el: "#app2",
        })
    </script>
</body>

</html>

2)局部注册 

通过Vue实例或某组件中的components对象注册组件,此方法注册的组件只能在注册的地方使用

<!DOCTYPE html>
<html lang="zh-cn">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Vue</title>
    <style></style>
</head>

<body>

    <div id="app">
        <!-- <ElSearch></ElSearch> 错误的,驼峰注册,(-)使用 -->
        <el-search></el-search>
    </div>

    <hr>

    <div id="app2">
        <!-- <el-search></el-search> 错误的,该组件没有在app2中注册 -->
    </div>

    <script src="./libs/vue@2.7.16/vue.js"></script>
    <script>
        //禁止控制台输出日志信息
        Vue.config.productionTip = false;
        // 创建vue实例
        new Vue({
            //挂载容器
            el: "#app",
            // 注册组件(此处表示局部注册)
            components: {
                // 此处注册组件名称采用驼峰命名“ElSearch”,在使用的时候需要改成 “el-search”
                // "el-search": {},
                "ElSearch": {
                    data() {
                        return {

                        }
                    },
                    template: `
                        <div>
                            <input type="text" placeholder="请输入关键字" style="width: 90%;height: 40px;">    
                        </div>
                    `
                },
            }
        })
        new Vue({
            //挂载容器
            el: "#app2",
        })
    </script>
</body>

</html>

注册组件注意事项

            1) 采用驼峰命名法注册组件名称时“ElSearch”,使用组件时需要改用短横线“el-search”

            2) 不能使用html文档内置的标签名称作为组件名称例如: div header footer nav

            3) 组件中的data一个函数,并且返回一个对象

            4) template选项需要有根节点(在vue@2版本)

            5) 像属性计算、侦听,过滤,生命周期的钩子和vue实例的写法一样

2.组件传值

在vue中允许组件嵌套组件但不宜嵌套过多,其中就涉及到不同组件间的数据交互的问题。

<!DOCTYPE html>
<html lang="zh-cn">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Vue</title>
    <style></style>
</head>

<body>
    <div id="app">
        <element-parent></element-parent>
        <!-- <element-child></element-child> 错误的 -->
    </div>
    <script src="./libs/vue@2.7.16/vue.js"></script>
    <script>


        //禁止控制台输出日志信息
        Vue.config.productionTip = false;
        //定义孙组件
        const ElementGrandson = {
            template: `
                <div>
                    <h4>孙组件</h4>
                </div>
            `,
        }

        // 定义子组件
        const ElementChild = {
            template: `
                <div>
                    <h3>子组件</h3>
                    <element-grandson></element-grandson>    
                </div>
            `,
            components: {
                ElementGrandson
            }
        }
        // 定义父组件
        const ElementParent = {
            template: `
                <div>
                    <h2>父组件</h2>
                    <element-child></element-child>
                </div>
            `,
            // 在父组件中注册子组件
            components: {
                ElementChild
            }
        }
        


        // vue实例对象
        new Vue({
            //挂载容器
            el: "#app",
            // 在vue实例中注册父组件
            components: {
                ElementParent
            }
        })
    </script>
</body>

</html>

1)父传子

因为组件之间不可以直接通信,所以父组件传值给子组件,

 需要在子组件中自定义属性,在props这个选项中自定义

在父组件的template模板中使用子组件时动态绑定属性

例如: <element-child v-bind:xxx="message"></element-child>

<!DOCTYPE html>
<html lang="zh-cn">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Vue</title>
    <style></style>
</head>

<body>
    <div id="app">
        <element-parent></element-parent>
        <!-- <element-child></element-child> 错误的 -->
    </div>
    <script src="./libs/vue@2.7.16/vue.js"></script>
    <script>


        //禁止控制台输出日志信息
        Vue.config.productionTip = false;

        // 定义子组件
        const ElementChild = {
            // 父组件传值给子组件,需要在子组件中自定义属性
            // 通过在props选项中自定义属性接收父组件传递的数据
            // props: ['xxx'],
            props: {
                xxx: {
                    default: "默认值",
                    type: [String,Number]
                },
                xxx2:{
                    default:'',
                    type: [String,Number]
                }
            },
            template: `
                <div>
                    <h3>子组件</h3>
                    <p>{{xxx}}</p>
                    <p>{{xxx2}}</p>
                </div>
            `
        }
        // 定义父组件
        const ElementParent = {
            // 设置数据
            data(){
                return {
                    message: "这是父组件的数据",
                    message2: "这是父组件的第二条数据"
                }
            },
            template: `
                <div>
                    <h2>父组件</h2>
                    <element-child v-bind:xxx="message"></element-child>
                    <element-child :xxx="100"></element-child>
                    <element-child :xxx="message" :xxx2="message2"></element-child>
                    <element-child></element-child>
                </div>
            `,
            // 在父组件中注册子组件
            components: {
                ElementChild
            }
        }


        // vue实例对象
        new Vue({
            //挂载容器
            el: "#app",
            // 在vue实例中注册父组件
            components: {
                ElementParent
            }
        })

    </script>
</body>

</html>

2)子传父

传值过程中,需要在子组件中自定义事件(行为),在methods中写方法, this.$emit("child-num", {cnum: this.num})

(调用this.$emit('第一个参数是在父组件中@on监听的事件名','第二个参数(在父组件中接受子组件参数的参数名):第三个参数(需要向父组件传递的数据)

  在父组件的模板中,定义一个方法用于接受子组件的数据并在子组件中绑定监听事件,例如: <element-child @child-num="jieshou"></element-child>就是也需要在父组件中写方法,接收子组件的数据。

<!DOCTYPE html>
<html lang="zh-cn">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Vue</title>
    <style></style>
</head>

<body>
    <div id="app">
        <element-parent></element-parent>
    </div>
    <script src="./libs/vue@2.7.16/vue.js"></script>
    <script>

        // 子组件传值给父组件属于负向传值,需要使用事件行为方可传递数据给父组件

        //禁止控制台输出日志信息
        Vue.config.productionTip = false;

        // 定义子组件
        const ElementChild = {
            data(){
                return {
                    num: 100
                }
            },
            template: `
                <div>
                    <h3>子组件</h3>
                    <button @click="add">发送数据</button>
                </div>
            `,
            methods: {
                add(){
                    // 自定义行为
                    // 参数1:在父组件中@on监听的事件名, 第二个参数(在父组件中接受子组件参数的参数名):第三个参数(需要向父组件传递的数据)
                    this.num --;
                    this.$emit("child-num", {cnum: this.num})
                }
            }
        }
        // 定义父组件
        const ElementParent = {
            data(){
                return {
                    num: 0
                }
            },
            template: `
                <div>
                    <h2>父组件</h2>
                    <p v-if="num!=0">{{num}}</p>
                    <element-child @child-num="jieshou"></element-child>
                </div>
            `,
            // 在父组件中注册子组件
            components: {
                ElementChild
            },
            // 编写方法
            methods: {
                // 自定义方法接受子组件的数据
                jieshou(data){
                    // console.log(data)
                    // 获取子组件传递的数据
                    this.num = data.cnum;
                }
            }
        }


        // vue实例对象
        new Vue({
            //挂载容器
            el: "#app",
            // 在vue实例中注册父组件
            components: {
                ElementParent
            }
        })


    </script>
</body>

</html>

3)兄弟传值

兄弟传值需要定义一个新的vue实例或通过同一个父组件来共享事件。通过$emit和$on来传数据。

<!DOCTYPE html>
<html lang="zh-cn">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Vue</title>
    <style>
        #app > div {
            padding: 20px;
            border: 1px solid #000;
            margin-top: 10px;
        }
    </style>
</head>
<body>
    <div id="app">
       <comp-a></comp-a>
       <comp-b></comp-b>

       
    </div>
    <script src="../libs/vue@2.7.16/vue.js"></script>
    <script>

        // 创建vue实例作为通信的桥梁(这种有响应式)
        const bridge = new Vue();

        // 并列关系组件
        const CompA = {
            template: `
            <div>
                <h3>组件A</h3>
                <button @click="senda">数字自增</button>
            </div>
            `,
            data(){
                return {
                    num: 100
                }
            },
            methods: {
                 senda(){
                    this.num ++;
                    let value = this.num;
                    bridge.$emit('xxx', value)
                 },
            },
            created(){
                // 发送数据
                setTimeout(()=>{
                    this.senda();
                },0)
            }
        }
        const CompB = {
            template: `
                <div>
                    <h3>组件B</h3>
                    <p>{{num}}</p>
                </div>

            `,
            data(){
                return {
                    num: 0
                }
            },
            created(){
                // 监听组件A的事件且接收组件A的数据
                bridge.$on("xxx",(value)=>{
                    this.num = value;
                })
            }
        }

        //禁止控制台输出日志信息
        Vue.config.productionTip = false;
        new Vue({
            //挂载容器
            el: "#app",
            components: { CompA , CompB },


        })
    </script>
</body>
</html>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值