作为Vue的死忠粉,React每天都在被折腾。没想到这次针对的是Vue3。本来对新版本的Vue3充满了期待,但体验之后,却大失所望。可惜Vue3保守!本文介绍了Vue3的基本使用,Vue3的设计理念,组合API的实现原理,以及个人的思考。可能会有不妥和狭隘的地方,欢迎大家批评指正。前言不懂Vue3的同学可以通过Vite工具快速搭建Vue3开发环境,参考《Vue3文档》接入开发。在《Vue3组合式API征求意见稿》中,我们可以一窥Vue3的设计思路和技术选择的判断过程。其中,《为什么不支持class?》和《和React-Hook的相比》的分析值得一看。下面提到的template的所有用法都参考了Vue文件的HTML模板的相关用法。Vue3实战体验为了了解Vue3的用法,通过下面Vue3的新特性实现定时效果,应该可以覆盖大部分应用场景:jsxTypeScriptprops结合API生命周期import{ref,defineComponent,onMounted,onBeforeUnmount}from"vue";exportinterfacePropsType{title:string;}exportdefaultdefineComponent({props:{title:String},setup:(props)=>{lettime=ref((newDate()).toLocaleString());让timerForDate:number;onMounted(()=>{timerForDate=window.setInterval(()=>{time.value=(newDate()).toLocaleString()},1e3);});onBeforeUnmount(()=>{if(timerForDate){clearInterval(timerForDate)}});让renderDate=()=>{return(
currenttime:{time.value}
)}return()=>(<>{props.title}
{renderDate()}>)}})在写demo的过程中,逐渐了解到更多Vue3的新特性,以及新特性之间的界限而老版本的Vue2和Vue3也变得模糊了。这是好消息还是坏消息,以下是我个人的一些困惑。vue3的碎片化jsx复杂虽然vue3的jsx在vue2的基础上做了优化,但是还是有一些复杂的语法。具体语法参考官方文档:{props.msg}
Vue2实现组合API+defineComponent
{props.title}
)}})第二次声明会增加代码维护成本,第二次定义也没有意义。这个问题已经在Vue官方仓库跟进:https://github.com/vuejs/vue-...解决办法?我个人的想法是在编译阶段解决:只写TypeScript接口,在编译阶段将接口编译成props定义,根据函数类型判断()=>()=>JSX,转换成纯函数进入一个组件://在开发过程中导出接口PropsType{title:string;}exportdefaultfunctionTitleComponent(props:PropsType){return()=>({props.title}
);};//编译后exportinterfacePropsType{title:string;}exportdefaultdefineComponent({name:"TitleCompnent",props:{title:String,},setup:(props)=>{return()=>({props.title
)}})这样开发时只需要统一维护一个props定义(即上面的接口),编译时自动生成Vue3的“props”定义流程和原有界面保留,兼顾两者。同样,vue3不支持的类也有可能成为可能:由于传递给泛型参数的接口只是一个类型注解,对于prop的代理行为,用户仍然需要为此提供其运行时声明。这个二级声明是多余的和笨拙的。为什么要放弃模板?为了支持模板功能,Vue需要添加很多特性,比如槽、指令、装饰器、道具定义、公共设置(inheritAttrs)等功能。即使模板有这些特性的加持,仍然无法与JSX相提并论。可以说Vue3对模板的保留得不偿失,1.造成了开发的局限;2.增加了JSX的复杂度。模板的局限性在于无法编写复杂的语句,必须抽取到方法或计算属性中再引用。TypeScript很难进行代码提取和集成。template和jsx冲突,即jsx不能只在同一个模板中渲染一个文件中重复的模板片段很难提取出来(不可能把所有的小片段都拆开,只能重复写).如果组件是模板,则无法通过props传递给jsx进行渲染,slot模板的使用肯定已经过时了。但令人担忧的是,早在Vue2时代,模板的实现就已经和jsx挂钩了:模板编译成jsx,转成虚拟dom(vdom)。游达认为template是一种比jsx更好的语法,业务场景应该用template来写,但是需要加入很多特性才能达到jsx的通用性。从Vue3的角度来看,这是一个很矛盾的点。template的用法确实是过时了,鸡肋了弃得更快,还不算鸡肋。Vue的困境Vue2时代的优势变成了Vue3的困境:向后兼容(progressive)运行时(runtime)覆盖所有功能。可能是以上两点,导致Vue3在CompromiseonCompositionAPI中,仍然坚持模板,JSX支持不到位。为什么在Vue2不是问题,到Vue3就成了问题?Vue2是大版本,大版本不应该引入破坏性的修改,所以一定要兼容模板、指令等用法。而在Vue2时代,我们“各有千秋”,你用template,我用jsx,互不影响。但是Vue3是新版本,其中一个主要目的就是接入TypeScript,但是对于老功能,妥协了太多东西,创新并不彻底。考虑到Vue3的生态问题,即使项目方坚持使用JSX,放弃模板相关功能,Vue3的开源生态也是不可控的。不管项目方怎么规范,开源组件还是要用的。接入生态必然涉及到插槽、指令等模板功能。毕竟jsx语法复杂、缺少props接口等问题是无法避免的。CompositionAPI是个好东西?组合API是未来吗?是好的设计吗?这对于Vue3来说是无关紧要的,因为Vue3已经放弃了class方案,组合API成为了Vue3接入TypeScript的唯一选择。按照React的尿性,React-Hook并不是什么高端的东西。至于好处,考虑到React的生命周期hook常年乱糟糟的,所以最终将其纳入了Hook的统一接口。从这里来看,还是有好处的。综上所述,虽然上面提到的Vue3有很多缺点,但是Vue的优点还是需要被认可的:清晰明了的生命周期也是React同行掀起的良好的数据惰性处理和数据监控,省了很多的工作量。》框架能优化的东西都在框架里,解决“Computed”的精彩案例,全靠代码实现的集合,非常优雅巧妙,值得大家一读。而且,这个设计包括export的数据更新,极大的避免了漏更新的问题。稳定严谨的迭代,Vue的双刃剑(渐进+向后兼容),相比隔壁React在小版本号引入破坏性更新的性追求终极,参考有大为什么放弃webpack的稳定生态,有大介入了大部分Vue生态的建设,理念相同,质量保证平衡功能和开发体验Vue的优势非常突出,希望在新版本之前Vue3正式上线,着重提炼优势特性,摒弃旧有功能,如果大踏步前进,Vue3还是值得期待的。最后,个人建议在Vue3版本中,无论是公共开源组件还是业务代码,都不要使用模板相关的功能(包括槽、指令、修饰符等),这样可以更好的对接jsx+打字稿。