三、teleport标签(传送门功能,<teleport to="#id">)
teleport标签:能够将原本组件中的元素传输到其他dom元素中,并依旧可以使用组件中的data对象数据。
写法:<teleport to="#id"></teleport>,其中to=xxx,可以填id名、class名以及标签,如#id1、.mbody、body都是可以的!!!
示例:点击按钮,将组件中的蒙层div元素挂载到页面的body标签中,实现全页面覆盖!
<style> .box { width: 300px; height: 500px; background-color: black; position: absolute; top: 50%; left: 50%; margin-top: -250px; margin-left: -150px; } .layerbox { position: absolute; left: 0; right: 0; top: 0; bottom: 0; background-color: blue; opacity: .5; } .layerbox div { width: 50px; height: 50px; background-color: yellow; vertical-align: middle; color: white; font-size: 50rpx; } </style> <body> <div id="app"></div> <script src="https://unpkg.com/vue@3.1.5/dist/vue.global.js"></script> <script> const app = Vue.createApp({ data() { return { showLayer: false, message: "changlu" } }, methods: { handleClick() { this.showLayer = this.showLayer ? false : true; } }, //2、使用自定义指令v-focus template: ` <div class="box" @click="handleClick"> <button >点我上蒙层</button> <teleport to="body"> <div class="layerbox" v-show="showLayer" @click="handleClick">{{message}}</div> </teleport> </div> ` }); const vm = app.mount("#app"); </script> </body>
看一下浏览器中的dom结构:可以很明显的看到被移动到指定的dom元素下。
四、render()函数(template属性底层转换)
4.1、认识render()函数(初使用)
介绍描述
render()函数作用:与template属性的效果一致,都是用来生成dom元素的。
知识点补充(template变为虚拟dom流程):template -> render -> h -> 虚拟dom元素(如{tagname:div,text: “hello”},就是一个js对象用来描述dom元素)。最终通过虚拟dom元素转位实际dom元素进行挂载操作,中间是有这一流程的。template在底层编译之后会生成rander函数!
目的:了解如何通过render()生成dom元素以及实际应用。
注意:一旦使用了render()函数,该组件中的template属性就不生效了!!!
好处:①让vue性能更快。②vue具备跨平台能力
示例
不仅仅可以使用在全局组件上,还可以使用至局部组件中:
<body> <div id="app"></div> <script src="https://unpkg.com/vue@3.1.5/dist/vue.global.js"></script> <script> const app = Vue.createApp({ // 1、设置render()函数:template=>render,只不过我们这里使用reder()函数来代替template render() { console.log("Vue=>", Vue); const { h } = Vue;//通过解构赋值拿到h函数 // 2、第一个参数为标签名,第二个参数为标签的属性,第三个参数为标签的内容值 return h('h' + 1, { 'data-user': 'changlu' }, "hello,changlu!"); }, }); const vm = app.mount("#app"); </script> </body>
4.2、使用render()函数解决冗余问题
需求:当我们在使用子组件时,若是出现子组件中使用同一类型的标签如h1、h2、h3,并且根据传递来的参数选择指定的标签展示,此时的话,我们使用普通的判断写法就会出现下面冗余问题!!!
<body> <div id="app"></div> <script src="https://unpkg.com/vue@3.1.5/dist/vue.global.js"></script> <script> const app = Vue.createApp({ //2、使用自定义指令v-focus template: ` <cl-item :level="2"> hello,changlu </cl-item> ` }); app.component('cl-item', { props: ['level'], template: ` <h1 v-if="level === 1"> <slot/> </h1> <h2 v-if="level === 2"> <slot/> </h2> <h3 v-if="level === 3"> <slot/> </h3> <h4 v-if="level === 4"> <slot/> </h4> ` }) const vm = app.mount("#app"); </script> </body>
优化:此时我们可以借助render()函数来动态创建虚拟dom元素,最终挂载至指定dom元素上。
<body> <div id="app"></div> <script src="https://unpkg.com/vue@3.1.5/dist/vue.global.js"></script> <script> const app = Vue.createApp({ data() { return { // 动态拿取level值 level: 2 } }, template: ` <cl-item :level="level"> hello,changlu </cl-item> ` }); app.component('cl-item', { props: ['level'], // 1、编写render()函数 render() { const { h } = Vue; // this.$slots.default():拿到默认的插槽值,也就是hello,changlu // 2、返回Vue实例中的h元素,包含了虚拟dom的相关属性如标签名、属性键值对以及内部值 return h('h' + this.level, {}, this.$slots.default()); }, }) const vm = app.mount("#app"); </script> </body>
4.3、render函数返回值h函数嵌套使用
对于h函数之前讲不是有三个参数嘛,其中第三个参数我们还可以在嵌套返回另一个标签值,从而达到了添加多个标签的方式!!!
返回数组(包含多个h函数):实现插入多个标签。
h函数第三个参数设置h函数:实现标签内部嵌套。
示例:
<body> <div id="app"></div> <script src="https://unpkg.com/vue@3.1.5/dist/vue.global.js"></script> <script> const app = Vue.createApp({ data() { return { // 动态拿取level值 level: 2 } }, template: ` <cl-item :level="level"> hello,changlu </cl-item> ` }); app.component('cl-item', { props: ['level'], render() { const { h } = Vue; // 返回数组就能够实现插入多个元素。并且你可以在h函数的第三个参数中使用h函数来表示指定的标签 return [h('h' + this.level, {}, this.$slots.default()), h('h' + this.level, {}, h('button', {}, '按钮'))]; }, }) const vm = app.mount("#app"); </script> </body>