前端学习六(vue的生命周期、组件化开发)

一、vue的生命周期以及钩子函数

生命周期:https://cn.vuejs.org/v2/guide/instance.html#%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%E5%9B%BE%E7%A4%BA

钩子函数:个人理解是生命周期中预留的(名称是确定的,当系统消息触发,自动会调用)、可以编辑的函数

vue生命周期中8个钩子函数定义

1、beforeCreate(创建前)
在数据观测和初始化事件还未开始。
2、created(创建后)
完成数据观测,属性和方法的运算,初始化事件,$el属性还没有显示出来。
3、beforeMounted(挂载前)
在挂载开始之前被调用,相关的render函数首次被调用。实例已完成以下的配置:
编译模板,把data里面的数据和模板生成html。此时还没有挂载html到页面上。
4、mounted(挂载后)
在el被新创建的vm.$el 替换,并挂载到实例上去之后调用。实例已完成以下的配置:
用上面编译好的html内容替换el属性指向的DOM对象。完成模板中的html渲染到html页面中。此过程中进行ajax交互
5、beforeUpdate(更新前)
在数据更新之前调用,发生在虚拟DOM重新渲染和打补丁之前。可以在该钩子中进一步地更改状态,不会触发附加的重渲染过程。
6、updated(更新后)
在由于数据更改导致的虚拟DOM重新渲染和打补丁之后调用。调用时,组件DOM已经更新,所以可以执行依赖于DOM的操
作。然而在大多数情况下,应该避免在此期间更改状态,因为这可能会导致更新无限循环。该钩子在服务器端渲染期间不被调用。
7、beforeDestroy(销毁前)
在实例销毁之前调用。实例仍然完全可用。
8、destroyed(销毁后)
在实例销毁之后调用。调用后,所有的时间监听器都会被溢出,所有的子实例也会被销毁。该钩子在服务器端渲染期间不被调用。

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
</head>

<body>
    <div id="app">
        <input type="text" v-model="message">
    </div>

    <script>
        var vm = new Vue({
            el: "#app",
            data: {
                message: 999
            },
            beforeCreate: function () {
                console.log("===vue创建前");
                console.log("el==>", this.$el);// undefined
                console.log("data==>", this.$data);// undefined
                console.log("message==>", this.message);// undefined
            },
            created: function () {
                console.log("===vue创建完毕");
                console.log("el==>", this.$el);// undefined
                console.log("data==>", this.$data);
                console.log("message==>", this.message);
            },
            beforeMount: function () {
                console.log("===data数据挂载前");
                console.log("el==>", this.$el);
                console.log(this.$el.innerHTML);// 未渲染
                console.log("data==>", this.$data);
                console.log("message==>", this.message);
            },
            mounted: function () {
                console.log("===数据挂载结束");
                console.log("el==>", this.$el);
                console.log(this.$el.innerHTML);// 已渲染
                console.log("data==>", this.$data);
                console.log("message==>", this.message);
            },
            beforeUpdate: function () {
                console.log("===数据更新前");
                console.log("el==>", this.$el);
                console.log(this.$el.innerHTML);
                console.log("data==>", this.$data);
                console.log("message==>", this.message);
            },
            updated: function () {
                console.log("===数据更新后");
                console.log("el==>", this.$el);
                console.log(this.$el.innerHTML);
                console.log("data==>", this.$data);
                console.log("message==>", this.message);
            },
            beforeDestroy: function () {
                console.log("===数据销毁前");
                console.log("el==>", this.$el);
                console.log(this.$el.innerHTML);
                console.log("data==>", this.$data);
                console.log("message==>", this.message);
            },
            destroyed: function () {
                console.log("===vue销毁完成");
                console.log("el==>", this.$el);
                console.log(this.$el.innerHTML);
                console.log("data==>", this.$data);
                console.log("message==>", this.message);
            }
        })
    </script>
</body>

</html>
View Code

 二、全局组件和局部组件的定义

1、全局组件
全局组件可以直接在其他组件直接使用
2、局部组件
在其他的组件(vue实例)中定义的子组件叫局部组件
3、组件的命名,按-连接的风格
驼峰命名也会自动转换成此风格(可以在template中使用)

<body>
    <div id="app">
        <h3>{{title}}</h3>
        <comp2></comp2>
        <br>
        <el-demo1></el-demo1>
    </div>

    <script>
        /*
        一、全局组件
            全局组件可以直接在其他组件直接使用
        二、局部组件
            在其他的组件(vue实例)中定义的子组件叫局部组件
        三、组件的命名,按-连接的风格
            驼峰命名也会自动转换成此风格(可以在template中使用)
        */

        // 全局组件,第一个入参是组件名
        // 不能使用下面的局部组件
        Vue.component('comp1', {
            template:'<div>全局组件中的内容</div>'
        })
        Vue.component('comp2', {
            // `符号支持换行写法,模板字符串
            template:`<div>
                <comp1></comp1>
                <comp1></comp1>
                <el-demo2></el-demo2>
                </div>`,
            components:{
                // 只能被当前定义的全局组件中使用,不能被外部调用
                'el-demo2':{
                    template:'<div>全局组件中的局部组件</div>'
                }
            }
        })

        var vm = new Vue({
            el: "#app",
            data: {
                title: "组件化开发"
            },
            // 定义局部组件,只能在#app节点下使用
            components:{
                'el-demo1':{
                    template:'<div>局部组件中的内容</div>'
                }
            }
        })
    </script>
</body>
View Code

 element ui 地址:https://element.eleme.io/#/zh-CN/component/layout

<body>
        <div id="app">
            <el-demo1></el-demo1>
        </div>

        <script>
            Vue.component("el-demo1", {
                // 组件模板最外层必须由一个根节点
                template: `
                <div>
                <h3>名字:{{name}},年龄:{{age}}</h3>
                <button @click="handle(age)">按钮</button>
                </div>`,
                // 组件中的data要定义为函数。功能和下面vm实例中的data一样,只是这里的数据只能被上面的模板使用
                data: function() {
                    return {
                        name: "测试",
                        age: 1888
                    }
                },
                // 组件中的方法
                methods: {
                    handle: function(val) {
                        console.log('参数为:', val);
                    }
                },
                // 组件中的计算属性
                computed: {},
                // 组件中的侦听器
                watch: {},
                // 组件中的过滤器
                filters: {},
                // 组件中的子组件
                components: {}
            })

            var vm = new Vue({
                el: "#app",
                data: {
                    name: "测试",
                    age: 18
                }
            })
        </script>
    </body>
View Code

二、组件数据传递 

父组件、子组件之间的参数传递
1、父组件往子组件中传递数据:
  a、子组件中的props属性可以来定义接收数据的属性名
2、子组件往父组件中传递数据:
  a、子组件中定义一个事件,通过$emit 触发自定义事件,并分别传入对应的参数
  b、监听子组件中自定义的事件,当触发事件时,子组件中传递过来的数据,父组件可以通过$event来接收

    <body>
        <div id="app">
            <!-- run是子组件中$emit自定义的名称
            $event 是固定不能改的 -->
            <el-table :lists=case1 @run="handle($event)"></el-table>
            <br>
            <el-table :lists=case2 @run="handle($event)"></el-table>

            <h5>运行的数据:{{case_}}</h5>

        </div>
        <script type="text/javascript">
            //一、 父组件往子组件中传递数据:
            //     1、子组件中的props属性可以来定义接收数据的属性名
            //二、 子组件往父组件中传递数据:
            //     1、子组件中定义一个事件,通过$emit 触发自定义事件,并分别传入对应的参数
            //     2、监听子组件中自定义的事件,当触发事件时,子组件中传递过来的数据,父组件可以通过$event来接收
            var vm = new Vue({
                el: "#app",
                data: {
                    case_: "",
                    case1: [{
                            "id": 1,
                            "name": "登录接口1",
                            "tester": "测试人1",
                            "project": "自动化测试平台1"
                        },
                        {
                            "id": 2,
                            "name": "登录接口2",
                            "tester": "测试人2",
                            "project": "自动化测试平台2"
                        }
                    ],
                    case2: [{
                            "id": 3,
                            "name": "登录接口3",
                            "tester": "测试人3",
                            "project": "自动化测试平台3"
                        },
                        {
                            "id": 4,
                            "name": "登录接口4",
                            "tester": "测试人4",
                            "project": "自动化测试平台4"
                        }
                    ]
                },
                methods:{
                    handle: function(val) {
                        console.log(val);
                        this.case_=val
                    }
                },
                components: {
                    "el-table": {
                        // 使用data或者props的数据
                        // $emit('run',item) 子组件中主动触发一个自定义的事件,run-事件,item-传的数据
                        template: `<table border="">
                                    <tr>
                                        <th>id</th>
                                        <th>name</th>
                                        <th>tester</th>
                                        <th>project</th>
                                        <th>操作</th>
                                    </tr>
                                    <tr v-for="item in lists">
                                        <td>{{item.id}}</td>
                                        <td>{{item.name}}</td>
                                        <td>{{item.tester}}</td>
                                        <td>{{item.project}}</td>
                                        <td><button @click="$emit('run',item)">运行</button></td>
                                    </tr>
                                </table>
                                `,
                        // 貌似优先使用props的数据
                        // data: function() {
                        //     return {
                        //         lists: [{
                        //                 "id": 1,
                        //                 "name": "登录接口1",
                        //                 "tester": "测试人1",
                        //                 "project": "自动化测试平台1"
                        //             },
                        //             {
                        //                 "id": 2,
                        //                 "name": "登录接口2",
                        //                 "tester": "测试人2",
                        //                 "project": "自动化测试平台2"
                        //             }
                        //         ]
                        //     }
                        // },
                        // 接收传递值,然后template使用传递值。因为template使用的是lists,所以下面定义的lists
                        props: ["lists"]
                    }
                }

            })
        </script>
    </body>
View Code

 三、插槽

个人理解是template组件在使用时,组件标签中间的内容会填充到组件定义好的slot标签位置

1、默认插槽:<slot></slot>

<body>
    <div id="app">
        <el-header>
            <!-- 往插槽中填充的内容 -->
            <h2>这个是标题</h2>
        </el-header>

    </div>

    <script>
        var vm = new Vue({
            el: "#app",
            data: {},
            // 定义局部组件,只能在#app节点下使用
            // 默认插槽:<slot></slot>
            components: {
                'el-header': {
                    template: `
                    <div>
                        <slot></slot>
                        <p>这个是段落</p>
                    </div>`
                }
            }
        })
    </script>
</body>
View Code

2、具名插槽:<slot name='s1'></slot>

<body>
    <div id="app">
        <el-header>
            <!-- 通过slot名称指定填充 -->
            <h2 slot="s3">这个是标题1</h2>
            <h2 slot="s2">这个是标题2</h2>
            <h2 slot="s1">这个是标题3</h2>
        </el-header>

    </div>

    <script>
        var vm = new Vue({
            el: "#app",
            data: {},
            // 定义局部组件,只能在#app节点下使用
            // 默认插槽:<slot></slot>
            components: {
                'el-header': {
                    template: `
                    <div>
                        <hr></hr>
                        <slot name='s1'></slot>
                        <slot name='s2'></slot>
                        <slot name='s3'></slot>
                        <hr></hr>
                    </div>`
                }
            }
        })
    </script>
</body>
View Code

 3、使用element-ui和插槽来练习

<!-- 引入的vue必须放最前面 -->
<!-- 引入样式 -->
<!-- 引入组件库 -->
<!-- style也必须在前面的引用之后才会生效 -->

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title></title>
    <!-- 引入的vue必须放最前面 -->
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
    <!-- 引入样式 -->
    <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
    <!-- 引入组件库 -->
    <script src="https://unpkg.com/element-ui/lib/index.js"></script>
    <!-- style也必须在前面的引用之后才会生效 -->
    <style>
        .el-header {
            padding: 0
        }
    </style>
</head>

<body>
    <!-- 我不知道什么原因,引用的组件库必须在挂载了vue的标签下才会有效果 -->
    <div id="app">
        <el-container>
            <el-header>
                <el-menu :default-active="activeIndex2" class="el-menu-demo" mode="horizontal" @select="handleSelect"
                    background-color="#545c64" text-color="#fff" active-text-color="#ffd04b">
                    <el-menu-item index="1">处理中心</el-menu-item>
                    <el-submenu index="2">
                        <template slot="title">我的工作台</template>
                        <el-menu-item index="2-1">选项1</el-menu-item>
                        <el-menu-item index="2-2">选项2</el-menu-item>
                        <el-menu-item index="2-3">选项3</el-menu-item>
                        <el-submenu index="2-4">
                            <template slot="title">选项4</template>
                            <el-menu-item index="2-4-1">选项1</el-menu-item>
                            <el-menu-item index="2-4-2">选项2</el-menu-item>
                            <el-menu-item index="2-4-3">选项3</el-menu-item>
                        </el-submenu>
                    </el-submenu>
                    <el-menu-item index="3" disabled>消息中心</el-menu-item>
                    <el-menu-item index="4"><a href="https://www.ele.me" target="_blank">订单管理</a></el-menu-item>
                </el-menu>
            </el-header>
            <el-container>
                <el-aside width="200px">
                    <el-menu default-active="2" class="el-menu-vertical-demo" @open="handleOpen" @close="handleClose"
                        background-color="#545c64" text-color="#fff" active-text-color="#ffd04b">
                        <el-submenu index="1">
                            <template slot="title">
                                <i class="el-icon-location"></i>
                                <span>导航一</span>
                            </template>
                            <el-menu-item-group>
                                <template slot="title">分组一</template>
                                <el-menu-item index="1-1">选项1</el-menu-item>
                                <el-menu-item index="1-2">选项2</el-menu-item>
                            </el-menu-item-group>
                            <el-menu-item-group title="分组2">
                                <el-menu-item index="1-3">选项3</el-menu-item>
                            </el-menu-item-group>
                            <el-submenu index="1-4">
                                <template slot="title">选项4</template>
                                <el-menu-item index="1-4-1">选项1</el-menu-item>
                            </el-submenu>
                        </el-submenu>
                        <el-menu-item index="2">
                            <i class="el-icon-menu"></i>
                            <span slot="title">导航二</span>
                        </el-menu-item>
                        <el-menu-item index="3" disabled>
                            <i class="el-icon-document"></i>
                            <span slot="title">导航三</span>
                        </el-menu-item>
                        <el-menu-item index="4">
                            <i class="el-icon-setting"></i>
                            <span slot="title">导航四</span>
                        </el-menu-item>
                    </el-menu>
                </el-aside>
                <el-container>
                    <el-main>Main</el-main>
                    <el-footer>Footer</el-footer>
                </el-container>
            </el-container>
        </el-container>

    </div>

    <script>
        var vm = new Vue({
            el: "#app",
            data: {}
        })
    </script>

</body>

</html>
View Code

 

posted @ 2021-11-06 22:26  whitewall  阅读(82)  评论(0)    收藏  举报