• 微信小程序之组件的集合(四)


      这个主要是来开发book的这个大模块的,看看如何优雅的开发出booked模块!

    一、book模块的创建

    这个就很简单了,创建一个大的框架是很简单的

     二、组件的编写

    (1)wxml组件页面的编码

    首先是将一本书的展示看做是一个组件,然后就是循环展示所有请求的书籍的信息,所以需要把一本书当做一个组件来制作,这样就能比较合理的解决这个问题!

     1 // book组件的页面的代码
     2 <view class="container">
     3   <image src="{{book.image}}"></image>
     4   <view class="description">
     5     <text class="title">{{book.title}}</text>
     6     <text class="author">{{book.author}}</text>
     7     <view class="foot">
     8       <text class="footer">{{book.fav_nums}} 喜欢</text>
     9     </view>
    10   </view>
    11 </view>

    将这个book组件引用到page中去,给用户展示书籍的信息,需要在book.json 中引入,并且将组件的写到book.wxml页面代码中,这里暂时只是展示一个book组件

     1 // page中的book.json 中引入book组件
     2 {
     3   "usingComponents": {
     4     "v-book":"/components/book/index"
     5   }
     6 }
     7 
     8 // page中的book.wxml中引入v-book标签
     9 <v-book book="{{books[0]}}" />
    10 
    11 // page中的book.js中操作数据,将数据传递到页面属性中,只写主要的生命周期函数
    12 import {
    13   BookModel
    14 } from '../../models/book.js';
    15 
    16 // 实例化BookModel对象
    17 const bookModel = new BookModel();
    18 
    19 Page({
    20 
    21   /**
    22    * 页面的初始数据
    23    */
    24   data: {
    25     // 服务器请求的数据 book的集合
    26     books:[]
    27   },
    28 
    29   /**
    30    * 生命周期函数--监听页面加载
    31    */
    32   onLoad: function(options) {
    33     // 这种写法才能规避回调地狱的
    34     bookModel.getHotList()
    35     .then(res => {
    36       // 这种写法不完善 只是做了赋值 页面无法获取到
    37       // this.data.books = res
    38       this.setData({
    39         books:res
    40       })
    41     })
    42 
    43   },

    (2)book组件样式的编码

    这个啊,让人头疼的,我是写不出来,哈哈

     1 .container{
     2   margin-top: 30rpx;
     3   display: flex;
     4   position: relative;
     5   box-shadow: 2px 2px 3px #e3e3e3;
     6   flex-direction: column;
     7   width: 240rpx;
     8   height: 360rpx;
     9 }
    10 
    11 /* 书籍封面的样式 */
    12 .container image {
    13   width: 100%;
    14   height: 100%;
    15   border-radius: 2px;
    16 }
    17 
    18 .description{
    19   width: 216rpx;
    20   position: absolute;
    21   bottom: 0;
    22   background-color: #fff;
    23   padding: 5rpx 10rpx 8rpx 15rpx;
    24   font-size: 24rpx;
    25   display: flex;
    26   flex-direction: column;
    27   border-bottom-left-radius: 2px;
    28   border-bottom-right-radius: 2px;
    29 }
    30 
    31 .title{
    32   margin-top: 10rpx;
    33   text-overflow: ellipsis;
    34   white-space: nowrap;
    35   overflow: hidden;
    36 }
    37 
    38 .author{
    39   font-size: 20rpx;
    40   color: #999999;
    41   margin-bottom: 10rpx;
    42   text-overflow: ellipsis;
    43   white-space: nowrap;
    44   overflow: hidden;
    45 }
    46 
    47 .foot{
    48   font-size: 20rpx;
    49   display: flex;
    50   flex-direction: row;
    51   justify-content: flex-end;
    52 }
    53 
    54 .footer{
    55   color: 
    56 }

    三、组件的应用

    因为书籍是使用的一组的书籍组件,如何来把服务器上传回来的所有的书籍信息全部显示出来,这个就是我们需要考虑的,需要完成的

    小程序中肯定是存在类似for循环的,那就是wx:for 但是在小程序中并不是叫做for循环,而是叫做列表渲染

    (1)列表渲染

    1 <block wx:for="{{books}}">
    2   <v-book book="{{item}}" />
    3 </block>

     (2)整体页面布局

    这个就是pages中的book页面的代码了,主题包含一个搜索栏,以及下面的图书列表

     1 <view class="container">
     2   <view class="header">
     3     <view class="box">
     4       <image src="/images/icon/search.png"></image>
     5       <text>搜索书籍</text>
     6     </view>
     7   </view>
     8   <view class="sub-container">
     9     <image src="/images/book/quality.png" class="head-img"></image>
    10     <view class="books-container">
    11       <block wx:for="{{books}}">
    12         <v-book book="{{item}}" />
    13       </block>
    14     </view>
    15   </view>
    16 </view>

    (3)整体的样式代码

    看一下如何设计样式来让这个页面看起来那么舒服,这是最难的吧,充分灵活的使用flex布局来实现这样的样式

     1 .container{
     2   display: flex;
     3   flex-direction: column;
     4   align-items: center;
     5   width:100%;
     6 }
     7 
     8  .sub-container{
     9   display: flex;
    10   flex-direction: column;
    11   align-items: center;
    12   background-color: #f5f5f5;
    13   margin-top:100rpx;
    14   /* z-index:0;  */
    15 } 
    16 
    17 .books-container{
    18   margin-top:10rpx;
    19   display: flex;
    20   flex-direction: row;
    21   flex-wrap: wrap;
    22   padding: 0 90rpx 0 90rpx;
    23   justify-content: space-between;
    24 }
    25 
    26 .books-container v-book{
    27   margin-bottom: 30rpx;
    28 }
    29 
    30 .box{
    31   display:flex; 
    32   flex-direction: row;
    33   justify-content: center;
    34   align-items: center; 
    35   border-radius: 50px;
    36   background-color: #f5f5f5;
    37   height: 34px;
    38   width:700rpx;
    39   color:#999999;
    40 }
    41 
    42 .header{
    43   /* fixed 是使得容器固定 */
    44   position: fixed; 
    45   background-color: #ffffff;
    46   height:100rpx;
    47   width:100%;
    48   border-top:1px solid #f5f5f5;
    49   border-bottom:1px solid #f5f5f5;
    50   display: flex;
    51   flex-direction: row;
    52   align-items: center;
    53   justify-content: center;
    54   box-shadow:0 0 3px 0 #e3e3e3; 
    55   z-index: 99;
    56 }
    57 
    58 .head-img{
    59   width:106rpx;
    60   height:34rpx;
    61   margin-top:40rpx;
    62 }
    63 
    64 .box image{
    65   margin-right:10px;
    66   width:14px;
    67   height:14px;
    68   margin-bottom:-2px;
    69 }

    四、book组件中业务逻辑的实现

    这个主要是实现功能就是从book列表页面用户直接点击之后,跳转到书籍的详细信息的页面,这个该如何实现,是在组件中实现跳转逻辑,还是在页面上实现,如何取舍,如何选择,是选择组件的通用性呢?还是选择组件的设计实现简单呢?如何来写这个逻辑代码?

    1、不考虑组件的通用性

    不考虑组件通用性的话,就直接在组件中实现页面的跳转就OK了,具体的实现代码如下:

     1 // 组件中的wxml文件
     2 <view bind:tap="onTap" class="container"> 
     3 </view>
     4 
     5 // 组件中的js文件 小程序中的navigateTo实现跳转
     6   methods: {
     7     onTap(event){
     8       const bid = this.properties.book.id;
     9       wx.navigateTo({
    10         url: `/pages/book-detail/book-detail?bid=${bid}`,
    11       })
    12     }
    13   }

    2、考虑组件通用性的

    五、book详细信息的开发

    1、小程序中的编译模式

    为了方便开发,让小程序每次编译之后都会是书籍详细信息的页面,我们可以添加编译模式,来控制编译之后的启动页面,这样有利于提高开发效率:

    选择自己定义的编译模式:

     2、具体book详情页面的开发

    首先把详情页面的样式也页面的代码进行编写,这里就是没有按照顺序来整理出来代码,直接把完整的代码都拿出来吧

     首先是详情页面的wxml文件中静态页面代码:(这里不是完整的,下面的点评功能没有实现)

     1 <wxs src="../../util/filter.wxs" module="util"/>
     2 <view class="container">
     3   <!-- 头部信息 -->
     4   <view class="head">
     5     <image src="{{book.image}}"></image>
     6     <text class="title">{{book.title}}</text>
     7     <text class="author">{{book.author}}</text>
     8   </view>
     9   <!-- 短评 -->
    10   <view class="sub-container">
    11     <text class="headline">短评</text>
    12     <view class="comment-container">
    13       <block wx:for="{{util.limit(comments,10)}}" wx:key="">
    14         <v-tag tag-class="{{index==0?'ex-tag1':'' || index==1?'ex-tag2':''}}" text="{{item.content}}">
    15           <text class="num" slot="after">{{"+" + item.nums}}</text>
    16         </v-tag>
    17       </block>
    18     </view>
    19     <!-- 内容简介 -->
    20     <view class="sub-container">
    21       <text class="heading">内容简介</text>
    22       <text class="content" decode="{{true}}">{{util.format(book.summary)}}</text>
    23     </view>
    24   </view>
    25   <!-- 书籍出版信息 -->
    26   <view class="sub-container">
    27     <text class="heading">书籍信息</text>
    28     <view class="detail-container">
    29       <view class="vertical description">
    30         <text>出版社</text>
    31         <text>出版年</text>
    32         <text>页数</text>
    33         <text>定价</text>
    34         <text>装帧</text>
    35       </view>
    36       <view class="vertical">
    37         <text>{{book.publisher}}</text>
    38         <text>{{book.pubdate}}</text>
    39         <text>{{book.pages}}</text>
    40         <text>{{book.price}}</text>
    41         <text>{{book.binding}}</text>
    42       </view>
    43     </view>
    44   </view>
    45 </view>·

    接下来是wxss样式的代码:

      1 .container {
      2   background-color: #f5f5f5;
      3   width: 100%;
      4 }
      5 
      6 .head {
      7   background-color: #fff;
      8   padding-top: 40rpx;
      9   padding-bottom: 40rpx;
     10   display: flex;
     11   flex-direction: column;
     12   align-items: center;
     13 }
     14 
     15 .title {
     16   color: #2f2f2f;
     17   margin-top: 20rpx;
     18   font-size: 38rpx;
     19   font-weight: 600;
     20 }
     21 
     22 .author {
     23   font-size: 28rpx;
     24   color: #999;
     25 }
     26 
     27 .head image {
     28   width: 200rpx;
     29   height: 300rpx;
     30   box-shadow: 2px 2px 3px #e3e3e3;
     31 }
     32 
     33 .sub-container {
     34   width: 690rpx;
     35   display: flex;
     36   flex-direction: column;
     37   align-items: center;
     38   margin-top: 30rpx;
     39   background-color: #fff;
     40   padding: 30rpx;
     41 }
     42 
     43 .headline {
     44   font-size: 30rpx;
     45   font-weight: 600;
     46   color: #2f2f2f;
     47   margin-bottom: 20rpx;
     48 }
     49 
     50 .comment-container {
     51   display: flex;
     52   flex-direction: row;
     53   flex-wrap: wrap;
     54 }
     55 
     56 .comment-container v-tag {
     57   margin-right: 15rpx;
     58   margin-bottom: 10rpx;
     59 }
     60 
     61 .num {
     62   margin-left: 10rpx;
     63   font-size: 22rpx;
     64   color: #aaa;
     65 }
     66 
     67 .content{
     68   text-indent: 58rpx;
     69   font-weight: 500
     70 }
     71 
     72 /* 给标签前两个设置背景色 这种设置违背了组件的封装原则的*/
     73 
     74 /* 这里引入了小程序中的externalClasses来进行自定义组件的样式的设置 */
     75 
     76 /* .comment-container > v-tag:nth-child(1) > view{
     77   background-color: #fffbdd;
     78 }
     79 
     80 .comment-container > v-tag:nth-child(2) > view{
     81   background-color: #eefbff;
     82 } */
     83 
     84 /* !important 强制提高外部样式的权限 */
     85 
     86 .ex-tag1 {
     87   background-color: #fffbdd !important;
     88 }
     89 
     90 .ex-tag2 {
     91   background-color: #eefbff !important;
     92 }
     93 
     94 /* 书籍出版信息样式 */
     95 .detail-container{
     96   width: 100%;
     97   display: flex;
     98   flex-direction: row;
     99   justify-content: flex-start;
    100   margin-bottom: 100rpx;
    101   font-size: 28rpx;
    102   color: #666;
    103 }
    104 
    105 .vertical{
    106   display: flex;
    107   flex-direction: column;
    108 }
    109 
    110 .description{
    111   color: #999;
    112   margin-right: 30rpx;
    113 }

    最后是book详情页面的js代码:

     1 import {
     2   BookModel
     3 } from '../../models/book.js';
     4 
     5 // 实例化BookModel对象
     6 const bookModel = new BookModel();
     7 
     8 Page({
     9 
    10   /**
    11    * 页面的初始数据
    12    */
    13   data: {
    14     comments:[],
    15     book:null,
    16     likeStatus:false,
    17     likeCount:0
    18   },
    19 
    20   /**
    21    * 生命周期函数--监听页面加载
    22    */
    23   onLoad: function (options) {
    24     // 从外部页面传递过来的参数id
    25     const bid = options.bid;
    26     console.log(bid);
    27     const detail = bookModel.getDetail(bid);
    28     const comments = bookModel.getComments(bid);
    29     const likeStatus = bookModel.getLikeStatus(bid);
    30 
    31     // 利用promise的then的回调获取数据
    32     detail.then(res => {
    33       // console.log(res);
    34       this.setData({
    35         book:res
    36       })
    37     })
    38 
    39     comments.then(res => {
    40       // console.log(res);
    41       this.setData({
    42         comments:res.comments
    43       })
    44     })
    45 
    46     likeStatus.then(res =>{
    47       // console.log(res);
    48       this.setData({
    49         likeStatus:res.like_status,
    50         likeCount:res.fav_nums
    51       })
    52     })
    53 
    54   },

     3、小程序插槽slot

    这里的插槽很适合来做自定义组件的,这种用法非诚灵活,感觉真的有一种美妙的感觉-slot的官方介绍:

    https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/wxml-wxss.html#组件wxml的slot

    其实文档中已经写的很清楚了,但是还是看一下老师的讲解,毕竟在实战中引用才是最重要的,如何将理论的东西应用到实战中,是很值得思考的东西

    1 <view class="container">
    2   <slot name="before"></slot>
    3   <text>{{text}}</text>
    4   <!-- 微信小程序中的 插槽 slot -->
    5   <slot name="after"></slot>
    6 </view>

    这个其实就相当于占位符,我事先在这里占有一个位置,随时等待有人来占有这个地方,但是如果没人来占,对总体的布局也不会产生影响,有人的话,我就要把这个人给你们展示出来了,这个人就和组件中的其他的标签融为一体了,注意这里需要指定slot的name值,因为在page中是需要根据name值来找具体哪个slot的

    看page中如何插入到插槽中slot的:

    1   <view class="sub-container">
    2     <text class="headline">短评</text>
    3     <view class="comment-container">
    4       <block wx:for="{{comments}}" wx:key="">
    5         <v-tag text="{{item.content}}">
    6           <text class="num" slot="after">{{"+" + item.nums}}</text>
    7         </v-tag>
    8       </block>
    9     </view>

    这里是将text标签插入到插槽中,那么插槽中就会被一个text标签完全的占有了,你看到就是text标签中的内容了

    但是,这样的话,slot并不会生效,需要在配置一个参数,就是:

    1   options: {
    2     multipleSlots:true
    3   },

    这样的话,才能实现slot的功能

    4、小程序中的externalClasses

    这个是说的是小程序中的自定义组件如何来引入外部样式类,就是如何将page中的样式放入到自定义组件中,使其生效,小程序提供了externalClasses这个配置,可以应用这个设置来解决这个问题

    小程序中国的官方的介绍文档:https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/wxml-wxss.html#外部样式类

    还是来看一下这个东西是如何在实战中应用的:

    首先,看自定义组件中需要设置哪些地方:

     1 // 首先是需要设置 js中配置
     2   externalClasses:[
     3     'tag-class'
     4   ],
     5 
     6 // 其次是需要在页面中使用这个自定义class
     7 <!-- tag标签组件 短评以及搜索中的标签组件 -->
     8 <view class="container tag-class">
     9   <slot name="before"></slot>
    10   <text>{{text}}</text>
    11   <!-- 微信小程序中的 插槽 slot -->
    12   <slot name="after"></slot>
    13 </view>

    这样的话,我们就可以在使用自定义标签的时候来传递样式进去了

     1 // 这里面有一个样式的切换 第一个和第二个分别展示不同的背景色  
     2 <view class="sub-container">
     3     <text class="headline">短评</text>
     4     <view class="comment-container">
     5       <block wx:for="{{comments}}" wx:key="">
     6         <v-tag tag-class="{{index==0?'ex-tag1':'' || index==1?'ex-tag2':''}}" text="{{item.content}}">
     7           <text class="num" slot="after">{{"+" + item.nums}}</text>
     8         </v-tag>
     9       </block>
    10     </view>

    再来看一下ex-tag1与ex-tag2的样式设置

    1 .ex-tag1 {
    2   background-color: #fffbdd !important;
    3 }
    4 
    5 .ex-tag2 {
    6   background-color: #eefbff !important;
    7 }

    注意:!important 这里是提高该样式的重要性的,如果没有的话,虽然外部样式已经设置进去了,但是可能会被默认的样式覆盖的,这里为了强制覆盖默认样式而进行的设置

     5、小程序中的wxs

    这个文件的主要功能就是在wxml文件中可以调用外部的js代码,当然js代码是放在wxs文件中的,看看这个新的知识点是如何来实现的,官方文档:

    https://developers.weixin.qq.com/miniprogram/dev/reference/wxs/01wxs-module.html

     开始编写逻辑代码:

     1 // filter.wxs文件中代码 注意model.exports导出 var关键字 正则替换写法
     2 var format = function(text){
     3   if(!text){
     4     return
     5   }
     6   var reg = getRegExp('\\n','g');
     7   return text.replace(reg,'
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;');
     8 
     9 }
    10 
    11 module.exports = {
    12   format:format
    13 }
    14 
    15 // 页面中的引入代码
    16 <wxs src="../../util/filter.wxs" module="util"/>
    17 // 标签中使用
    18 <text class="content" decode="{{true}}">{{util.format(book.summary)}}</text>
    内容出处:七月老师《纯正商业级小程序开发》视频课程
  • 相关阅读:
    客户端通过spice-gtk实现USB重定向
    KVM通过qemu实现USB重定向
    Json
    《卓有成效的管理者》读书笔记
    《第五项修炼•实践篇》读书笔记
    《远大前程——从软件新手到行业大件》读书笔记
    目前常用的网站
    Objective-C内存管理
    Ubuntu修改屏幕默认亮度
    Ubuntu下安装eclipse及PyDev插件注意事项
  • 原文地址:https://www.cnblogs.com/ssh-html/p/11335687.html
Copyright © 2020-2023  润新知