简介
Svelte是最近新出的前端框架,和react的vdom不同,Svelte应用动态剖析在构建时创立DOM更新代码,搭配官网高深莫测的老手教程,给人直观的应用体验,上手会很快。在业务实际中我上手采坑并总结了一下内容,经实际能够间接上生产。
ts+scss+svlete模板
通常在react我的项目里咱们会用ts进步业务逻辑开发效率,style module用来防止css命名重叠。在react中可能是这么写
// index.tsx...<ul className={styles.mylist} ref={this.myRef} onScroll={this.scrollHandler}>{this.props.data.length>0 ?this.props.data.map((v,i)=> <Item key={i}>{v}</Item> ) :<li>empty</li> }</ul>...
在svelte间接单文件组件
// index.svelte<script lang="ts">...import type {IData} from "./types.ts"import Item from "./item.svelte"export let data:IData=[]export let myRef;scrollHandler=()=>{}</script><style>...</style><ul class="mylist" bind:this={myRef} on:scroll={scrollHandler}>{# if data.length>0} <li>empty</li>{:else} {#each data as v,i} <Item>{v}</Item> {/each}{/if}</ul>
须要留神:
1.但凡svelte组件import的名称必须首字母大写,不然编译不认它是个svelte组件。
2.import ts类型申明必须是 import type ... 也是为了更好的辨别.
export let/const
变量 作为相似props的语法,目前语法查看还不欠缺,有时会呈现正告- 和React不同,循环的dom不强制查看key属性
- svelte单文件组件中的css会人造反对编译成类style module的className,不必放心css名称反复,但会疏忽和正告未应用的css,不会打包进去。(这个很奇怪,如果父组件和子组件想笼罩对方的css classname 就比拟麻烦了,这时候纯css思路断了只能换js思路也就是通过props来实现)
状态治理
组件内的状态没什么好说的,长期变量一把梭就好了。本文只探讨store的用法。为了让svelte状态治理有redux的滋味,我实际中用以下的写法,不喜勿喷:
//store.tsimport { writable } from 'svelte/store';//申明初始statelet initState={ loading:false, readed:0,}const state = writable(initState);const { subscribe, set, update } = state;//可能用失去的resetconst reset = () => set(initState);//mounted办法会在组件的onMount时调用const mounted = async () => { updateLoadStart(); const {data,error}=await server.getPageData(); !error && await updateReaded(data); updateLoadEnd();}updateLoadStart=()=>update((prevState)=>{ return { ...prevState, loading:true }})...
在组件里便能够这么引入应用:
<script lang="ts"> import {state,mounted, onBtnClick} from "./store";onMount(mounted);</script><button on:click={onBtnClick}>{$state.readed}</button>
实际中你能够大胆的拆分和命名 比方类vue的命名 mounted method compute的数据管理,又比方类rematch的 select loading.effects 组合,具体看之前框架的习惯适度一下~
须要留神:
- 目前没有devtool的浏览器插件能够查看批改state,我反正装置了个svelte的插件试了啥都没有,可能将来不久会公布吧。目前只能{@debug $state} 来察看state的变动
与dom的交互
我看到 https://css-tricks.com/lazy-l... 一步步教学写个图片懒加载的组件。着实不错,改一下兼容问题能够上生产。
其次官网文档的motion/transition/animate 我试过能够很不便实现一些常见动画性能,比方动画折叠开展、轮播的滚动,这里就不贴代码了,跟着文档走一遍根本没难度。
留神的点:
1.on:click 这种间接透传事件的貌似只在组件的根元素起作用,在子元素里还是得用on:click={() => dispatch('click')} 的形式向上emit
2.html标签校验居然认为 href="javascript:" 不是非法的链接,必须要在上一行正文<!-- svelte-ignore a11y-invalid-attribute -->才行
3.款式写法习惯上class="" style=""更靠近vue,而不是react的 className="" style={}
4.bind过的ref记得onDestory时销毁
打包
官网给的rollup打包配置过于简略了,也不兼容es5。网上看到有其他同学从新编译svelte到es5的,也是厉害。其实魔改一下官网的rollup配置就行。我实际中能够欢快的把ts编译成es5。
简略讲一下几个要点,最初会放出配置文件给大家参考,少走弯路少采坑。
1.打包资源加hash
...output:{ ... entryFileNames: "bundle.[hash].js"}
- 向下兼容
"> 1%, not dead" 为了兼容连箭头语法都不反对的浏览器,抉择个,文件体积会加倍,一个页面差不多200k gzip 60k
"> 5%, not dead" 这个就小了好多 100k+ gzip 30k+
3.用"rollup-plugin-serve"换掉官网手写的serve
!production && serve({ contentBase: "dist", port: 5000})
- svelte css 加hash
css: (css) => { const hash = crypto.createHash("md5").update("bundle" + css.code).digest("hex"); css.write("bundle." + hash.slice(0, 8) + ".css", !production);}
当然如果想postcss autofixer进一步解决的网上也有其余答案
5.用@rollup/plugin-html 依据模板替换hash的文件并生成manifest
html({dest: "dist",fileName: "index.html",template: async ({ bundle }) => { let bundleFileNames = Object.keys(bundle); fs.writeFile('dist/asset-manifest.json', JSON.stringify( bundleFileNames.reduce((assetMap,fileName) => { assetMap[fileName.replace(/\.\w+\./, '.')] = fileName; return assetMap }, {}),null,"\t"),"utf8"); return bundleFileNames.reduce( (code, fileName) => code.replace(fileName.replace(/\.\w+\./, '.'), fileName), await fs.readFile("public/index.html", "utf8") );},})
rolllup.config.js
集体感悟
感觉svelte体验上模板语法和单位件组件的思路更靠近vue,但又不齐全遵循指令标准(比方循环判断)退出了精简但又实用的 动画 和 状态治理。其次性能方面比react好一点点,打包体积小是有很大劣势。冀望将来在开发体验比方工具链上有新的冲破。
框架比照?
https://medium.com/@d_kzlv/yeah-holy-wars-i-like-that-1406eb291331 发现medium大家意见不一,看看就好