1. 首页
  2. IT资讯

vue实现模态框的通用写法

Vue 推荐在绝大多数情况下使用 template 来创建你的 HTML。然而在一些场景中,你真的需要 JavaScript 的完全编程的能力,这就是 render 函数,它比 template 更接近编译器。 在 HTML 层, 我们决定这样定义组件接口:通过传入不同的level 1-6 生成h1-h6标签,和使用slot生成内容

<div id="div1">     <child :level="1">Hello world!</child> </div> <script type="text/x-template" id="child-template">   <h1 v-if="level === 1">     <slot></slot>   </h1>   <h2 v-if="level === 2">     <slot></slot>   </h2>   <h3 v-if="level === 3">     <slot></slot>   </h3>   <h4 v-if="level === 4">     <slot></slot>   </h4>   <h5 v-if="level === 5">     <slot></slot>   </h5>   <h6 v-if="level === 6">     <slot></slot>   </h6>  </script>  <script type="text/javascript">     /**      * 全局注册child组件,注意template如果值以 # 开始,则它用作选项符,将使用匹配元素的 innerHTML 作为模板。常用的技巧是用 <script type="x-template"> 包含模板,这样的好处是html不会渲染里面的内容      *  这里使用template不是最好的选择,      * 一、代码冗长       * 二、在不同的标题插入内容需要重复使用slot       * 三、由于组件必须有根元素,所以标题和内容被包裹在一个无用的div中,比如<div><h1>hello world</h1></div>      */      Vue.component('child', {       template: '#child-template',       props: {         level: {           type: Number,           required: true         }       },       data: function() {         return {           a: 1         }       }     })      new Vue({         el:"#div1"     })   </script>

我们尝试使用render函数实现上面的例子,注意使用render函数,template 选项将被忽略。 createElement接收3个参数:

第一个参数可以是HTML标签名,组件或者函数都可以;此参数是必须的;

第二个为数据对象{Object}(可选);

第三个为子节点{String | Array}(可选),多个子节点[createElement(tag1),createElement(tag2)]。

<div id="div1">    <child :level="1">      Hello world!    </child>    <child :level="2">      <!-- 将不会被显示 -->      <span slot="footer">span</span>      <p slot="header">header slot<span>span</span></p>    </child>  </div>  Vue.component('child', {       render: function(createElement) {         console.log(this.$slots);         return createElement(           'h'+ this.level, // tagName标签名称           {             // 为每个h标签设置class             'class': {               foo: true,               bar: false             },             // 最终被渲染为内联样式             style: {               color: 'red',               fontSize: '14px'             },             // 其他的html属性             attrs: {               id: 'foo',               'data-id': 'bar'             },             // DOM属性             domProps: {               // innerHTML: 'from domProps',             },             // 事件监听器基于 "on"             // 所以不再支持如 v-on:keyup.enter 修饰器             on: {               click: this.clickHandler             },             // ...           },           // 你可以从this.$slots获取VNodes列表中的静态内容           // $slots.default用来访问组件的不具名slot           // 当你可能需要具名slot的时候需要指定slot的name, this.$slots.header           [this.$slots.default]         )       },       template: '<div v-if="level===1"><slot></slot></div>', // 将被忽略       props: {         level: {           type: Number,           required: true         }       },       methods: {         clickHandler: function() {           console.log('clickHandler')         }       }     })      new Vue({         el:"#div1"     })

我们现在可以完成这样的组件<h1>

     <a name="hello-world" href="#hello-world">         Hello world!      </a> </h1>  // 递归函数获得helloworld文本     function getChildrenTextContent(child) {         return child.map(function(node) {             return node.children? getChildrenTextContent(node.children) : node.text         }).join('')     }     Vue.component('child',{         render: function(createElement) {             var hello_world = getChildrenTextContent(this.$slots.default)                               .toLowerCase()                               .replace(/W+/g,'-')                               .replace(/^-|-$/g,'');             return createElement(                 'h'+ this.level,                 {},                 [ // 创建一个a标签,设置属性,并设置a标签的子节点                     createElement('a',{                         attrs: {                             name: hello_world,                             href: '#' + hello_world                         }                     },this.$slots.default)                 ]             )         },         props: {             level: {                 type: Number,                 required: true             }         }     })     new Vue({         el:"#div1"     })

注意VNode的唯一性,这里两个VNode指向同一引用是错误的,如果要重复创建多个相同元素/组件,可以使用工厂函数实现

<div id="div1">     <child :level="1">       Hello world!     </child> </div>  Vue.component('child',{     // render: function(createElement) {     //  var myParagraphVNode  = createElement('p','hello')     //  return createElement('div',     //      [myParagraphVNode, myParagraphVNode]     //  )     // },     render: function(createElement) {         return createElement('div',             Array.apply(null, {length:20}).map(function() {                 return createElement('p','hello')             })         )     },     props: {         level: {             type: Number,             required: true         }     } }) new Vue({     el:"#div1" })

使用javascript代替模板功能,某些api要自己实现

①使用if/else代替v-if

②使用map代替v-for

Vue.component('child',{     render: function(createElement) {         if (this.lists.length) {             return createElement('ul',this.lists.map(function() {                 return createElement('li','hi')             }))         } else {             return createElement('p','no lists')         }     },     props: {         level: {             type: Number,             required: true         }     },     data: function() {         return {             lists: [1,2,3]         }     } })  // render函数中没有与v-model相应的api - 你必须自己来实现相应的逻辑: Vue.component('child-msg',{     render: function(createElement) {         var self = this;         return createElement('div', [                 createElement('input',{                     'on': {                         input: function(event) {                             self.value = event.target.value;                         }                     }                 }),createElement('p',self.value)             ])     },     props: {         level: {             type: Number,             required: true         }     },     data: function() {         return {             value: ''         }     } }) new Vue({     el:"#div1" })

相信很多人在刚接触前端或者中期时候总会遇到一些问题及瓶颈期,如学了一段时间没有方向感或者坚持不下去一个人学习枯燥乏味有问题也不知道怎么解决,对此我整理了一些资料 喜欢我的文章想与更多资深大牛一起讨论和学习的话 欢迎加入我的学习交流群907694362

原文始发于:vue实现模态框的通用写法

主题测试文章,只做测试使用。发布者:逗乐男神i,转转请注明出处:http://www.cxybcw.com/22183.html

联系我们

13687733322

在线咨询:点击这里给我发消息

邮件:1877088071@qq.com

工作时间:周一至周五,9:30-18:30,节假日休息

QR code