当前位置: 首页 > Web前端 > vue.js

感受Vue3的神奇力量

时间:2023-03-31 15:12:29 vue.js

作者:JD牛志伟在过去的六个月中有幸参与了一个创新项目。由于没有历史包袱,他选择了Vue3技术栈。总体感觉如下:?设置语法糖大多数情况下,单向数据流应该遵循【单向数据流】的原则,禁止子组件直接修改props,否则复杂应用下的数据流会变得混乱,容易出现BUG,难以排错。直接修改props会报警,但是如果props是引用类型,修改props内部值不会有报警提示,所以如果props是引用类型,应该有团队协议(第5条除外)。给子组件状态赋值时,复杂的逻辑需要解引用(第5条除外)。state和修改state的方法可以封装成自定义的hooks或者提升到store内部,避免props的层层传递和修改一些父子组件是紧耦合的场景,可以允许修改内部值props,可以减少很多复杂度和工作量(需要团队约定一个固定的场景)逻辑/UI解耦使用Vue3的Composition/combinationAPI,将一定逻辑中涉及的state和修改state的方法封装成一个自定义的钩子,将组件中的逻辑解耦,这样即使UI有不同的造型或调整,只要逻辑不变,就可以复用逻辑下面是本项目涉及的真实案例——逻辑树component,UI有两种形式,可以相互转化。?钩子部分的代码:useDynamicTree.tsimport{ref}from'vue'import{nanoid}from'nanoid'exporttypeTreeNode={id?:stringpid:stringnodeUuid?:stringpartentUuid?:stringnodeType:stringnodeValue?:任何logicValue?:任何孩子:TreeNode[]level?:number}exportconstuseDynamicTree=(root?:TreeNode)=>{consttree=ref(root?[root]:[])constlevel=ref(0)//添加节点constadd=(node:TreeNode,pid:string='root'):boolean=>{//添加根节点if(pid===''){tree.value=[node]returntrue}level.value=0constpNode=find(tree.value,pid)if(!pNode)returnfalse//嵌套关系不能超过3层if(pNode.level&&pNode.level>2)returnfalseif(!node.id){node.id=nanoid()}if(pNode.nodeType==='operator'){pNode.children.push(node)}else{//如果父节点不是关系节点,然后构造一个新的关系节点constcurrent=JSON.parse(JSON.stringify(pNode))current.pid=pidcurrent.id=nanoid()Object.assign(pNode,{nodeType:'operator',nodeValue:'and',//重置回显信息logicValue:undefined,nodeUuid:undefined,parentUuid:undefined,children:[current,node],})}returntrue}//删除节点constremove=(id:string)=>{constnode=find(tree.value,id)if(!node)return//根节点处理if(node.pid===''){tree.value=[]return}constpNode=find(tree.value,node.pid)if(!pNode)returnconstindex=pNode.children.findIndex((item)=>item.id===id)if(index===-1)returnpNode.children.splice(index,1)if(pNode.children.length===1){//如果只剩下一个节点,则替换父节点(关系节点)const[one]=pNode.childrenObject.assign(pNode,{...one,},{pid:pNode.pid,},)if(pNode.pid===''){pNode.id='root'}}}//切换逻辑关系:and/orconsttoggleOperator=(id:string)=>{constnode=find(tree.value,id)if(!node)returnif(node.nodeType!=='operator')返回node.nodeValue=node.nodeValue==='和'?'or':'and'}//查找节点constfind=(node:TreeNode[],id:string):TreeNode|undefined=>{//console.log(node,id)for(leti=0;i0){level.value+=1常量结果=find(node[i].children,id)if(result){returnresult}level.value-=1}}returnundefined}//提供遍历节点方法,支持返回调constdfs=(node:TreeNode[],callback:(node:TreeNode)=>void)=>{for(leti=0;i0){dfs(node[i].孩子们,callback)}}}return{tree,add,remove,toggleOperator,dfs,}}?在不同组件中使用(UI1/UI2组件为递归组件,内部实现不再展开)//组件1//Component2Pinia状态管理将复杂的状态逻辑和修改状态的方法改进到store的内部管理,可以avoidlayersofpropsPassing,reducingpropscomplexity,clearstatemanagement定义一个商店(非声明式)::stringheadImg:stringorganizationFullName:string}exportconstuseUserStore=defineStore('user',()=>{constuserInfo=reactive({userName:'',realName:'',headImg:'',organizationFullName:''})constfullName=computed(()=>{return`${userInfo.userName}[${userInfo.realName}]`})constsetUserInfo=(info:UserInfo)=>{Object.assgin(userInfo,{...info})}return{userInfo,fullName,setUserInfo}})?在组件中使用