用Jsx写Vue组件

下面我们要讲的是如何在vue里面写jsx,知道react的人应该都知道jsx,jsx的一个特性就是非常灵活,虽然有的人觉得jsx很丑陋,把逻辑都写到模版的感觉,但萝卜青菜各有所爱,适合自己适合团队的就是最好的。

下面我们要讲的是如何在vue里面写jsx,知道react的人应该都知道jsx,jsx的一个特性就是非常灵活,虽然有的人觉得jsx很丑陋,把逻辑都写到模版的感觉,但萝卜青菜各有所爱,适合自己适合团队的就是最好的。

用Jsx写Vue组件

前言

我们平常写vue的组件时,一般都是用的是模版,这种方式看起来比较简洁,而且vue作者也推荐使用这个方式,但是这种方式也有一些它的弊端,例如模版调试麻烦,或者在一些场景下模版描述可能没那么简单和方便。

下面我们要讲的是如何在vue里面写jsx,知道react的人应该都知道jsx,jsx的一个特性就是非常灵活,虽然有的人觉得jsx很丑陋,把逻辑都写到模版的感觉,但萝卜青菜各有所爱,适合自己适合团队的就是***的。

在使用jsx之前我们需要安装一个babel插件(babel-plugin-transform-vue-jsx )

安装方式:

  1. npminstall\
  2. babel-plugin-syntax-jsx\
  3. babel-plugin-transform-vue-jsx\
  4. babel-helper-vue-jsx-merge-props\
  5. babel-preset-es2015\
  6. --save-dev

然后再.babelrc里面添加:

  1. {
  2. "presets":["es2015"],
  3. "plugins":["transform-vue-jsx"]
  4. }

接着我们就可以愉快地在vue里面编写jsx了。

Test.vue

  1. <script>
  2. exportdefault{
  3. props:['onClick','isShow'],
  4. data(){
  5. return{
  6. test:123
  7. };
  8. },
  9. render(){
  10. return(
  11. <divclass="test"onClick={this.onClick}>
  12. {this.test}
  13. {this.isShow+''}
  14. </div>
  15. );
  16. }
  17. }
  18. </script>

可以看到我们把jsx写在了render方法里面,render方法是vue2.0才支持的,用来提供对虚拟DOM的支持,也就是说只有vue2.0才支持jsx语法转换。

这里要注意的一点是vue里面编写jsx和在react里面的jsx语法还是有一点不一样的。

一下是一段覆盖大部分语法的vue jsx代码:

  1. render(h){
  2. return(
  3. <div
  4. //normalattributesorcomponentprops.
  5. id="foo"
  6. //DOMpropertiesareprefixedwith`domProps`
  7. domPropsInnerHTML="bar"
  8. //eventlistenersareprefixedwith`on`or`nativeOn`
  9. onClick={this.clickHandler}
  10. nativeOnClick={this.nativeClickHandler}
  11. //otherspecialtop-levelproperties
  12. class={{foo:true,bar:false}}
  13. style={{color:'red',fontSize:'14px'}}
  14. key="key"
  15. ref="ref"
  16. //assignthe`ref`isusedonelements/componentswithv-for
  17. refInFor
  18. slot="slot">
  19. </div>
  20. )
  21. }

可以看到DOM属性要加domProps前缀,但这里lass和style却不需要,因为这两个是特殊的模块,而且react的class用的是className,vue却用的class。事件监听是以“on”或者“nativeOn”为开始。

实际上vue2.0的模版***都会被编译为render方法,所以模版声明的组件和jsx声明的组件***都是一样的。

上面的jsx***会被编译成下面这样:

  1. render(h){
  2. returnh('div',{
  3. //Componentprops
  4. props:{
  5. msg:'hi'
  6. },
  7. //normalHTMLattributes
  8. attrs:{
  9. id:'foo'
  10. },
  11. //DOMprops
  12. domProps:{
  13. innerHTML:'bar'
  14. },
  15. //Eventhandlersarenestedunder"on",though
  16. //modifierssuchasinv-on:keyup.enterarenot
  17. //supported.You'llhavetomanuallycheckthe
  18. //keyCodeinthehandlerinstead.
  19. on:{
  20. click:this.clickHandler
  21. },
  22. //Forcomponentsonly.Allowsyoutolistento
  23. //nativeevents,ratherthaneventsemittedfrom
  24. //thecomponentusingvm.$emit.
  25. nativeOn:{
  26. click:this.nativeClickHandler
  27. },
  28. //classisaspecialmodule,sameAPIas`v-bind:class`
  29. class:{
  30. foo:true,
  31. bar:false
  32. },
  33. //styleisalsosameas`v-bind:style`
  34. style:{
  35. color:'red',
  36. fontSize:'14px'
  37. },
  38. //otherspecialtop-levelproperties
  39. key:'key',
  40. ref:'ref',
  41. //assignthe`ref`isusedonelements/componentswithv-for
  42. refInFor:true,
  43. slot:'slot'
  44. })
  45. }

这也意味着两种形式的组件是可以相互引用的。

有时候我们难免会在模版里引入jsx编写的vue组件或者在jsx编写的vue组件里引入模版组件,这里还是有些需要注意的事项:

1.在模版里面引入jsx的组件,可以通过components引用,另外props的编写从驼峰式改为连接符:

  1. <template>
  2. <divclass="wrapper">
  3. <Test:on-click="clickHandler":is-show="show"></Test>
  4. </div>
  5. </template>
  6. <script>
  7. importTestfrom'./Test.vue';
  8. exportdefault{
  9. name:'hello',
  10. components:{
  11. Test
  12. },
  13. data(){
  14. return{
  15. msg:'WelcometoYourVue.jsApp',
  16. show:true
  17. };
  18. },
  19. methods:{
  20. clickHandler(){
  21. this.show=!this.show;
  22. }
  23. }
  24. };
  25. </script>

2.在jsx里面引入vue模版组件,这里没有什么要注意的,除了连接符式的属性要转换成驼峰式,还有一个需要注意的是指令,如果用了jsx,那么内置的指令都不会生效(除了v-show),好在内置指令大部分都可以用jsx描述。那么自定义指令要怎么用呢?

自定义指令可以使用“v-name={value}”语法,如果要支持指令参数和modifier可以用“v-name={{ value, modifier: true }}”语法:

  1. <script>
  2. importVuefrom'vue';
  3. Vue.directive('my-bold',{
  4. inserted:function(el){
  5. el.style.fontWeight=900;
  6. }
  7. })
  8. exportdefault{
  9. props:['onClick','isShow'],
  10. data(){
  11. return{
  12. test:123
  13. };
  14. },
  15. methods:{
  16. afterLeave(){
  17. console.log('afterLeave')
  18. }
  19. },
  20. render(){
  21. constdirectives=[
  22. {name:'my-bold',value:666,modifiers:{abc:true}}
  23. ];
  24. return(
  25. <transitiononAfterLeave={this.afterLeave}name="fade">
  26. <divclass="test"onClick={this.onClick}v-show={this.isShow}v-my-bold>
  27. {this.test}
  28. {this.isShow+''}
  29. </div>
  30. </transition>
  31. );
  32. }
  33. }
  34. </script>
  35. <style>
  36. .fade-enter-active,.fade-leave-active{
  37. transition:opacity.5s
  38. }
  39. .fade-enter,.fade-leave-to{
  40. opacity:0
  41. }
  42. </style>

我们还可以用原生vnode的数据格式使用自定义指令:

  1. constdirectives=[
  2. {name:'my-dir',value:123,modifiers:{abc:true}}
  3. ]
  4. return<div{...{directives}}/>

扩展

如果有人觉得在vue组件里面要写data,props,computed和methods不够优雅,可以参考下这个插件vue-class-component,它能让你使用ES6的class和ES7的装饰器编写vue组件。

相关链接

babel-plugin-transform-vue-jsx(https://github.com/vuejs/babel-plugin-transform-vue-jsxhttps://github.com/vuejs/babel-plugin-transform-vue-jsx)

©本文为清一色官方代发,观点仅代表作者本人,与清一色无关。清一色对文中陈述、观点判断保持中立,不对所包含内容的准确性、可靠性或完整性提供任何明示或暗示的保证。本文不作为投资理财建议,请读者仅作参考,并请自行承担全部责任。文中部分文字/图片/视频/音频等来源于网络,如侵犯到著作权人的权利,请与我们联系(微信/QQ:1074760229)。转载请注明出处:清一色财经

(0)
打赏 微信扫码打赏 微信扫码打赏 支付宝扫码打赏 支付宝扫码打赏
清一色的头像清一色管理团队
上一篇 2023年5月5日 00:11
下一篇 2023年5月5日 00:11

相关推荐

发表评论

登录后才能评论

联系我们

在线咨询:1643011589-QQbutton

手机:13798586780

QQ/微信:1074760229

QQ群:551893940

工作时间:工作日9:00-18:00,节假日休息

关注微信