所需E币: 0
时间: 2023-12-18 15:21
大小: 3.45KB
前端高手特训从0到1带你手写一个微信小程序底层框架,小程序是一种不需要下载安装即可使用的应用,它实现了应用“触手可及”的梦想,用户扫一扫或者搜一下即可打开应用。也体现了“用完即走”的理念,用户不用关心是否安装太多应用的问题。应用将无处不在,随时可用,但又无需安装卸载。框架管理了整个小程序的页面路由,可以做到页面间的无缝切换,并给以页面完整的生命周期。开发者需要做的只是将页面的数据、方法、生命周期函数注册到框架中,其他的一切复杂的操作都交由框架处理。wepy支持类似Vue的组件化开发,可以将页面拆分成多个独立的组件,提高代码复用性和开发效率。下面我们通过一个实际的案例来说明组件化开发在wepy中的应用。假设我们有一个小程序项目,其中包含一个商品列表页面和一个商品详情页面。我们可以将商品列表和商品详情抽象成两个组件,并在需要的地方引用它们。首先,我们创建一个名为GoodsList的组件。在src/components目录下创建GoodsList.wpy文件,并编写如下代码:importaxiosfrom'axios'constdefaultConfig={ timeout:5000, baseURL:'/release/'}constaxiosInstance=axios.create(defaultConfig)//添加请求拦截器axiosInstance.interceptors.request.use(config=>{ returnconfig},(err)=>{ //对请求错误做些什么 returnPromise.reject(err)})//请求拦截器,内部根据返回值,重新组装,统一管理。axiosInstance.interceptors.response.use(res=>{ console.log('接口详情:',res) returnres})exportdefault{ //封装get httpGet(url:any,params={}){ returnaxiosInstance.get(url,{params}).then(res=>res.data).catch() }, //封装post httpPost(url:any,params={}){ returnaxiosInstance.get(url,{params}).then(res=>res.data).catch() }}封装一个openStore(),使用indexedDB.open()方法返回一个IDBRequest对象,接着将这个对象上的三个事件分别放置进入:onsuccess、onerror、onupgradeneeded。onsuccess表示打开数据库成功的事件。onerror表示打开数据库失败的事件。onupgradeneeded是数据库升级事件,如果版本号更新,并且大于之前的版本号则进行数据库升级,该事件回调里面,会创建我们所需要的对象仓库,类似于关系型数据库中的表的概念。exportdefaultclassDB{ privatedbName:string//数据库名称 constructor(dbName:string){ this.dbName=dbName } //打开数据库 publicopenStore(storeName:string,keyPath:string,indexs?:Array<string>){ constrequest=window.indexedDB.open(this.dbName,2) request.onsuccess=(event)=>{ console.log('数据库打开成功') console.log(event) } request.onerror=(event)=>{ console.log('数据库打开失败') console.log(event) } request.onupgradeneeded=(event)=>{ console.log('数据库升级成功') const{result}:any=event.target conststore=result.createObjectStore(storeName,{autoIncrement:true,keyPath}) if(indexs&&indexs.length>0){ indexs.map((v:string)=>{ store.createIndex(v,v,{unique:true}) }) } store.transaction.oncomplete=(event:any)=>{ console.log('创建对象仓库成功') } console.log(event) } }}在子组件headerCommon.vue中切换语言时,调用saveLanguageApi接口,保存当前语言环境到indexedDB中,并将当前语言包zhCn或者en作为参数传递给父组件App.vue,代码片段如下://commonHeader.vuefunctionhandleSelect(e:any){ if(e==='zh'){ emit('changeLang',zhCn) saveLanguage('zh') }elseif(e==='en'){ emit('changeLang',en) saveLanguage('en') } console.log(e)}//Mock接口:保存当前语言环境functionsaveLanguage(language:any){ saveLanguageApi(language).then(res=>{ const{success}=res if(success){ console.log('保存当前语言包成功') } })}通过调用getLanguage接口获取到之前调用存储在indexedDB中的语言环境,然后赋值给全局组件,代码片段如下://headerCommon.vue//Mock接口:保存当前语言环境functiongetLanguage(){ fetchLanguageApi().then(res=>{ const{success,result}=res const{name}=result if(success){ if(name==='zh'){ emit('changeLang',zhCn) }elseif(name==='en'){ emit('changeLang',en) } console.log('获取当前语言环境成功') } })}getLanguage()使用@include指令来引入定义好的样式函数,该函数的三个参数可以根据传入的值来对flex布局进行自定义,默认值为:column、center、right,在footerCommon.scss中我们重新自定义了该样式函数,分别传入row、space-between、flex-start,代码片段如下://footerCommon.scss.common-footer{ border-top:1pxsolidrgb(235,235,235); .footer{ @includemain-wrapper; @includelayout(row,space-between,flex-start); padding:20px0; li{ @includelayout; h4{ font-weight:bold; } a{ margin-bottom:10px; color:rgb(72,72,72); text-decoration:none; &:hover{ text-decoration:underline; } } } }}订单中心模块会使用到的两个Mock接口为saveOrderApi、fetchOrderApi,一个是立即预定,另一个是查询订单列表,具体代码片段如下//src/api/order/index.tsconststoreName=Object.keys(airbnb.orderObjectStore)[0]//Mock接口:立即预定exportasyncfunctionsaveOrderApi(params:any){ constloading=ElLoading.service({ lock:true, background:'rgba(0,0,0,0.1)' }) //是否存在相同订单Id consthasOrderId=awaitnewPromise((resolve,reject)=>{ airbnb.airbnbDB.getList(storeName).then((res:any)=>{ setTimeout(()=>{ loading.close() },200) res&&res.filter((item:any)=>{ if(item.orderId===params.orderId){//存在相同订单Id resolve(true) } }) resolve(false) }) }) letresult:IResultOr if(hasOrderId){ result=awaitnewPromise((resolve,reject)=>{ resolve({code:'000001',success:false,message:'数据已存在',result:null}) }) }else{ result=awaitnewPromise((resolve,reject)=>{ airbnb.airbnbDB.updateItem(storeName,params).then(res=>{ setTimeout(()=>{ loading.close() },200) resolve({code:'000000',success:true,message:'操作成功',result:null}) }) }) } returnresult}通过应用这些进阶技巧和最佳实践,可以进一步提升小程序的性能和开发效率,同时优化代码质量,为用户提供更好的使用体验。