[经验分享] wepy组件化框架使用说明

[复制链接]
hyt_xcx手机认证 实名认证 视频认证 发表于 2017-5-11 23:02:39 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题
最近开始,针对一些第三方的框架及组件,做一些针对性的聚合;这次是针对wepy框架,这个框架深受好评;
主要解决的问题
开发模式转换
支持组件化开发
支持加载外部NPM包
单文件模式,使得目录结构更加清晰
默认使用babel编译,支持ES6/7的一些新特性
针对原生API进行优化
(更详细的内容请点击这里)
 在学习了一波wepy后,于是有了今天的微信小程序之图书管理系统(wepy版)。
153914hatyd8116as316y3.gif

153948qkxafdst44of16oj.gif

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

searchbar组件
searchbar组件的功能也很单纯,只是需要告诉父组件用户输入了什么信息。看一下代码
// searchbar.vue
<template>
<view class="search-bar">
    <input placeholder="请输入书名" bindinput="inputChange" />
    <button type="primary" bindtap="queryBooks">查詢</button>
</view>
</template>
<script>
import wepy from 'wepy';
export default class SearchBar extends wepy.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事件,从而获取到从子组件传递出来的数据,继而过滤数据。
  1. // index.vue
  2.     events = {
  3.         // 监听searchbar emit出来的事件,从而获得searchbar的输入
  4.         'inputChange': ($event, ...args) => {
  5.             this.searchFilter = args[0];
  6.             let filterBooks = [];
  7.             if (this.searchFilter.trim().length === 0) {
  8.                 filterBooks = this.booksCopy;
  9.             } else {
  10.                 this.books.forEach((book) => {
  11.                     if (this.searchFilter.trim() &&
  12.                         book.title.toUpperCase().indexOf(this.searchFilter.toUpperCase()) >= 0) {
  13.                         filterBooks.push(book);
  14.                     }
  15.                 });
  16.             }
  17.             this.books = filterBooks;
  18.             this.$apply();
  19.         },
  20.         // 点击book list组件时候转跳到明细页面,book list组件把被点击的book传递出来
  21.         'goToDetailPage': ($event, ...args) => {
  22.             let book = args[0];
  23.             wx.navigateTo({
  24.                 url: 'bookdetail?book=' + JSON.stringify(book),
  25.             });
  26.         },
  27.     };
复制代码
booklist组件
booklist组件接收一个book数组,然后for循环把book的概要信息显示出来.父组件(index)需要在onLoad的时候发起请求获取book信息,然后通过props把信息传递给booklist。index页面在发起请求的时候使用了wepy封装后的wx.request,返回promise。然后利用async/await可以让异步请求看起来像同步,是不是很爽!!
  1. // index
  2.     async onShow() {
  3.         var op1 = {
  4.             url: Config.clubApi.list,
  5.             data: {
  6.                 appkey: Config.appKey,
  7.                 type: 'bookLibrary'
  8.             }
  9.         };
  10.         let res = await wx.request(op1);
  11.         let clubBooks = res.data.result;
  12.         let clubBooksArray = [];
  13.         if (clubBooks.length > 0) {
  14.             try{
  15.                 clubBooks.forEach((clubBook) => {
  16.                     clubBooksArray.push(clubBook.value);
  17.                 });
  18.                 this.books = clubBooksArray;
  19.                 this.booksCopy = this.books;
  20.             }catch(err){
  21.                 this.books=[];
  22.                 this.booksCopy=[];
  23.             }
  24.         }
  25.         this.$apply();
  26.     }
复制代码
  1. //booklist组件 ,通过props获取从父组件传递过来的数据
  2. <template>
  3. <view class="book-content">
  4.     <view wx:for="{{books}}" wx:key="isbn13" id="{{item.isbn13}}" data-qty="{{item.qty}}" bindtap="goToDetailPage({{item}})">
  5.         <view class="book-list">
  6.             <view class="book-image">
  7.                 <image src="{{item.image}}" mode="aspectFit"></image>
  8.             </view>
  9.             <view class="book-info">
  10.                 <view class="book-info-style">
  11.                     <view>书名:{{item.title}}</view>
  12.                     <view>作者:{{item.author}}
  13. </view>
  14.                     <view>价格:{{item.price}}
  15. </view>
  16.                     <view>出版信息:{{item.publisher}}
  17. </view>
  18.                     <view>可借数量:{{item.qty}}
  19. </view>
  20.                 </view>
  21.             </view>
  22.         </view>
  23.         <view class="line"></view>
  24.     </view>
  25. </view>
  26. </template>
  27. props = {
  28. // 接收父组件传递的books数组
  29.   books: {},
  30. };
复制代码
然后,我们回到index页面,把两个组件引用进来就可以了,index页面完成!
  1. <view class="main-wrapper">
  2.     <view class="search-bar-wrapper">
  3.         <component id="searchBar"></component> //searchbar组件
  4.     </view>
  5.     <view class="book-list-wrapper">
  6.         <component id="bookList" :books.sync="books"></component> //booklist组件
  7.     </view>
  8. </view>
复制代码
book detail页面
接着我们再看看book detail 页面的结构。其实也是由3部分组成。最上方是booklist 组件,中间是book info组件,最下面是btn wrapper,如下图。大家可以发现,这个页面也是有book list的,那我们是否需要把代码copy过来的。No!我们只需要引用过来就好了,这个是组件化开发的好处之一,重用性高。
153915m37bmbvixis95145.jpg

以下是book detail的页面结构,非常的简单。
  1. <view class="main-wrapper">
  2.     <view class="book-list-wrapper">
  3.         <component id="bookList" :books.sync="book"></component>
  4.     </view>
  5.     <view class="book-detail-wrapper">
  6.         <component id="bookInfo" :books.sync="bookInfo" :height.sync="windowHeight"></component>
  7.     </view>
  8.     <view class="control-btn-wrapper">
  9.         <button type="primary" wx:if="{{bookInfo.qty > 0}}" bindtap="borrowBook"> 借阅 </button>
  10.         <button type="primary" wx:if="{{bookInfo.qty === 0}}"> 预约 </button>
  11.         <button type="primary" wx:if="{{showAddBook}}"> 录入 </button>
  12.     </view>
  13. </view>
复制代码
现在我们还差一个book info组件,now,一起来把它撸出来。
book info 组件
其实book info组件的功能也很单纯。把“内容推荐”,“作者简介”和“目录”信息显示出来就可以。看以下页面结构:
  1. // book info组件
  2. <view class="book-info">
  3.     <scroll-view scroll-y="true" style="height:{{height}}px;" >
  4.         <view class="book-intro">
  5.             <text class="book-title">内容推荐</text>
  6.             <text class="book-msg">{{books.summary}}</text>
  7.         </view>
  8.         <view class="space-line-30"></view>
  9.         <view class="book-intro">
  10.             <text class="book-title">作者简介</text>
  11.             <text class="book-msg">{{books.author_intro}}</text>
  12.         </view>
  13.         <view class="space-line-30"></view>
  14.         <view class="book-intro">
  15.             <text class="book-title">目录</text>
  16.             <text class="book-msg">{{books.catalog}}</text>
  17.         </view>
  18.     </scroll-view>
  19. </view>
复制代码
这里使用到scroll view,小程序的scroll view是需要指定高度的,否则无法滚动。所以我们要动态计算中间那部分的高度。但是,组件本身是不知道它的容器的有多高的,所以需要父组件通过props告诉组件。
  1. // book info 组件
  2.     props = {
  3.         books: {},//接收要显示的书本的信息
  4.         height:Number,//接收scroll view的高度
  5.     };
  6. //book detail 组件
  7.     async onLoad(options) {
  8.         this.book = [];
  9.         this.book.push(JSON.parse(options.book));
  10.         this.bookInfo = JSON.parse(options.book);
  11.         if (this.windowHeight === 0) {
  12.             // 获取设备的高度,然后减去book list组件的高度,减去btn wrapper的高度再减去margin top 的高度
  13.             let res = await wx.getSystemInfo();
  14.             this.windowHeight = res.windowHeight - 66 - 136 - 10;
  15.             this.$apply();
  16.         }
  17.     }
复制代码
好了,book info组件也差不多完成了,然后我们运行程序就差不多可以看到上面贴图的效果了。
到此,本demo中最复杂的部分已经完成了,希望能给大家一点点启示。
接下来的“图书录入”和“我”页面,就不那么详细诉述了,只对功能做一些介绍。
153916gb8s0p0kmqh0ws30.png

图书录入画面具有两个开关和一个按钮。
“扫码录入”开关控制是否调用扫一扫录入图书信息(扫图书后面的ISBN码),如果关闭这个开关,将显示一个表单人工录入信息(人工录入功能尚未完善)。如果启用这个功能,在按“开始录入”的时候会开启摄像头扫一扫,默认开启。
“连续录入”按钮控制录入完一本书后继续开启摄像头继续录入还是录入一本后返回index页面。默认开启。
点击“开始录入”启用扫一扫功能,可以连续扫描,直到用户按返回。
我 页面
153916gb8s0p0kmqh0ws30.png

该页面主要用于查看借了什么书,什么时候改归还(该页面功能尚未完善,后续补充)。
最后,放上github地址,有兴趣的可以去下载看看,请点击这里,喜欢的可以点个star喔,谢谢。


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

专注源码分享,教程分享
全国服务电话

187-8198-7163

周一至周8:00-22:00

反馈建议

cdhaoyt@163.com 在线QQ咨询

扫描二维码关注我们

Powered by Discuz! X3.2© 2001-2013 Comsenz Inc.( 蜀ICP备16032957号-1