学Vue,就要学会vue JSX(三)

是时候使用JSX代替createElement

接着上面的讲,当咱们看到上面用createElement去实现组件,太麻烦了,别说工做效率提升了,就是那些嵌套能够嵌套正确就很赞了,因此咱们须要用JSX去简化整个逻辑。当年我作项目的时候就遇到过这样的状况,嵌套太多,本身都快搞不明白了,在崩溃的边缘。javascript

 methods: {
   $_handleInputUser(value) {
     this.formInline.user = value
   },
   $_handleChangeRegion(value) {
     this.formInline.region = value
   },
   $_handleSubmit() {}
 },
   /**
   *将 h 做为 createElement 的别名是 Vue 生态系统中的一个通用惯例,实际上也是 JSX 所要求的。从 Vue 的 Babel 插件的 3.4.0   *版本开始,咱们会在以 ES2015 语法声明的含有 JSX 的任何方法和 getter 中 (不是函数或箭头函数中) 自动注入 
   *const h = this.$createElement,这样你就能够去掉 (h) 参数了。对于更早版本的插件,若是 h 在当前做用域中不可用,应用会抛错。
  */
 render(h) {
     return (
       <ElForm inline model={this.formInline} class="demo-form-inline">
         <ElFormItem label="审批人">
           <ElInput
             value={this.formInline.user}
             onInput={this.$_handleInputUser}
             placeholder="审批人"
           ></ElInput>
         </ElFormItem>
         <ElFormItem label="活动区域">
           <ElSelect
             value={this.formInline.region}
             onChange={this.$_handleChangeRegion}
             placeholder="活动区域"
           >
             <ElOption label="区域一" value="shanghai"></ElOption>
             <ElOption label="区域二" value="beijing"></ElOption>
           </ElSelect>
         </ElFormItem>
         <ElFormItem>
           <ElButton type="primarty" onClick={this.$_handleSubmit}>
             查询
           </ElButton>
         </ElFormItem>
       </ElForm>
     )
   }

 

看了上面的代码,你们其实会发现用JSXtemplate的语法都属于xml的写法,并且也比较像,但实质上仍是有许多区别的,下面我将为你们一一分析php

没有v-model怎么办,还有其余指令能够用吗?

当你选择使用JSX的时候,你就要作好和指令说拜拜的时候了,在JSX中, 你惟一可使用的指令是v-show,除此以外,其余指令都是不可使用的,有没有感到很慌,这就对了。不过呢,换一个角度思考,指令只是Vue在模板代码里面提供的语法糖,如今你已经能够写Js了,那些语法糖用Js均可以代替了。html

v-model

v-modelVue提供的一个语法糖,它本质上是由 value属性(默认) + input事件(默认)组成的。因此,在JSX中,咱们即可以回归本质,经过传递value属性并监听input事件来实现数据的双向绑定vue

 export default {
   data() {
     return {
       name: ''
     }
   },
   methods: {
     // 监听 onInput 事件进行赋值操做
     $_handleInput(e) {
       this.name = e.target.value
     }
   },
   render() {
     // 传递 value 属性 并监听 onInput事件
     return <input value={this.name} onInput={this.$_handleInput}></input>
   }
 }

 

经我测试,在新版脚手架vue-cli4中,已经默认集成了对v-model的支持,你们能够直接使用`,若是你的项目比较老,也能够安装插件babel-plugin-jsx-v-model`来进行支持java

一样的,在JSX中,对于.sync也须要用属性+事件来实现,以下代码所示:c++

 export default {
   methods: {
     $_handleChangeVisible(value) {
       this.visible = value
     }
   },
   render() {
     return (
       <ElDialog
         title="测试.sync"
         visible={this.visible}
         on={{ 'update:visible': this.$_handleChangeVisible }}
       ></ElDialog>
     )
   }
 }

 

v-if 与 v-for

在模板代码里面咱们经过v-for去遍历元素,经过v-if去判断是否渲染元素,在jsx中,对于v-for,你可使用for循环,array.map来代替,对于v-if,可使用if语句,三元表达式等来代替vue-cli

循环遍历列表element-ui

 const list = ['java', 'c++', 'javascript', 'c#', 'php']
 return (
   <ul>
   {list.map(item => {
    return <li>{item}</li>
   })}
   </ul>
 )

 

使用条件判断c#

 const isGirl = false
 return isGirl ? <span>小妹,哥哥教你写Vue</span> : <span>鸟你干啥</span>

 

v-bind

在模板代码中,咱们通常经过 v-bind:prop="value":prop="value"来给组件绑定属性,在JSX里面写法也相似babel

 render() {
   return <input value={this.name}></input>
 }

 

v-html 与 v-text

在说v-htmlv-text以前,咱们须要先了解一下Vue中的属性,Vue中的属性一共分为三种,第一种是你们写bug时候最经常使用的props,即组件自定义的属性;第二种是attrs,是指在父做用域里面传入的,但并未在子组件内定义的属性。第三种比较特殊,是domProps,经小编不彻底测试,在Vue中,domProps主要包含三个,分别是innerHTML,textContent/innerTextvalue

  • v-html: 在模板代码中,咱们用v-html指令来更新元素的innerHTML内容,而在JSX里面,若是要操纵组件的innerHTML,就须要用到domProps

     export default {
       data() {
         return {
           content: '<div>这是Heo写的一篇新的文章</div>'
         }
       },
       render() {
         // v-html 指令在JSX的写法是 domPropsInnerHTML
         return <div domPropsInnerHTML={this.content}></div>
       }
     }

     

  • v-text: 看了上面的v-html,你是否是当即就想到了v-textJSX的写法domPropsInnerText,是的,你没有想错

     export default {
       data() {
         return {
           content: '这是Heo写的一篇新的文章的内容'
         }
       },
       render() {
         return <div domPropsInnerText={this.content}></div>
       }
     }

     

    但实际上咱们不须要使用domPropsInnerText,而是将文本做为元素的子节点去使用便可

     <div>{this.content}</div>

实际上,对于domProps,只有innerHTML才须要使用domPropsInnerHTML的写法,其余使用正常写法便可

我还要监听事件呢

监听事件与原生事件

当咱们开发一个组件以后,通常会经过this.$emit('change')的方式对外暴露事件,而后经过v-on:change的方式去监听事件,很遗憾,在JSX中你没法使用v-on指令,但你将解锁一个新的姿式

  render() {
     return <CustomSelect onChange={this.$_handleChange}></CustomSelect>
   }

 


 
 JSX`中,经过`on` + 事件名称的大驼峰写法来监听,好比事件`icon-click`,在`JSX`中写为`onIconClick

有时候咱们但愿能够监听一个组件根元素上面的原生事件,这时候会用到.native修饰符,有点绝望啊,修饰符也是不能用了,但好在也有替代方案,以下代码

  render() {
     // 监听下拉框根元素的click事件
     return <CustomSelect nativeOnClick={this.$_handleClick}></CustomSelect>
   }

 

监听原生事件的规则与普通事件是同样的,只须要将前面的on替换为nativeOn

除了上面的监听事件的方式以外,咱们还可使用对象的方式去监听事件

   render() {
     return (
       <ElInput
         value={this.content}
         on={{
           focus: this.$_handleFocus,
           input: this.$_handleInput
         }}
         nativeOn={{
           click: this.$_handleClick
         }}
       ></ElInput>
     )
   }

 

事件修饰符

和指令同样,除了个别的以外,大部分的事件修饰符都没法在JSX中使用,这时候你确定已经习惯了,确定有替代方案的。

  • .stop : 阻止事件冒泡,在JSX中使用event.stopPropagation()来代替

  • .prevent:阻止默认行为,在JSX中使用event.preventDefault() 来代替

  • .self:只当事件是从侦听器绑定的元素自己触发时才触发回调,使用下面的条件判断进行代替

     if (event.target !== event.currentTarget){
       return
     }
  • .enterkeyCode: 在特定键触发时才触发回调

     if(event.keyCode === 13) {
       // 执行逻辑
     }

除了上面这些修饰符以外,尤大大为了照顾咱们这群CV仔,仍是作了一点优化的,对于.once,.capture,.passive,.capture.once,尤大大提供了前缀语法帮助咱们简化代码

  render() {
     return (
       <div
         on={{
           // 至关于 :click.capture
           '!click': this.$_handleClick,
           // 至关于 :input.once
           '~input': this.$_handleInput,
           // 至关于 :mousedown.passive
           '&mousedown': this.$_handleMouseDown,
           // 至关于 :mouseup.capture.once
           '~!mouseup': this.$_handleMouseUp
         }}
       ></div>
     )
   }

 

对了,还有插槽

插槽就是子组件中提供给父组件使用的一个占位符,插槽分为默认插槽,具名插槽和做用域插槽,下面我依次为您带来每种在JSX中的用法与如何去定义插槽。

默认插槽

  • 使用默认插槽

使用element-uiDialog时,弹框内容就使用了默认插槽,在JSX中使用默认插槽的用法与普通插槽的用法基本是一致的,以下代码所示:

  render() {
     return (
       <ElDialog title="弹框标题" visible={this.visible}>
         {/*这里就是默认插槽*/}
         <div>这里是弹框内容</div>
       </ElDialog>
     )
   }

 

  • 自定义默认插槽

    Vue的实例this上面有一个属性$slots,这个上面就挂载了一个这个组件内部的全部插槽,使用this.$slots.default就能够将默认插槽加入到组件内部

     export default {
       props: {
         visible: {
           type: Boolean,
           default: false
         }
       },
       render() {
         return (
           <div class="custom-dialog" vShow={this.visible}>
             {/**经过this.$slots.default定义默认插槽*/}
             {this.$slots.default}
           </div>
         )
       }
     }

     

具名插槽

  • 使用具名插槽

    有时候咱们一个组件须要多个插槽,这时候就须要为每个插槽起一个名字,好比element-ui的弹框能够定义底部按钮区的内容,就是用了名字为footer的插槽

  render() {
     return (
       <ElDialog title="弹框标题" visible={this.visible}>
         <div>这里是弹框内容</div>
         {/** 具名插槽 */}
         <template slot="footer">
           <ElButton>肯定</ElButton>
           <ElButton>取消</ElButton>
         </template>
       </ElDialog>
     )
   }

 

  • 自定义具名插槽

在上节自定义默认插槽时提到了$slots,对于默认插槽使用this.$slots.default,而对于具名插槽,可使用this.$slots.footer进行自定义

 render() {
     return (
       <div class="custom-dialog" vShow={this.visible}>
         {this.$slots.default}
         {/**自定义具名插槽*/}
         <div class="custom-dialog__foolter">{this.$slots.footer}</div>
       </div>
     )
   }

 

做用域插槽

  • 使用做用域插槽

    有时让插槽内容可以访问子组件中才有的数据是颇有用的,这时候就须要用到做用域插槽,在JSX中,由于没有v-slot指令,因此做用域插槽的使用方式就与模板代码里面的方式有所不一样了。好比在element-ui中,咱们使用el-table的时候能够自定义表格单元格的内容,这时候就须要用到做用域插槽

     data() {
         return {
           data: [
             {
               name: 'Heo'
             }
           ]
         }
       },
       render() {
         return (
           {/**scopedSlots即做用域插槽,default为默认插槽,若是是具名插槽,将default该为对应插槽名称便可*/}
           <ElTable data={this.data}>
             <ElTableColumn
               label="姓名"
               scopedSlots={{
                 default: ({ row }) => {
                   return <div style="color:red;">{row.name}</div>
                 }
               }}
             ></ElTableColumn>
           </ElTable>
         )
       }

     

  • 自定义做用域插槽

    使用做用域插槽不一样,定义做用域插槽也与模板代码里面有所不一样。加入咱们自定义了一个列表项组件,用户但愿能够自定义列表项标题,这时候就须要将列表的数据经过做用域插槽传出来。

     render() {
         const { data } = this
         // 获取标题做用域插槽
         const titleSlot = this.$scopedSlots.title
         return (
           <div class="item">
             {/** 若是有标题插槽,则使用标题插槽,不然使用默认标题 */}
             {titleSlot ? titleSlot(data) : <span>{data.title}</span>}
           </div>
         )
       }

     

ok。vue JSX 的重点就已经讲完了。下面一篇文章来说一下注意的地方和总结。你们以为对你有帮助的话能够给我点个赞哦,推荐给更多的人看。

相关文章
相关标签/搜索