微信小程序之图书管理系统(wepy版)

miyunkeji 2017-01-19

2016年小程序的推出,刷爆了朋友圈。作为一名好奇的程序猿,当然是要学习一下。于是就在2个月前在小黄象发了个demo图书管理系统(社区API版).个人在写这个demo的时候发现小程序有一些不方便的地方:

不能使用promise(后来发现手动引用第三方promise库还是可以的)

不能使用promise意味着一定要使用回调这种写法,当回调的层次深了后,代码的可读性将大幅下降,日后维护也麻烦。

开发模式不利于代码的重复利用

 后来发现Gcaufy大神有开发了一个wepy框架,能解决小程序的一些问题。以下摘自于wepy的介绍.

主要解决的问题

开发模式转换

支持组件化开发

支持加载外部NPM包

单文件模式,使得目录结构更加清晰

默认使用babel编译,支持ES6/7的一些新特性

针对原生API进行优化

(更详细的内容请点击这里)

 在学习了一波wepy后,于是有了今天的微信小程序之图书管理系统(wepy版),数据的存储还是使用社区的API,大家可以直接把源码下载下来运行。本demo在外观和功能上与图书管理系统(社区API版)没有多大的区别,更多的是一种组件化的开发思路(本文不对样式进行介绍)。好了,开始进入正题。

完成效果图

index页面分析index页面其实很简单,就包含两个组件,分别是searchbar和booklist。我们只需通过css控制这两个组件的布局就可以。剩下的就是searchbar和booklist的开发。

searchbar组件searchbar组件的功能也很单纯,只是需要告诉父组件用户输入了什么信息。看一下代码

//searchbar.vue

<template>

<viewclass="search-bar">

<inputplaceholder="请输入书名"bindinput="inputChange"/>

<buttontype="primary"bindtap="queryBooks">查詢</button>

</view>

</template>

<script>

importwepyfrom'wepy';

exportdefaultclassSearchBarextendswepy.component{

props={};

data={};

events={

'index-broadcast':($event,...args)=>{

console.log(`${this.name}receive${$event.name}from${$event.source.name}`);

}

};

methods={

inputChange(e){

this.$emit('inputChange',e.detail.value);

},

};

}

</script>

当用户在输入的时候会触发inputChange事件,而inputChange会emit一个叫“inputChange”的事件。在父组件中(page也是组件,这里指index页面),会监听inputChange事件,从而获取到从子组件传递出来的数据,继而过滤数据。

//index.vue

events={

//监听searchbaremit出来的事件,从而获得searchbar的输入

'inputChange':($event,...args)=>{

this.searchFilter=args[0];

letfilterBooks=[];

if(this.searchFilter.trim().length===0){

filterBooks=this.booksCopy;

}else{

this.books.forEach((book)=>{

if(this.searchFilter.trim()&&

book.title.toUpperCase().indexOf(this.searchFilter.toUpperCase())>=0){

filterBooks.push(book);

}

});

}

this.books=filterBooks;

this.$apply();

},

//点击booklist组件时候转跳到明细页面,booklist组件把被点击的book传递出来

'goToDetailPage':($event,...args)=>{

letbook=args[0];

wx.navigateTo({

url:'bookdetail?book='+JSON.stringify(book),

});

},

};

booklist组件booklist组件接收一个book数组,然后for循环把book的概要信息显示出来.父组件(index)需要在onLoad的时候发起请求获取book信息,然后通过props把信息传递给booklist。index页面在发起请求的时候使用了wepy封装后的wx.request,返回promise。然后利用async/await可以让异步请求看起来像同步,是不是很爽!!

//index

asynconShow(){

varop1={

url:Config.clubApi.list,

data:{

appkey:Config.appKey,

type:'bookLibrary'

}

};

letres=awaitwx.request(op1);

letclubBooks=res.data.result;

letclubBooksArray=[];

if(clubBooks.length>0){

try{

clubBooks.forEach((clubBook)=>{

clubBooksArray.push(clubBook.value);

});

this.books=clubBooksArray;

this.booksCopy=this.books;

}catch(err){

this.books=[];

this.booksCopy=[];

}

}

this.$apply();

}

//booklist组件,通过props获取从父组件传递过来的数据

<template>

<viewclass="book-content">

<viewwx:for="{{books}}"wx:key="isbn13"id="{{item.isbn13}}"data-qty="{{item.qty}}"bindtap="goToDetailPage({{item}})">

<viewclass="book-list">

<viewclass="book-image">

<imagesrc="{{item.image}}"mode="aspectFit"></image>

</view>

<viewclass="book-info">

<viewclass="book-info-style">

<view>书名:{{item.title}}</view>

<view>作者:{{item.author}}

</view>

<view>价格:{{item.price}}

</view>

<view>出版信息:{{item.publisher}}

</view>

<view>可借数量:{{item.qty}}

</view>

</view>

</view>

</view>

<viewclass="line"></view>

</view>

</view>

</template>

props={

//接收父组件传递的books数组

books:{},

};

然后,我们回到index页面,把两个组件引用进来就可以了,index页面完成!

<viewclass="main-wrapper">

<viewclass="search-bar-wrapper">

<componentid="searchBar"></component>//searchbar组件

</view>

<viewclass="book-list-wrapper">

<componentid="bookList":books.sync="books"></component>//booklist组件

</view>

</view>

bookdetail页面接着我们再看看bookdetail页面的结构。其实也是由3部分组成。最上方是booklist组件,中间是bookinfo组件,最下面是btnwrapper,如下图。大家可以发现,这个页面也是有booklist的,那我们是否需要把代码copy过来的。No!我们只需要引用过来就好了,这个是组件化开发的好处之一,重用性高。

以下是bookdetail的页面结构,非常的简单。

<viewclass="main-wrapper">

<viewclass="book-list-wrapper">

<componentid="bookList":books.sync="book"></component>

</view>

<viewclass="book-detail-wrapper">

<componentid="bookInfo":books.sync="bookInfo":height.sync="windowHeight"></component>

</view>

<viewclass="control-btn-wrapper">

<buttontype="primary"wx:if="{{bookInfo.qty>0}}"bindtap="borrowBook">借阅</button>

<buttontype="primary"wx:if="{{bookInfo.qty===0}}">预约</button>

<buttontype="primary"wx:if="{{showAddBook}}">录入</button>

</view>

</view>

现在我们还差一个bookinfo组件,now,一起来把它撸出来。

bookinfo组件其实bookinfo组件的功能也很单纯。把“内容推荐”,“作者简介”和“目录”信息显示出来就可以。看以下页面结构:

//bookinfo组件

<viewclass="book-info">

<scroll-viewscroll-y="true"style="height:{{height}}px;">

<viewclass="book-intro">

<textclass="book-title">内容推荐</text>

<textclass="book-msg">{{books.summary}}</text>

</view>

<viewclass="space-line-30"></view>

<viewclass="book-intro">

<textclass="book-title">作者简介</text>

<textclass="book-msg">{{books.author_intro}}</text>

</view>

<viewclass="space-line-30"></view>

<viewclass="book-intro">

<textclass="book-title">目录</text>

<textclass="book-msg">{{books.catalog}}</text>

</view>

</scroll-view>

</view>

这里使用到scrollview,小程序的scrollview是需要指定高度的,否则无法滚动。所以我们要动态计算中间那部分的高度。但是,组件本身是不知道它的容器的有多高的,所以需要父组件通过props告诉组件。

//bookinfo组件

props={

books:{},//接收要显示的书本的信息

height:Number,//接收scrollview的高度

};

//bookdetail组件

asynconLoad(options){

this.book=[];

this.book.push(JSON.parse(options.book));

this.bookInfo=JSON.parse(options.book);

if(this.windowHeight===0){

//获取设备的高度,然后减去booklist组件的高度,减去btnwrapper的高度再减去margintop的高度

letres=awaitwx.getSystemInfo();

this.windowHeight=res.windowHeight-66-136-10;

this.$apply();

}

}

原文链接:http://bbs.jointforce.com/topic/25380

相关推荐