模板不是vue的一个特点吗,为什么现在写组件都用jsx呢

模板不是vue的一个特点吗,为什么现在写组件都用jsx呢

阅读 1.8k
2 个回答

直接说答案,因为vue模板表现力不足,你还在问这个问题说明你压根用不到jsx

我举几个例子你就知道了

例子1:

<CompA :v-bind="props1" v-model="value1"  v-if="condition">
   <div>
     ....
   </div>
</CompA>
<CompA :v-bind="props2" v-model="value2"  v-else>
   <div>
     ....
   </div>
</CompA>

假如这个if-elseCompAdefault slot是一摸一样的,而且这个默认插槽有几百行代码,并且大量引用了this上的变量,解决的方案只有两个

  • a. 一模一样的代码得复制两遍分别作为if分支和else的默认插槽
  • b. 把插槽的代码封装成一个SFC,但是不得不他在this上引用的变量全部作为props传递给他

上面两个方案都是很痛苦的,相反如果用用jsx那就太简单了他的代码可能是这样的

const sharedChildren = <div>....</div>

return condition ? <CompA {...props1}  vModel={value1}>
   {
    {
      default: () => sharedChildren
    }
   }
</CompA> :
<CompA {...props2} vModel={value2}>
   {
    {
      default: () => sharedChildren
    }
   }
</CompA>

例子2

假如有一个组件Menu当使用它时可以给他传一个插槽,不过有一个限制就是他的插槽内的VNode只能是SubMenuMenuItem类型的,假如混搭有其他类型的VNode这个组件都不能正常工作
所以它使用是大概是像下面这个样子

<Menu>
  <SubMenu>
    <MenuItem title="1-1">
    </MenuItem>
    <MenuItem title="1-2">
    </MenuItem>
    <MenuItem title="1-3">
    </MenuItem>
  </SubMenu>
  <MenuItem title="2-1" />
  <SubMenu>
    <MenuItem title="3-1">
    </MenuItem>
    <MenuItem title="3-2">
    </MenuItem>
    <MenuItem title="3-3">
    </MenuItem>
  </SubMenu>
</Menu>

可能很不巧,这个Menu需要是根据数据动态渲染的,而且数据的数量,和层级都是不确定的,也就是需要用到递归组件。
一般用模板我们可能会建立一个SFC组件
NestedMenuRenderer.vue

<script lang="ts">
type MenuItem = {
   title: string
   children: MenuItem[]
}
const NestedMenuRenderer = defineComponent({
  name: 'NestedMenuRenderer',
  props: {
    menuItem: {
       type: Object as PropType<MenuItem>
    }
  }
})
</script>

<template>
   <Fragment>
     <SubMenu v-if="menuItem.children.length" :title="menuItem.title">
       <NestedMenuRenderer v-for="item in menuItem.children" menuItem="item" />
     </SubMenu>
     <MenuItem v-else :title="menuItem.title"/>
   </Fragment>
</template>

的确是完成了任务,可是他会在每个MenuItemSubMenu外面包一个类型NestedMenuRendererVNode所以这个组件不能正常的工作,相反换成了jsx就很简单了.

const renderNestedMenu = (menu: MenuItem) => {
   if(menu.children.length) {
     return <SubMenu title={menu.title}>{menu.children.map(v => renderNestedMenu(v))}</SubMenu>
   }
   else return <MenuItem title={menu.title}/>
}
const data: MenuItem[] = ...;
return (<Menu>
         {data.map(v => renderNestedMenu(v))}
       </Menu>)

这个问题可以理解为「为啥大家不用/要用 dsl」
那就是「入门成本高、小众但高效」和「低入门成本、复杂」的取舍了

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题