微信小程序入门之旅-第六天-自定义组件及request的使用-制作电影页面


前文
微信小程序学习之旅–第一个页面的制作
微信小程序学习之旅–零基础制作自己的小程序–第二个页面的制作
微信小程序学习之旅–完善pages页面–字体图标,数据绑定,条件/列表渲染,事件/catch/bind以及路由的学习
微信小程序学习之旅–零基础制作自己的小程序-完成文章详情页–自定义属性/页面通信/缓存机制/异步API/async/await
微信小程序学习之旅–零基础制作自己的小程序-文章详情页音乐播放功能的实现-背景音频/全局App/页面的bug修改和优化

微信小程序入门(六)-自定义组件

完善文章轮播图

轮播图文章跳转

前面我们的轮播图只能简单的动起来。

现在打算实现点击轮播图上的图片,跳转到对应的文章详情页去。只要在图片上绑定文章的id号即可。用到的函数还是我们之前用来进行文章详情页跳转的函数。

image-20210830155819318

image-20210830155923444

生成tabBar选项卡

配置生成

小程序提供的有tabBar的选项卡。我们只需要在app.json中配置这个选项,即可生成。

"tabBar": {
    "list": [
      {
          // tabbar的标题 
        "text": "阅读",
          // 点击这个bar后去往的页面路径(必填)
        "pagePath": "pages/posts/posts"
      },
      {
        "text": "电影",
        "pagePath": "pages/movies/movies"
      }
    ]
  }

image-20210830161307756

image-20210830161329755

tabBar的其他配置

image-20210830162513452

"tabBar": {
    // 设置边框线的颜色为白色 这样舒服点
    "borderStyle": "white",
    // bar的位置 可以在顶端
    "position": "bottom",
    // bar未选中时文字的颜色
    "color": "#999",
    // 选中当前bar,文字的颜色
    "selectedColor": "#333",
    "list": [
      {
        "text": "阅读",
        "pagePath": "pages/posts/posts",
          // 未选中时的图标
        "iconPath": "/images/tab/yuedu.png",
          // 选中时的图标
        "selectedIconPath": "/images/tab/yuedu_hl.png"
      },
      {
        "text": "电影",
        "pagePath": "pages/movies/movies",
        "iconPath": "/images/tab/dianying.png",
        "selectedIconPath": "/images/tab/dianying_hl.png"
      }
    ]
  }

image-20210830162740174

页面跳转

如果想要让一个普通页面,跳转到一个带有bar选项卡的页面,我们之前的逻辑是不行的了。

image-20210830162924013

回顾一下,之前我们在这的跳转方式是点击按钮,进行页面的重定向,跳转到文章页面。

image-20210830163045023

这种方式现在是不能满足我们的要求了。

switchTab方法的使用

使用switchTab方法,就可以从普通页面跳转到选项卡页面。

image-20210830163310415

自定义组件

要说精髓,小程序的精髓应该就是在自定义组件这里了。

做一个自己的自定义组件

新建一个自定义组件

image-20210830165112837

右键点击post文件夹,然后点新建Component,就可以建好自定义组件的文件了。

一般来说,我们习惯性的让自定义组件的文件名都是index。

这里我们就先做一个文章的自定义组件,重构一下之前的那个文章页面。

注册自定义组件

很明显,就跟我们前面使用第三方的自定义组件库一样,使用组件之前都是需要进行自定义的。

image-20210830165856693

组件的自定义属性
常规写法

在我们组件的js文件的properties属性上,我们可以进行自定义属性的注册。到时候使用组件的时候就可以给该属性赋值,就和使用image标签的时候,给src属性赋值类似的操作。

/**
   * 组件的属性列表
   */
  properties: {
    // 自定义一个属性 属性名称
    text: {
      // 属性值的类型
      type: String,
      // 属性的默认值
      value: "我是默认值"
    }
  }

image-20210830170751026

如果不给属性赋值,那么就是我们定义好的该属性的默认值

image-20210830170935499

简写(语法糖)

很多时候,我们觉得上面那种定义属性的方式比较麻烦。那么可以采取下面这种方式。在没有默认值的情况下很适用。

**这种方式定义的属性,如果属性没有传参,那么默认值就是当前属性的类型的默认值。**比如Number的默认值是0。String的默认值是空字符串

/**
   * 组件的属性列表
   */
  properties: {
    // 自定义一个属性 属性名称 类型
    text: String
  }

以前,普通的页面只有data里面的变量才能做数据绑定(setData定义的数据最后也会出现在data里面),但是,在自定义组件里,组件的属性properties和data里面出现的变量,都可以进行数据绑定。

自定义属性可以接收一个Object对象

image-20210830171959559

前面,我们进行文章列表的遍历,来渲染整个文章页面(除去轮播图)。

我们可以发现,每篇文章的结构实际上都是相同的。唯一不同的,只是数据而已。

所以我们可以考虑用自定义组件来代替这个文章的结构,将结构隐藏到组件中,使页面看起来更加清爽,而且还可以达到复用的效果。

封装文章组件结构/样式

我们将文章的结构和样式,都直接封装到这个自定义组件里面。

结构

结构还会进行二次更改。

<!--components/post/index.wxml-->

<view data-post-id="{{item.postId}}" class="post-container" bind:tap="onGoToDetail">
  <!-- 第一部分 作者 日期 -->
  <view class="post-author-date">
    <!-- 头像 -->
    <image class="post-author" src="{{item.avatar}}"></image>
    <text class="post-date">{{item.date}}</text>
  </view>
  <!-- 第二部分 文章标题 -->
  <text class="post-title" user-select="true">{{item.title}}</text>
  <!-- 第三部分 -->
  <image class="post-image" src="{{item.imgSrc}}"></image>
  <!-- 第四部分 文章内容 -->
  <!-- user-select 方便用户复制 -->
  <text class="post-content">{{item.content}}</text>
  <!-- 第五部分 -->
  <view class="post-like">
    <l-icon color="#666" size="28" name="favor" class="post-like-image" />
    <text class="post-like-font">{{item.collection}}</text>
    <l-icon color="#666" size="32" name="eye" class="post-like-image" />
    <text class="post-like-font">{{item.reading}}</text>
  </view>
</view>
样式
/* components/post/index.wxss */

/* 文章样式 */
.post-container {
  /* 弹性布局 */
  display: flex;
  flex-direction: column;
  margin-top: 20rpx;
  margin-bottom: 40rpx;
  background-color: #fff;
  /* 上下边框线 */
  border-top: 1rpx solid #ededed;
  border-bottom: 1rpx solid #ededed;
  padding-bottom: 10rpx;
}

/* 作者 日期样式 */
.post-author-date {
  margin: 10rpx 0 20rpx 10rpx;
  display: flex;
  flex-direction: row;
  /* flex 布局居中方案 */
  align-items: center;
}

.post-author {
  width: 60rpx;
  height: 60rpx;
  /* 头像和文字居中 */
  /* vertical-align: middle; */

}

.post-date {
  margin-left: 20rpx;
  font-size:26rpx;
  /* vertical-align: middle; */
}

/* 文章标题 */
.post-title{
  font-size:34rpx;
  font-weight: 700;
  margin-bottom: 20rpx;
  margin-left: 20rpx;
  color:#333;
}
/* 文章主图 */
.post-image{
  width: 100%;
  height: 340rpx;
  margin-bottom: 30rpx;
}
/* 文章内容 */
.post-content{
  color:#666;
  font-size: 28rpx;
  margin-bottom: 20rpx;
  margin-left: 10rpx;
  margin-right: 10rpx;
  line-height: 40rpx;
  letter-spacing: 2rpx;
  text-indent: 2em;
}
/* 文章模拟阅读量 */
.post-like{
  display: flex;
  flex-direction: row;
  margin-left: 26rpx;
  align-items: center;
}
.post-like-image{
  /* height: 32rpx;
  width: 32rpx; */
  margin-right: 16rpx;
}
.post-like-font{
  margin-right: 40rpx;
  font-size: 26rpx;
}
自定义属性:Object类型

很明显,我们一篇文章会用到很多数据,所有使用文本进行传递是不可靠的。

这里采用传递文章对象,这个对象里面包含所有的当前文章的信息。

那么我们就需要定义一个属性,且该属性的类型是对象类型。

/**
   * 组件的属性列表
   */
  properties: {
    // 自定义一个属性 属性名称
    postData:Object
  },
组件结构调整

将进行数据绑定的地方进行修改。

<!--components/post/index.wxml-->

<view data-post-id="{{postData.postId}}" class="post-container" bind:tap="onGoToDetail">
  <!-- 第一部分 作者 日期 -->
  <view class="post-author-date">
    <!-- 头像 -->
    <image class="post-author" src="{{postData.avatar}}"></image>
    <text class="post-date">{{postData.date}}</text>
  </view>
  <!-- 第二部分 文章标题 -->
  <text class="post-title" user-select="true">{{postData.title}}</text>
  <!-- 第三部分 -->
  <image class="post-image" src="{{postData.imgSrc}}"></image>
  <!-- 第四部分 文章内容 -->
  <!-- user-select 方便用户复制 -->
  <text class="post-content">{{postData.content}}</text>
  <!-- 第五部分 -->
  <view class="post-like">
    <l-icon color="#666" size="28" name="favor" class="post-like-image" />
    <text class="post-like-font">{{postData.collection}}</text>
    <l-icon color="#666" size="32" name="eye" class="post-like-image" />
    <text class="post-like-font">{{postData.reading}}</text>
  </view>
</view>
使用文章自定义组件
<block wx:for="{{posts}}" wx:key="postId" wx:for-item="post">
    <post post-data="{{post}}"></post>
  </block>

image-20210830174933350

可以看见,文章被成功的渲染出来了。

自定义组件的事件

这里,我们简单的把当时进行点击文章,调整到对应的文章详情页的方法代码,抽离到自定义组件中。

组件使用到的放到,都需要在methods属性里面进行定义。

image-20210830175752019

自定义组件-movie-list

这里将自定义一个展示电影列表的自定义组件。

image-20210830202641102

image-20210830180105559

组件建立好了以后就在电影页面movies里面进行组件的注册。

image-20210830180350540

测试:发现正常引入

image-20210830180548725

组件的嵌套

我们可以发现,每个电影实际上也是结构相同,只是数据不同而已。所以我们可以把电影也抽成一个组件。

电影组件-movie

image-20210830181255465

组件的制作

我们前面说过,开发页面的时候,可以先用假数据模拟,然后等静态页面制作好了以后,再将假数据替换为我们实际从服务器请求的数据。

组件的开发也是一样,先用假数据,然后在替换为实际使用组件时,外界传递进来的数据。

在movie-list组件内部,我们会使用 movie组件,那么这就构成了组件之间的相互嵌套。

组件嵌套的使用
注册

在movie-list组件内组成movie组件

image-20210830181601571

使用movie组件

在组件内部使用其他组件,也是和普通标签一样使用。

image-20210830181747226

movie组件的制作
静态模板的制作

这一步,比较简单,没什么好说的。

<!--components/movie/index.wxml-->
<!-- 电影容器 -->
<view class="container">
  <!-- 电影海报 -->
  <image class="poster" src="/images/img1.jpg"></image>
  <!-- 电影标题 -->
  <text class="title">小米手机哈哈哈哈哈哈哈</text>
</view>
静态模板的css
/* components/movie/index.wxss */

/* 容器 */
.container {
  display: flex;
  width: 200rpx;
  flex-direction: column;
}

/* 电影海报 */
.poster {
  width: 100%;
  height: 270rpx;
  margin-bottom: 22rpx;
}

/* 标题 */
.title {
  /* 标题字数过长 多出的隐藏 */
  white-space: nowrap;
  text-overflow: ellipsis;
  overflow: hidden;
  word-break: break-all;
}
静态模板效果

image-20210830204133639

使用lin-ui的评分组件

这个评分的组件,我们自己制作的话是比较麻烦的,所以直接使用第三方提供好的。(如果想要自己实现其实也不是很难,只实现整数性质的平分还是比较容易的。

l-rate评分组件的注册

image-20210830204453700

使用l-rate继续完成movie组件

image-20210830210043421

<view class="rate-container">
    <!-- 评分 -->
    <!-- score属性 显示点亮多少星星 可以是小数 -->
    <!-- 星星的大小 size 进行设置 -->
    <!-- 使用count属性可以修改星星的数量(默认是五个星) -->
    <!-- 设置禁用点击 disabled="true" -->
    <!-- 使用active-color属性 可以修改点亮的星星的颜色 -->
    <!-- 使用 inActive-color 属性 可以修改未选中的星星颜色 -->
    <l-rate disabled="{{true}}" score="3.6" size="22" />
    <!-- 显示评分 -->
    <text class="score">3.6</text>
  </view>
/* 评分容器 */
.rate-container{
  margin-top: 6rpx;
  display: flex;
  flex-direction: row;
  /* 基线对齐 */
  align-items: baseline;
}
.score{
  margin-left: 16rpx;
  font-size: 24rpx;
}
movie-list组件的制作

通过开始的图片我们看见了,一个movie-list组件里面是有三个电影组件的。

所以接下来我们要利用制作好的movie组件来制作我们的movie-list组件了。

<!--components/movie-list/index.wxml-->

<view class="container">
  <view class="title-container">
    <text>正在热映</text>
    <text class="more-text">更多 ></text>
  </view>
  <!-- 组件的嵌套 -->
  <view class="movie-container">
    <movie />
    <movie />
    <movie />
  </view>
</view>
/* components/movie-list/index.wxss */
/* 组件容器 */
.container {
  padding: 36rpx 28rpx;
}

/* 标题容器 */
.title-container {
  display: flex;
  flex-direction: row;
  /* 主轴排列方式 两端对齐*/
  justify-content: space-between;
  margin-bottom: 26rpx;
}
.more-text{
  color:#1f4ba5;
}

/* 海报组件容器 */
.movie-container {
  display: flex;
  flex-direction: row;
  justify-content: space-between;
}

静态的制作都是挺简单的,先用死数据,制作好样式,后期在替换就完事。

image-20210830212121035

使用多个movie-list组件

效果看起来也还可以。但是样式还需要进行调整。

image-20210830212302788

设置组件的样式

我们在使用movie-list组件的时候,感觉这个样式并不完美,想要给这个组件加一些样式,但是,遇见了一些问题,就是给这个组件设置的样式都不生效。

image-20210830213440059

直接用组件的名称设置样式,或者给组件添加class类名设置样式,都不生效。

这是为什么呢?

解决movie-list样式不生效

想要解决样式不生效的问题,我们这里需要使用组件的外部样式类

之所以使用外部样式,是因为我们使用的组件,并不知道我们实际上会设置什么样式,所以定义好类名交给我们外部进行设置,到时候通过外部样式的入口进行传递给组件引用,完成样式的设置。

外部样式类的使用也比较简单。

image-20210830215344883

很明显,可以看见第一个设置外部样式的颜色发生了改变。

image-20210830215541605

这种直接给自定义组件设置样式不生效的问题,是由小程序内部的机制引起的。这时候我们就需要考虑使用外部样式类了。

movie-list组件的优化
动态标题

前面我们将所有的数据都是按照死数据来定死的。实际上这肯定是不合理的。这里进行标题的动态赋值。

我们在组件的js文件中设置这个属性。让外界动态的传参。

image-20210830220442697

/**
   * 组件的属性列表
   */
  properties: {
    title:String
  },

image-20210830220715789

小程序请求服务端数据

发起请求wx.request方法

常规用法,请求地址加上回调函数

// 请求服务器数据 获取正在热映的电影
    wx.request({
      // 请求地址
      url: 'url',
      // 请求方式 默认就是get请求
      method:"GET",
      success(res){
        console.log(res);
      }
    })
获取请求数据
// 别忘了获取全局app
const app = getApp()
/**
   * 页面的初始数据
   */
  data: {
    // 正在热映的电影数据
    inTheaters:[],
    // 即将上映的电影数据
    comingSoon:[],
    // top250
    top250:[]
  },
/**
   * 生命周期函数--监听页面加载
   */
  onLoad(options) {
    // 请求服务器数据 获取正在热映的电影
    wx.request({
      // 请求地址
      url: app.gBaseUrl+'in_theaters',
      method: "GET",
      // 参数 在get请求中为查询字符串
      data: {
        // 电影的起始索引
        start: 0,
        // 电影的总条数
        count: 3
      },
      success:(res) =>{ // 使用箭头函数解决this指向问题
        // 电影数据
        console.log(res.data.subjects);
        this.setData({
          inTheaters:res.data.subjects
        })
      }
    });

    // 即将上映的数据
    wx.request({
      // 请求地址
      url: app.gBaseUrl+'coming_soon',
      method: "GET",
      data: {
        start: 0,
        count: 3
      },
      success:(res) =>{ 
        // console.log(res);
        this.setData({
          comingSoon:res.data.subjects
        })
      }
    });
    // top250
    wx.request({
      // 请求地址
      url: app.gBaseUrl+'top250',
      method: "GET",
      data: {
        start: 0,
        count: 3
      },
      success:(res) =>{ 
        this.setData({
          top250:res.data.subjects
        })
      }
    })

  },
将数据绑定到movie-list组件
<!--pages/movies/movies.wxml-->

<movie-list movies="{{inTheaters}}" title="正在热映" l-class="movie-list" />
<movie-list movies="{{comingSoon}}" title="正在上映" l-class="movie-list" />
<movie-list movies="{{top250}}" title="豆瓣Top250" l-class="movie-list" />
movie-list组件数据的替换

现在,数据已经传递进来了,我们要做的就是动态替换实际的电影列表数据,并将每个电影的数据传递给电影组件

image-20210831083904536

movie组件的数据替换

接下来将movie组件的死数据替换为真实数据即可。

image-20210831084105206

效果

image-20210831084148756

有些图片加载不出来,和星星显示有误很正常,毕竟不是我们自己写的服务端数据。肯定会出现数据图片等有问题的错误。

下一篇

微信小程序一星期入门-完结篇–电影详情页的制作

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

尤雨东

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值