前端学习六(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>
二、全局组件和局部组件的定义
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>
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>
二、组件数据传递
父组件、子组件之间的参数传递
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>
三、插槽
个人理解是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>
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>
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>

浙公网安备 33010602011771号