从0开始写一个小程序

项目简介

从0开始写一个小程序,本来想写一个新闻类的程序,后来发现调用的聚合数据api每天只能访问100次,就换成豆瓣的了,直接用豆瓣的接口又访问不了,在网上查了一下,要把豆瓣的地址换成“http://t.yushu.im”才能访问,所以电影和图书用的豆瓣的接口,音乐用的是百度音乐的接口。主要分三个部分,一个是电影,一个是图书,一个是音乐。主要功能包括分享功能,电影主要包括列表和焦点图轮播,其他图书和音乐界面只包括列表,对于详情页,因为api数据问题,没有现成的接口做详情页,所以做了三个演示详情页,一个是演示怎么加载html格式的字符串,并且在界面上显示,一个是演示播放音乐,一个是演示播放电影。主要图片如下:

首页
这里写图片描述
这里写图片描述
这里写图片描述

项目搭建

首先新建一个小程序项目,基本上需要6个界面,可以在app.json文件中,写入需要创建的文件,点击保存,工具会自动将文件创建好,代码如下:

"pages":[
    "pages/index/index",
    "pages/lista/lista",
    "pages/listb/listb",
    "pages/view0/view0",
    "pages/view/view",
    "pages/view2/view2",
    "pages/logs/logs"
  ]

这样项目中就会创建出需要的文件,
这里写图片描述
然后搭建三个tab,分别是电影,图书,娱乐,tab的创建,可以查看小程序api中配置部分(https://mp.weixin.qq.com/debug/wxadoc/dev/framework/config.html),
这里写图片描述
这里写图片描述
另外,分享一个网页,可以在里边搜索一些icon,方便开发(http://www.iconfont.cn/),我在这个网上搜索了一些图片,作为tab的iconPath和selectedIconPath,在项目中创建一个image文件夹,将下载下来的文件放在文件夹中,如图:
这里写图片描述
在app.json中创建tab:

 "tabBar":{
    "color":"#8a8a8a",
    "selectedColor":"#d81e06",
    "list":[
      {
        "pagePath": "pages/index/index",
        "text": "电影",
        "iconPath": "image/listaD.png",
        "selectedIconPath": "image/listaS.png"
      },
      {
      "pagePath":"pages/lista/lista",
      "text":"图书",
      "iconPath":"image/indexD.png",
      "selectedIconPath":"image/indexS.png"
    },
    {
      "pagePath": "pages/listb/listb",
      "text": "音乐",
      "iconPath": "image/listbD.png",
      "selectedIconPath": "image/listbS.png"
    }]
  }

然后对navigationBar进行定制,也是在app.json中:

 "window":{
    "backgroundTextStyle":"light",
    "navigationBarBackgroundColor": "#000",
    "navigationBarTitleText": "电影",
    "navigationBarTextStyle":"white",
    "enablePullDownRefresh":true,
    "backgroundTextStyle":"dark"
  },

这里写图片描述
有一个属性:enablePullDownRefresh,这个设置为true可以开启下拉刷新功能,backgroundTextStyle设置下拉刷新时怎么显示。navigationBar可以在不同的界面进行定制,比如在图书模块,在图书模块的json中设置:

{
  "navigationBarTitleText": "图书"
}

在音乐模块的json中设置:

{
  "navigationBarTitleText": "音乐"
}

电影

现在开始写电影页面,这个主要包括三个功能,一个是焦点图轮播,一个是列表,包括列表拉到底部显示加载图标,加载数据,还有分享功能
首先是焦点图轮播,焦点图需要用到swiper,这个使用方法具体查看官方文档(https://mp.weixin.qq.com/debug/wxadoc/dev/component/swiper.html),
小程序开发,.wxml和.js文件进行通信,在.js中,通过data定义变量,如果要改变变量值,需要使用 setData方法来赋值,在wxml中,通过{{变量}}来调用,对于方法通信,在.wxml中,在控件中,通过bindtap=”方法名”定义,在js中,通过 方法名: function(e) {}来响应。对于界面样式,在wxml的控件中,定义class属性,在.wxss中,通过.class名来设置样式
1.设置焦点图:
在index.wxml中:

<swiper indicator-dots='{{indicatorDots}}' autoplay='{{autoplay}}' interval='{{interval}}' duration='{{duration}}' circular='{{circular}}'>
  <block wx:for='{{imageUrls}}'>
    <swiper-item>
      <navigator url='/pages/view0/view0'>
        <image src='{{item.images.large}}'></image>
      </navigator>
    </swiper-item>
  </block>
</swiper>

解释一下这段代码:
{{}}包括的是变量,可以在index.js中进行设置,wx:for是列表渲染,官方解释:

wx:for
在组件上使用 wx:for 控制属性绑定一个数组,即可使用数组中各项的数据重复渲染该组件。

默认数组的当前项的下标变量名默认为 index,数组当前项的变量名默认为 item

<view wx:for="{{array}}">
  {{index}}: {{item.message}}
</view>
Page({
  data: {
    array: [{
      message: 'foo',
    }, {
      message: 'bar'
    }]
  }
})
使用 wx:for-item 可以指定数组当前元素的变量名,

使用 wx:for-index 可以指定数组当前下标的变量名:

<view wx:for="{{array}}" wx:for-index="idx" wx:for-item="itemName">
  {{idx}}: {{itemName.message}}
</view>
wx:for 也可以嵌套,下边是一个九九乘法表

<view wx:for="{{[1, 2, 3, 4, 5, 6, 7, 8, 9]}}" wx:for-item="i">
  <view wx:for="{{[1, 2, 3, 4, 5, 6, 7, 8, 9]}}" wx:for-item="j">
    <view wx:if="{{i <= j}}">
      {{i}} * {{j}} = {{i * j}}
    </view>
  </view>
</view>
block wx:for
类似 block wx:if,也可以将 wx:for 用在<block/>标签上,以渲染一个包含多节点的结构块。例如:

<block wx:for="{{[1, 2, 3]}}">
  <view> {{index}}: </view>
  <view> {{item}} </view>
</block>

navigator是页面链接,就是点击一个控件,跳转到另一个页面,主要用法:
这里写图片描述
注意:url属性可以带一些值,比如:

<navigator url="/page/navigate/navigate?id=navigate" hover-class="navigator-hover">跳转到新页面</navigator>

跳转到新页面时,可以在console中查看到传入的值:

onLoad:function(e){
    // 页面初始化 options为页面跳转所带来的参数
    console.log(e.id)
    }

这一点很重要,因为有的时候,跳转到的页面,需要上一个页面的数据作为参数调用接口,设置值之类的操作,类似于安卓中的Intent
index.js中设置焦点图的对应的代码:

 //初始化数据
  data: {
    imageUrls:{},
    newsList:{},
    page:1,
    loading:false,
    indicatorDots: false,
    autoplay: true,
    interval: 5000,
    duration: 1000,
    circular:true
  },
  //加载时的操作
  onLoad: function () {
    console.log("加载时触发");
    var that = this;
    //顶部图片轮播调用的数据
    wx.request({
      url: 'http://t.yushu.im/v2/movie/in_theaters', 
      method:"GET",
      success: function (res) {
        that.setData({
          imageUrls: res.data.subjects
        })
      }
    })

首先定义一个变量,imageUrls,然后通过 wx.request调用数据,将获取的数据给imageUrls赋值,然后index.wxml中{{imageUrls}}就可以使用js中imageUrls的值了。

开始做列表功能,列表同样需要用到wx:for进行循环,将数据显示在界面上,对应代码:

<block wx:for='{{newsList}}'>
  <navigator class='listWrap' url='/pages/view0/view0'>
    <image class='listThumb' src='{{item.images.large}}'></image>
    <view class='listInfo'>
      <view class='listTitle'>{{item.original_title}}</view>
      <view class='listKeyAdd'>
        <text class='addFN'>{{item.year}}</text>
        <text class='addKY'>{{item.rating.average}}</text>
      </view>
    </view>
  </navigator>
</block>

注意:控件中的class,是为了对控件好进行操作,这里要对控件设置布局,在index.wxss中进行设置:


/*优化后的样式*/
swiper-item image {
  width:750rpx;
}
.listWrap {
  width:705rpx;
  padding:0 25rpx;
  padding:30rpx 25rpx;
  border-bottom:1px solid #e5e5e5;
}
.listThumb {
  width:260rpx;
  height:160rpx;
  display:block;
  float:left;
}
.listInfo {
  height:160rpx;
  width:435rpx;
  display:inline-block;
  padding-left:10rpx;
  position: relative;
}
.listTitle {
  color:#333;
  font-size:36rpx;
  font-weight:600;
}
.listKeyAdd {
  font-size:30rpx;
  position: absolute;
  bottom: 0;
  width:100%;
}
.addFN {
  color: #808080;
  display:block;
  float:left;
}
.addKY {
  color: #d9c599;
  float:right;
  display:block;
  margin-right:15rpx;
}

rpx单位是微信小程序中css的尺寸单位,rpx可以根据屏幕宽度进行自适应。规定屏幕宽为750rpx。如在 iPhone6 上,屏幕宽度为375px,共有750个物理像素,则750rpx = 375px = 750物理像素,1rpx = 0.
下拉列表,界面到达底部,有一个onReachBottom方法进行监听,可以在这个方法里,进行一些分页加载之类的操作
index.js中列表操作的代码:

 //列表调用的数据
    wx.request({
      url: 'http://t.yushu.im/v2/movie/top250',
      data: {
        start: that.data.page,
        count:10
      },
      method: "GET",
      success: function (res) {
        console.log(res)
        that.setData({
          newsList: res.data.subjects
        })
      }
    })

 /*页面上拉触底事件的处理函数 演示滑到底部加载新数据*/
  onReachBottom:function(e){
    var that = this
    that.setData({
      //界面滑到底部,页面加1
      page:++that.data.page,
      loading:true
    })
    console.log(that.data.page);
    wx.request({
      url: 'http://t.yushu.im/v2/movie/top250',
      data: {
        start: that.data.page,
        count: 10
      },
      method: "GET",
      success: function (res) {
        loading:false
        that.setData({
          //获取到数据,将新获取的数据加在原有数据的后边
          newsList: that.data.newsList.concat(res.data.subjects)
        })
      }
    })
  }

在原来数据基础上加上新的数据,需要通过concat方法

分享功能:
默认情况下,点击右上角的三点图标,会提示没有配置分享,如果要实现分享,需要通过onShareAppMessage方法,对应的使用说明(https://mp.weixin.qq.com/debug/wxadoc/dev/api/share.html),对应的代码:

 //分享
  onShareAppMessage: function (res) {
    return {
      title: "电影",
      path: "pages/index/index",
      success: function (res) {

        wx.showToast({
          title: "转发成功" + res.errMsg,
          icon: 'success',
          duration: 2000
        })
      },
      fail: function (res) {
        console.log(res);
        wx.showToast({
          title: "失败:" + res.errMsg,
          icon: 'none',
          duration: 2000
        })
      }
    }

显示瞬时提示,需要通过wx.showToast方法(https://mp.weixin.qq.com/debug/wxadoc/dev/api/api-react.html#wxshowtoastobject)。
在列表底部,需要一个加载的loading,具体设置:

<block wx:if="{{loading}}">
    <image class='loading' src='/image/loading.png'></image>
</block>

这个用到了wx:if,条件渲染(https://mp.weixin.qq.com/debug/wxadoc/dev/framework/view/wxml/conditional.html),在js中设置loading的值,控制loading图标是否显示,需要在wxss中设置样式

@-webkit-keyframes rotation{
from {-webkit-transform: rotate(0deg);}
to {-webkit-transform: rotate(360deg);}
}
.loading {
-webkit-transform: rotate(360deg);
animation: rotation 1.5s linear infinite;
-moz-animation: rotation 1.5s linear infinite;
-webkit-animation: rotation 1.5s linear infinite;
-o-animation: rotation 1.5s linear infinite;
width:60rpx;
height:60rpx;
display:block;
margin:10rpx auto;
}

index.js全部代码:

//index.js
//获取应用实例
const app = getApp()

Page({
  //初始化数据
  data: {
    imageUrls:{},
    newsList:{},
    page:1,
    loading:false,
    indicatorDots: false,
    autoplay: true,
    interval: 5000,
    duration: 1000,
    circular:true
  },
  //加载时的操作
  onLoad: function () {
    console.log("加载时触发");
    var that = this;
    //顶部图片轮播调用的数据
    wx.request({
      url: 'http://t.yushu.im/v2/movie/in_theaters', 
      method:"GET",
      success: function (res) {
        that.setData({
          imageUrls: res.data.subjects
        })
      }
    })
    //列表调用的数据
    wx.request({
      url: 'http://t.yushu.im/v2/movie/top250',
      data: {
        start: that.data.page,
        count:10
      },
      method: "GET",
      success: function (res) {
        console.log(res)
        that.setData({
          newsList: res.data.subjects
        })
      }
    })
  },
  //下拉刷新
  onPullDownRefresh: function () {
    this.onLoad();
  },
  /*页面上拉触底事件的处理函数 演示滑到底部加载新数据*/
  onReachBottom:function(e){
    var that = this
    that.setData({
      //界面滑到底部,页面加1
      page:++that.data.page,
      loading:true
    })
    console.log(that.data.page);
    wx.request({
      url: 'http://t.yushu.im/v2/movie/top250',
      data: {
        start: that.data.page,
        count: 10
      },
      method: "GET",
      success: function (res) {
        loading:false
        that.setData({
          //获取到数据,将新获取的数据加在原有数据的后边
          newsList: that.data.newsList.concat(res.data.subjects)
        })
      }
    })
  },
  //分享
  onShareAppMessage: function (res) {
    return {
      title: "电影",
      path: "pages/index/index",
      success: function (res) {

        wx.showToast({
          title: "转发成功" + res.errMsg,
          icon: 'success',
          duration: 2000
        })
      },
      fail: function (res) {
        console.log(res);
        wx.showToast({
          title: "失败:" + res.errMsg,
          icon: 'none',
          duration: 2000
        })
      }
    }
  }
})

index.wxml

<!--index.wxml-->
<swiper indicator-dots='{{indicatorDots}}' autoplay='{{autoplay}}' interval='{{interval}}' duration='{{duration}}' circular='{{circular}}'>
  <block wx:for='{{imageUrls}}'>
    <swiper-item>
      <navigator url='/pages/view0/view0'>
        <image src='{{item.images.large}}'></image>
      </navigator>
    </swiper-item>
  </block>
</swiper>

<block wx:for='{{newsList}}'>
  <navigator class='listWrap' url='/pages/view0/view0'>
    <image class='listThumb' src='{{item.images.large}}'></image>
    <view class='listInfo'>
      <view class='listTitle'>{{item.original_title}}</view>
      <view class='listKeyAdd'>
        <text class='addFN'>{{item.year}}</text>
        <text class='addKY'>{{item.rating.average}}</text>
      </view>
    </view>
  </navigator>
</block>

<block wx:if="{{loading}}">
    <image class='loading' src='/image/loading.png'></image>
</block>

index.wxss

/**index.wxss**/
.userinfo {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.userinfo-avatar {
  width: 128rpx;
  height: 128rpx;
  margin: 20rpx;
  border-radius: 50%;
}

.userinfo-nickname {
  color: #aaa;
}

.usermotto {
  margin-top: 200px;
}

/*优化后的样式*/
swiper-item image {
  width:750rpx;
}
.listWrap {
  width:705rpx;
  padding:0 25rpx;
  padding:30rpx 25rpx;
  border-bottom:1px solid #e5e5e5;
}
.listThumb {
  width:260rpx;
  height:160rpx;
  display:block;
  float:left;
}
.listInfo {
  height:160rpx;
  width:435rpx;
  display:inline-block;
  padding-left:10rpx;
  position: relative;
}
.listTitle {
  color:#333;
  font-size:36rpx;
  font-weight:600;
}
.listKeyAdd {
  font-size:30rpx;
  position: absolute;
  bottom: 0;
  width:100%;
}
.addFN {
  color: #808080;
  display:block;
  float:left;
}
.addKY {
  color: #d9c599;
  float:right;
  display:block;
  margin-right:15rpx;
}

@-webkit-keyframes rotation{
from {-webkit-transform: rotate(0deg);}
to {-webkit-transform: rotate(360deg);}
}
.loading {
-webkit-transform: rotate(360deg);
animation: rotation 1.5s linear infinite;
-moz-animation: rotation 1.5s linear infinite;
-webkit-animation: rotation 1.5s linear infinite;
-o-animation: rotation 1.5s linear infinite;
width:60rpx;
height:60rpx;
display:block;
margin:10rpx auto;
}

其他两个图书和音乐界面基本上和电影类似,就不写了

加载html 字符串

在做项目的时候,避免不了会用到富文本,也就是html格式的内容,而小程序默认是不支持html格式的内容显示的,需要显示html内容的时候,就可以通过wxParse来实现。
github地址:https://github.com/icindy/wxParse
将项目下载下来,打开本地小程序,将wxParse文件夹复制到小程序目录中,在view.js文件中引入:

var WxParse = require('../../wxParse/wxParse.js');

在view.wxss中:

@import "/wxParse/wxParse.wxss";

数据绑定:
/**
* WxParse.wxParse(bindName , type, data, target,imagePadding)
* 1.bindName绑定的数据名(必填)
* 2.type可以为html或者md(必填)
* 3.data为传入的具体数据(必填)
* 4.target为Page对象,一般为this(必填)
* 5.imagePadding为当图片自适应是左右的单一padding(默认为0,可选)
*/
在view.js中配置

Page({
  data: {
   htmlData:{}
  },
  onLoad: function () {
    console.log("加载时触发");
    var that = this;
    wx.request({
      url: 'http:\/\/mini.eastday.com\/mobile\/180320091535191.html',
      method: "GET",
      success: function (res) {
        console.log(res)
        that.setData({
          htmlData: WxParse.wxParse('htmlData', 'html', res.data, that, 5) 
        })
      }
    })
  },

在view.wxml中:

<!--pages/view/view.wxml-->
<import src="../../wxParse/wxParse.wxml"/> 
<template is="wxParse" data="{{wxParseData:htmlData.nodes}}"/>

注意:wxParseData:htmlData.nodes中的htmlData与view.js中的htmlData保持一致。
这样基本上就可以完成富文本的显示了

播放音乐

播放音乐,使用微信提供的audio(https://mp.weixin.qq.com/debug/wxadoc/dev/component/audio.html),
view2.js

// pages/view2/view2.js
Page({

  onReady: function (e) {
    // 使用 wx.createAudioContext 获取 audio 上下文 context
    this.audioCtx = wx.createAudioContext('myAudio')
  },
  data: {
    poster: 'http://oeff2vktt.bkt.clouddn.com/image/45.jpg',
    name: '刚好遇见你',
    author: '李玉刚',
    src: 'http://up.mcyt.net/?down/35760.mp3',
  },
  audioPlay: function () {
    this.audioCtx.play()
  },
  audioPause: function () {
    this.audioCtx.pause()
  },
  audio14: function () {
    this.audioCtx.seek(14)
  },
  audioStart: function () {
    this.audioCtx.seek(0)
  }
})

view2.wxml

<audio poster="{{poster}}" name="{{name}}" author="{{author}}" src="{{src}}" id="myAudio" controls loop></audio>

<button type="primary" bindtap="audioPlay">播放</button>
<button type="primary" bindtap="audioPause">暂停</button>
<button type="primary" bindtap="audio14">设置当前播放时间为14秒</button>
<button type="primary" bindtap="audioStart">回到开头</button>

播放视频

播放视频使用video(https://mp.weixin.qq.com/debug/wxadoc/dev/component/video.html)
view0.js

function getRandomColor() {
  let rgb = []
  for (let i = 0; i < 3; ++i) {
    let color = Math.floor(Math.random() * 256).toString(16)
    color = color.length == 1 ? '0' + color : color
    rgb.push(color)
  }
  return '#' + rgb.join('')
}

Page({
  onReady: function (res) {
    this.videoContext = wx.createVideoContext('myVideo')
  },
  inputValue: '',
  data: {
    src: '',
    danmuList: [
      {
        text: '第 1s 出现的弹幕',
        color: '#ff0000',
        time: 1
      },
      {
        text: '第 3s 出现的弹幕',
        color: '#ff00ff',
        time: 3
      }]
  },
  bindInputBlur: function (e) {
    this.inputValue = e.detail.value
  }
})

view0.wxml


<view class="section tc">
  <video id="myVideo" src="http://wxsnsdy.tc.qq.com/105/20210/snsdyvideodownload?filekey=30280201010421301f0201690402534804102ca905ce620b1241b726bc41dcff44e00204012882540400&bizid=1023&hy=SH&fileparam=302c020101042530230204136ffd93020457e3c4ff02024ef202031e8d7f02030f42400204045a320a0201000400" danmu-list="{{danmuList}}" enable-danmu danmu-btn controls></video>
</view>

项目源码:
https://download.csdn.net/download/jifashihan/10299954

  • 8
    点赞
  • 49
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值