小程序的豆瓣项目练习

小程序的豆瓣项目:

一. tabbar的布局实现

​ 需要创建 pages/welcome board list item search mine

​ 全局配置 —> tabBar

​ app.json里面进行了配置:

"tabBar":{  //配置底部的tab栏
    "color":"#ccc",  //默认的颜色
    "selectedColor":"#35495e",  //选中tabar的文字颜色
    "borderStyle":"white",      //tabbar的上边框线  white 默认是black
    "backgroundColor":"#f9f9f9", //tabbar的背景色
    "list":[ //数组 规定了2-5
      {
        "text": "榜单",  //tabbar的文字
        "pagePath":"pages/board/board", //tabbar的页面路径
        "iconPath":"images/board.png",  //tabbar的icon图标
        "selectedIconPath":"images/board-actived.png" //tabbar当前选中的图标
      },
      {
        "text": "搜索",
        "pagePath": "pages/search/search",
        "iconPath": "images/search.png",
        "selectedIconPath": "images/search-actived.png"
      },
      {
        "text": "我的",
        "pagePath": "pages/mine/mine",
        "iconPath": "images/mine.png",
        "selectedIconPath": "images/mine-actived.png"
      }
    ]
  }

window的配置:

"window": {
    "backgroundTextStyle": "light",
    "navigationBarBackgroundColor": "#35495e", //导航栏的背景
    "navigationBarTitleText": "豆瓣",  //全局的文字  例如welcome页面没有配置,就用全局
    "navigationBarTextStyle": "white" //文字的颜色  white/black
  },

二. 欢迎页面的实现

2-1 封装ajax请求 (https://www.cnblogs.com/e-cat/p/8656040.html)

​ utils/douban.js文件:

export default ({
  url,data={start:0,count:20},method='get'
})=>{
  return new Promise((resolve,reject)=>{
    //调用微信的请求数据的方法
    wx.request({
      url, 
      data,
      header: {
        'content-type': 'json' //请求头的content-type需要改!
      },
      method,
      success(res) {
        resolve(res)
      },
      fail(err){
        reject(err)
      }
    })
  })
}


//import douban from "XXXX"
/*
  douban({
    url:"https://douban.uieee.com/v2/movie/in_theaters",
    data:{
      start:0,
      count:3
    }
  }).then(res=>{
    console.log(res)
  })

 */

welcome/welcome.js文件:

  onLoad: function (options) {
    douban({
      url:"https://douban.uieee.com/v2/movie/in_theaters",
    }).then(res=>{
      console.log("res",res)
    })
  },

后续发现报错! 需要配置开发=》开发设置=》服务器域名=》request合法域名 (https://douban.uieee.com)

再去重新打开微信开发者工具,就可以正常访问接口了。 (详情=》本地设置=》不校验域名)

welcome/welcome.js文件:

import douban from "../../utils/douban.js"

data: {
	movies:[]
},

onLoad: function (options) {
    douban({
      url:"https://douban.uieee.com/v2/movie/in_theaters",
      data:{
        count:3
      }
    }).then(res=>{
      console.log("res",res)
      let result = [];
      res.data.subjects.map(item=>{
        result.push({
          id:item.id,
          image:item.images.large
        })
      })
      //进行数据的设置
      this.setData({
        movies:result
      })
    })
  },

welcome/welcome.wxml

需要在欢迎页面结构上面显示轮播图了!

<view class="container">
  <swiper class="welcome" indicator-dots indicator-color="#ccc">
      <block>
        <swiper-item
          class="swiper-item"
          wx:for="{{movies}}"
          wx:key="id"
        >
          <image class="slide-image" src="{{item.image}}"/>
          <button 
            wx:if="{{movies.length-1 === index}}" 
            class="start"
            bindtap="clickHandler"
          >立即体验</button>
        </swiper-item>
      </block>
    </swiper>
</view>

welcome/welcome.json:

{
  "navigationStyle":"custom",
  "usingComponents": {}
}

2-2 小程序的事件注意

小程序的事件绑定方式有两种:bind绑定(支持事件冒泡行为) catch绑定(非冒泡)

小程序的事件参数传递通过data-形式传递。

<text data-a='10' bindtap="clickme">pages/board/board.wxml</text>
clickme(event){
    console.log(event.target.dataset.a)
},

2-3 小程序的跳转

​ 1) wx.switchTab(Object object)

​ 跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面

wx.switchTab({
	url: '/pages/search/search',
})

​ 2)wx.reLaunch(Object object)

​ 关闭所有页面,打开应用内的某一个页面

 wx.reLaunch({
 	url: '/pages/list/list?id=1&name=zhangsan',
 })
onLoad: function (options) {
	console.log("list-id",options)
},

3)wx.redirectTo(Object object)

关闭当前页面,跳转到应用内的某个页面。但是不允许跳转到 tabbar 页面

wx.redirectTo({
	url:"/pages/list/list?id=1"
})

4)wx.navigateTo(Object object)

​ 保留当前页面,跳转到应用内的某个页面。但是不能跳到 tabbar 页面。使用 wx.navigateBack 可以返回到原页面。小程序中页面栈最多十层

wx.navigateTo({
	url: '/pages/list/list?id=1',
})

5)wx.navigateBack(Object object)

关闭当前页面,返回上一页面或多级页面。可通过 getCurrentPages 获取当前的页面栈,决定需要返回几层

// 注意:调用 navigateTo 跳转时,调用该方法的页面会被加入堆栈,
// 而 redirectTo 方法则不会。见下方示例代码

// 此处是A页面
wx.navigateTo({
  url: 'B?id=1'
})

// 此处是B页面
wx.navigateTo({
  url: 'C?id=1'
})

// 在C页面内 navigateBack,将返回A页面
wx.navigateBack({
  delta: 2  // A=>B=>C  现在从c直接到a,那么就写个2,默认是1,只能返回B
})

三. board的实现

3-1 borad的banner

​ app.js文件:

globalData: { 
    baseUrl:"https://douban.uieee.com/v2/movie/"
  }

​ utils/douban.js

let app = getApp();
wx.request({
      url:app.globalData.baseUrl+url, 
      ...
})

​ welcome/welcome.js

onLoad: function (options) {
    douban({
      url:"in_theaters",
      data:{
        count:3
      }
    }).....
})

​ board/board.js

data: {
    banner:{
      key:"coming_soon",
      title:"即将上映",
      content:[]  //[{id,image},{},{}]
    }
 },
 
 
 onLoad: async function (options) {
    let res = await douban({
      url:this.data.banner.key,
      data:{count:3}
    })
    //组装数据
    let result = []
    res.data.subjects.map(item=>{
      result.push({
        id:item.id,
        image:item.images.large
      })
    })
    //更改小程序data里面的content
    // this.setData({banner:{content:result}})
    this.setData({
      "banner.content":result
    })
  },

board/board.wxml

<view class="container">
  <view class="slide">
    <swiper circular indicator-dots>
      <swiper-item
        wx:for="{{banner.content}}"
        wx:key="id"
      >
        <image src="{{item.image}}"></image>
      </swiper-item>
    </swiper>
  </view>
</view>

board/board.wxss

小程序里面rpx适配

​ iphone6下:

​ 1css像素 ~ 2物理像素 ~ 2rpx

.container{
  display: flex;
  flex: 1;
  flex-direction: column;
  box-sizing: border-box;
}
.slide .swp{
  height:400rpx;
}
.slide .nav-img{
  width:100%;
  height:400rpx;
}

3-2 board的列表实现

board/board.js

data: {
    banner:{
      key:"coming_soon",
      title:"即将上映",
      content:[]  //[{id,image},{},{}]
    },
    list:[
      { key: "coming_soon", title: "即将上映" },
      { key: "top250", title: "排行榜" },
      { key: "in_theaters", title: "正在热映" }
    ]
  },

board/board.wxml

<view class="container">
  <view class="slide">
    <swiper circular indicator-dots class="swp">
     .....
    </swiper>
  </view>

  <view class="board">
    <view 
      class="board-item"
      wx:for="{{list}}"
      wx:key="key"
    >
      <text class="board-item-title">{{item.title}}</text>
      <image class="arrow" src="../../images/arrowright.png"></image>
    </view>
  </view>
</view>

board/board.wxss

.container{
  display: flex;
  flex: 1;
  flex-direction: column;
  box-sizing: border-box;
}
.slide .swp{
  height:400rpx;
}
.slide .nav-img{
  width:100%;
  height:400rpx;
}

//榜单列表的样式
.board-item{
  display: flex;
  border:1px solid #999;
  margin:40rpx;
  padding: 40rpx;
}
.board-item .board-item-title{
  flex:1
}

.board-item .arrow{
  width:40rpx;
  height:40rpx;
}

3-3 点击轮播图跳转到item

跳转方式:

小程序里面:

方式一. 编程式导航跳转 (wx.switchTab({url:“url地址”}))

方式二. 声明式导航跳转 ()

vue里面: ( this.$router.push(“url地址”) )

react里面: ( this.props.history(“url地址”)) )

​ 需要在banner的image上面嵌套navigator导航标签,url属性指明跳转目标路由。

<navigator open-type="navigate" url="{{'/pages/item/item?id='+item.id}}">
	<image class="nav-img" src="{{item.image}}"></image>
</navigator>

3-4 item详情页面的数据搭建

item/item.js

// pages/item/item.js
import douban from "../../utils/douban.js"
Page({

  /**
   * 页面的初始数据
   */
  data: {
    photos:[],  //电影详情剧照
    detail:"",  //电影的所有的信息
    title:''   //电影的标题
  },

  //点击剧照
  clickImage(){
    wx.previewImage({ //实现图片的预览
      urls: this.data.photos,  // Array<String>
    })
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {
    // wx.showNavigationBarLoading()
    // wx.showLoading({
    //   title: '加载中...',
    // })
    douban({
      url: "subject/" + options.id,
      loadingTop:true,//在导航栏上面显示loading
    }).then(res=>{
      let photos = []
      res.data.photos.map(item=>{
        photos.push(item.image)  
      })
      this.setData({
        photos,
        detail: res.data,
        title:res.data.title
      })
      //设置导航的标题
      wx.setNavigationBarTitle({
        title: this.data.title
      })
      //设置导航栏颜色
      wx.setNavigationBarColor({
        frontColor: '#ffffff',
        backgroundColor: '#f45332',
        animation: {
          duration: 400,
          timingFunc: 'easeIn'
        }
      })
      // wx.hideNavigationBarLoading()
      // wx.hideLoading()
    })
  },
})

utils/douban

let app = getApp(); 
export default ({
  url,data={start:0,count:20},method='get',loadingTop,loadingCenter 
})=>{
  return new Promise((resolve,reject)=>{
    //显示loading
    if(loadingTop){
      wx.showNavigationBarLoading() //显示导航loading
      wx.setNavigationBarTitle({    //设置导航title
        title: '加载中...',
      })
    }
    if(loadingCenter){
      wx.showLoading({
        title: '加载中...',
      })
    }

    //调用微信的请求数据的方法
    wx.request({
      ....
      complete(){   //不管请求成功还是请求失败,都会调用
        if(loadingTop) wx.hideNavigationBarLoading()
        if(loadingCenter) wx.hideLoading()
      }
    })
  })
}


//import douban from "XXXX"
/*
  douban({
    url:"https://douban.uieee.com/v2/movie/in_theaters",
    data:{
      start:0,
      count:3
    }
  }).then(res=>{
    console.log(res)
  })

 */

item/item.wxml

<view class="container">
  <!--注意!这边需要对于detail这个数据进行判断-->
  <block wx:if="{{detail.title}}">
    <image mode="aspectFill" class="background" src="{{detail.images.large}}"></image>
    <view class="meta"> 
      <image bindtap="clickImage" class="poster" src="{{photos[0]}}"></image>    
      <text class="title">{{title}}({{detail.year}})</text>
      <text class="info">评分:{{detail.rating.average || "暂无评分"}}</text>
      <text class="info">导演:<block wx:for="{{detail.directors}}" wx:key="id">{{item.name}} </block></text>
      <text class="info">主演:<block wx:for="{{detail.casts}}" wx:key="id">{{item.name}} </block></text> 
    </view>
    <view class="summary">
      <text class="label">摘要:</text>
      <text class="content">{{detail.summary}}</text>
    </view>
  </block>
  <view wx:else>
  	<image src="/images/loading.gif"></image>
  </view>
</view>

item/item.wxss

.background{
  position: fixed;
  left:0;
  top:0;
  width:100%;
  height:100%;
  z-index: -1;
  opacity: .1;
}

.meta{
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 50rpx 40rpx;
}
.meta .poster{
  width:100%;
  height:800rpx;
  margin:20rpx;
}
.title{
  font-size: 42rpx;
  color:#222;
}
.info{
  font-size: 28rpx;
  color:#444;
  margin-top: 18rpx;
}

.summary{
  width:90%;
  margin:0 auto;
}
.summary .label{
  display: block;
  font-size: 34rpx;
  margin-bottom: 20rpx;
}
.summary .content{
  font-size: 30rpx;
  color:#555;
  line-height: 60rpx;
}

3-4 点击榜单跳转list

board/board.wxml

<view class="board">
    <navigator
      wx:for="{{list}}"
      wx:key="key"
      url="{{'/pages/list/list?key='+item.key+'&title='+item.title}}"
    >
      <view class="board-item">
        <text class="board-item-title">{{item.title}}</text>
        <image class="arrow" src="../../images/arrowright.png"></image>
      </view>
    </navigator>
  </view>

list/list.js

onLoad: function (options) {
    console.log("list",options)  //{key:"",title:""}
},

四. list的实现

4-1 列表的展示

​ list/list.js

// pages/list/list.js
import douban from "../../utils/douban.js"
Page({
  /**
   * 页面的初始数据
   */
  data: {
    title:"",
    key:"",
    list:[]
  },

  update(){
    douban({
      url:this.data.key,
      loadingTop:true
    }).then(res=>{
      //整理数据
      let result = []
      res.data.subjects.map(item=>{
        result.push({
          id:item.id,  //电影的id
          image:item.images.small, //电影图片
          average:item.rating.average, //电影评分
          title:item.title,    //电影标题
          original_title: item.original_title, //电影英文标题
          year:item.year,   //电影年份
          directors:item.directors  //电影导演数组
        })
      })
      this.setData({
        list:result
      })
      //设置导航栏标题
      wx.setNavigationBarTitle({
        title: this.data.title,
      })
    })
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {
    let {title,key} = options;
    this.setData({
      title,
      key
    })
    //数据的渲染
    this.update();
  }
})

list/list.wxml

<view class="list">
  <block wx:for="{{list}}" wx:key="id">
    <view class="item">
      <image class="poster" src="{{item.image}}"></image>
      <view class="meta">
        <text class="title">{{item.title}}</text>
        <text class="sub-title">{{item.original_title}} ({{item.year}})</text>
        <view class="directors">导演:<block wx:for="{{item.directors}}" wx:key="id">{{item.name}}</block></view>
      </view>
      <view class="rating">{{item.average}}</view>
    </view>
  </block>
</view>

4-2 product组件实现

后续我们考虑到list里面的每一项如果很多地方都需要用到的话,我们将要进行拆分成自定义组件,进行复用。

/components/product/xxxx (component)

创建好了之后,必须要进行组件注册!(app.json进行全局注册 or page.json进行局部注册)

选择了app.json里面进行了全局注册,目的就是后续很多页面都可以使用到product组件。

"usingComponents": {
    "product":"/components/product/product"
 }

list/list.wxml里面调用product组件,发现Ok了

<block wx:for="{{list}}" wx:key="id">
    <!--使用自定义组件product-->
    <product/>
</block>

后续需要给product传递item这个对象,让其进行渲染

<view class="list">
  <block wx:for="{{list}}" wx:key="id">
    <!--使用自定义组件product,需要将item传递给它-->
    <product item="{{item}}"/>
  </block>
</view>

在product.js里面的properties中接收外部传入的item

properties: {
    item:{
      type:Object  //接受外部传入的item,并且是对象类型
    }
},

product.wxml里面进行数据的渲染操作

<view class="item">
  <image class="poster" src="{{item.image}}"></image>
  <view class="meta">
    <text class="title">{{item.title}}</text>
    <text class="sub-title">{{item.original_title}} ({{item.year}})</text>
    <view class="directors">导演:<block wx:for="{{item.directors}}" wx:key="id">{{item.name}}</block></view>
  </view>
  <view class="rating">{{item.average}}</view>
</view>


接下来点击product的时候,实现跳转到item页面

<view class="item" bindtap="clickHandler">
...
</view>
methods: {
    //点击product的时候跳转方法
    clickHandler(){
      wx.navigateTo({
        url: '/pages/item/item?id='+this.properties.item.id,
      })
    }
}

4-3 list页面开启下拉刷新

​ list/list.json

{
  "navigationBarTitleText": "",
  "enablePullDownRefresh":true,  //开启当前list页面的下拉刷新
  "backgroundTextStyle":"dark",  //下拉刷新的loading  light or dark
  "usingComponents": {}
}

​ list/list.js

  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh: function () {
    this.update()  //就是保证用户下拉的时候数据是最新的20条数据
  },

五. 云开发

5-1 初始云环境

​ -开发工具->创建云开发项目(选择云开发)

​ -填入appId字段

​ -开发工具->云开发->设置->创建环境->输入环境名称

​ -开发工具->右键点击项目cloundfunctions目录,切换你所创建的环境

​ -右键点击cloudfunctions/login云函数 -> 上传并部署 (为了将来小程序可以访问我们的云环境)

5-2 多云环境

​ 初始化云环境多次

​ 注意:目前免费的环境只支持两个,没有多个。 一个用来做测试,一个是正式环境

​ 多云环境的情况下需要指定env:

​ app.js

onLaunch: function () { //小程序初始化生命周期钩子
    if (!wx.cloud) {
      console.error('请使用 2.2.3 或以上的基础库以使用云能力')
    } else {
      wx.cloud.init({
        // env 参数说明:
        //   env 参数决定接下来小程序发起的云开发调用(wx.cloud.xxx)会默认请求到哪个云环境的资源
        //   此处请填入环境 ID, 环境 ID 可打开云控制台查看
        //   如不填则使用默认环境(第一个创建的环境)
        env: 'demo123-3o9h6',
        traceUser: true,
      })
    }

    this.globalData = {}
  }

5-3 数据库环境

创建集合

​ 开发工具->云开发->数据库->创建集合->权限设置(放大)

添加记录

​ 手动添加: 开发工具->云开发->数据库->添加记录

导入数据:
导入本地mongodb数据

​ 首先需要将mongodb的数据进行出库操作。

mongoexport -h 127.0.0.1 -d 数据库 -c 集合名 -o 输出路径/xx.json

​ 开发工具->云开发->数据库->douban->上传文件(home.json)

导入第三方的数据

​ 导入第三方的数据,需要安装json-view谷歌浏览器插件。

​ copy到vscode里面去,进行代码格式化,之后对象与对象之间","去掉。再去进行导入即可。

获取openid (前提将login部署上去)

​ app.js文件

let res = await wx.cloud.callFunction({ //调用云函数 
	name:"login"
})
console.log(res.result.openid)

数据库操作
增:
 const db = wx.cloud.database();
 
 add(){
    db.collection('douban')
      .add({
        data:{ //不能进行批量添加  使用云函数方式进行批量添加
          name: 'apple',
          category: 'fruit',
          price: 10,
        }
      }).then(res => {
        console.log("res",res)
      }).catch(err=>{
        console.log("err",err)
      })
  },
删:
  //删除操作
  remove(){
    db.collection('douban').doc('5e6ebf68efe8d765db7b66e6')
      .remove()
      .then(res => {
        console.log("res", res)
      }).catch(err => {
        console.log("err", err)
      })
  },
改:
db.collection('douban').doc('37e26adb5eb510d1004d4bee74d12799')
	  //.set({}) 替换更新 
      .update({  //局部更新  
        data: {
          // price: _.inc(10)
          name: 'milk',
          category: 'dairy'
        }
      }).then(res=>console.log(res))
      .catch(err=>console.log(err))
查:
find(){
    db.collection('douban')
      .where({  //查询条件
        price: _.gt(2)  //查询指令  价格大于2的
      })
      .field({  //显示的字段
        name: true,
        price: true,
      })
      .orderBy('price', 'desc')  //按照price进行降序排列
      // .skip(1)
      // .limit(10)
      .get()
      .then(res=>console.log(res))
      .catch(err=>console.log(err))
}
数据推送服务

​ A页面修改了集合,B页面事先监听了这个集合,就会收到更新后的数据,这个数据就是后端推送来的。

​ (websocket)

一旦douban的集合数据发生变化了,onChange函数就会执行,在这里面我们可以实现自己的业务逻辑。

   db.collection('douban').where({}).watch({
      onChange: (snapshot)=>{
        console.log(snapshot.docChanges)
      },
      onError:err=>{
        console.log(err)
      }
    })

5-4 云存储

​ 上传图片

//上传图片
  upload(){
    // 选择图片
    wx.chooseImage({
      count: 1,  //图片数量
      sizeType: ['compressed'],  //压缩图
      sourceType: ['album', 'camera'], //拍照  or  相册
      success:  (res)=> {
        wx.showLoading({
          title: '上传中',
        })
        const filePath = res.tempFilePaths[0]  //324324.png
        // 上传图片
        const cloudPath = 'my-image'+Date.now() + filePath.match(/\.[^.]+?$/)[0]
        wx.cloud.uploadFile({ //上传图片到云存储
          cloudPath,  //云存储路径
          filePath,   //本地图片路径
          success: res => {
            console.log('[上传文件] 成功:', res)
            this.setData({
              imgUrl:res.fileID
            })
          },
          fail: e => {
            console.error('[上传文件] 失败:', e)
            wx.showToast({
              icon: 'none',
              title: '上传失败',
            })
          },
          complete: () => {
            wx.hideLoading()
          }
        })
      },
      fail: e => {
        console.error(e)
      }
    })
  },

5-5 云函数(后端接口)

​ 创建云函数

​ 右键cloudfuncitons->新建node云函数->定义函数名->右键函数名->一旦更改了,必须重新上传并部署

// 云函数入口文件
const cloud = require('wx-server-sdk')
cloud.init()

// 云函数入口函数
//第一个参数就是用来接收传递的参数
//第二个参数context用来获取上下文的相关信息   context来获取openid等字段
exports.main = async (event, context) => {
  return {
    sum:event.a+event.b,
    reduce:event.a-event.b
  }
}

test/test.js

  //调用sum云函数
  sum(){
    wx.cloud.callFunction({
      // 需调用的云函数名
      name: 'sum',
      // 传给云函数的参数
      data: {
        a: 1,
        b: 2,
      },
    }).then(res=>{
      console.log(res.result.sum,res.result.reduce)
    })
  },

六. 使用云开发改装项目

6-1 创建云环境

​ 方案一. 创建云开发的模板环境,把之前的douban项目放入到此环境下。

​ 方案二. 在原有的douban项目基础上,融入云开发环境。

​ 1.project.config.js文件

"cloudfunctionRoot":"cloudfunctionRoot",

​ 根目录下面创建与其指明的文件夹。然后里面就会有你的云函数了,同时你也可以再此下面创建自己的一些云函数,一旦云函数进行了内容更改,你需要重新上传并部署。

​ 2.app.js文件

onLaunch(){
	//看一下当前环境是否支持云开发
    if (!wx.cloud) {
      console.error('请使用 2.2.3 或以上的基础库以使用云能力')
    } else {
      //初始化云开发环境,指明env  环境id
      wx.cloud.init({
        env: 'node-78c4ee',
        traceUser: true,
      })
    }

    let storage = wx.getStorageSync("douban_welcome")
    if(storage){
      wx.switchTab({
        url: '/pages/board/board',
      }) 
    }  
  },  
3.app.js 测试云函数login是否可用 (前提早就把login函数部署到云函数里面去了)
onLunch(){
	....
	//测试login云函数是否可用
     let res = await wx.cloud.callFunction({
       name:"login"
     })
     console.log("res====》",res)
}

6-2 改装welcome

welcome/welcome.js

//获取数据库对象
const db = wx.cloud.database() 
//获取集合in_theaters
const in_theaters = db.collection("in_theaters")

onLoad: async function (options) {
    //从云数据库里面取正在热映的数据
    let res = await in_theaters
      .where({})
      .limit(3)
      .get()
    let result = [];
    res.data.map(item=>{
      result.push({
        id:item.id,
        image:item.images.large
      })
    })
    this.setData({
      movies:result
    })
}

6-3 改装 board

 
 const db = wx.cloud.database()
 
 onLoad: async function (options) {
    let res = await db.collection(this.data.banner.key)
            .limit(3)
            .get()
    let result = []
    res.data.map(item=>{
      result.push({
        id:item.id,
        image:item.images.large
      })
    })
    this.setData({
      "banner.content":result
    })
 }

6-3 改装item

先把utils/douban.js文件进行了改版。

let app = getApp(); 
//获取数据库
let db = wx.cloud.database()

//根据数据库集合查询数据
//collectionName:集合名字
//id  电影的唯一id
//q   电影的名字
export default ({
  collectionName,id=null,data={start:0,count:20,q:null},method='get',loadingTop,loadingCenter 
})=>{
  return new Promise((resolve,reject)=>{
    //显示loading
    if(loadingTop){
      wx.showNavigationBarLoading()
      wx.setNavigationBarTitle({
        title: '加载中...',
      })
    }
    if(loadingCenter){
      wx.showLoading({
        title: '加载中...',
      })
    }

    //查询条件  id  q进行查询
    let where = {}
    let title = {
      $regex:'.*'+data.q, //包含data.q就可以
      $options:'i'        //忽略大小写
    }
    where = id ? {...where,id} : where 
    where = data.q ? {...where,title} : where

    //根据集合查询对应的数据
    db.collection(collectionName)
      .where(where)  //查询条件 
      .skip(data.start * data.count)  // 0 * 20
      .limit(data.count)              // 20 
      .get(
        {
          success(res) {
            resolve(res)
          },
          fail(err){
            reject(err)
          },
          complete(){
            if(loadingTop) wx.hideNavigationBarLoading()
            if(loadingCenter) wx.hideLoading()
          }
        }
      )
  })
}

item/item.js文件

在onload里面我们需要一个collectionName,因为要按照集合进行查询。

所以 board/board.wxml

<swiper circular indicator-dots class="swp">
      <swiper-item
        wx:for="{{banner.content}}"
        wx:key="id"
      > 
        <navigator open-type="navigate" url="{{'/pages/item/item?id='+item.id+'&collectionName='+banner.key}}">
          <image class="nav-img" src="{{item.image}}"></image>
        </navigator>
      </swiper-item>
    </swiper>
onLoad: function (options) {
    let {id,collectionName} = options;
    douban({
      collectionName,
      id,
      loadingTop:true
    }).then(res=>{
      //通过where条件查找数据,返回的是一个数组
      let detail = res.data[0]
      let photos = []
      detail.casts.map(item=>{
        //如果item.avatars存在,再给photos数组添加大图
        if(item.avatars){
          photos.push(item.avatars.large)
        }
      })
      this.setData({
        photos,
        detail,
        title:detail.title
      })
      //设置导航的标题
      wx.setNavigationBarTitle({
        title: this.data.title
      })
    })  
}

6-4 改装list

list/list.js

update(){
    douban({
      collectionName:this.data.key,
      loadingTop: true
    }).then(res=>{
      let result = []
      res.data.map(item=>{
        result.push({
          id:item.id,  //电影的id
          image:item.images.small, //电影图片
          average:item.rating.average, //电影评分
          title:item.title,    //电影标题
          original_title: item.original_title, //电影英文标题
          year:item.year,   //电影年份
          directors:item.directors  //电影导演数组
        })
      })
      this.setData({
        list:result
      })
      //设置导航栏标题
      wx.setNavigationBarTitle({
        title: this.data.title,
      })

      //需要停止下拉刷新
      wx.stopPullDownRefresh()
    })
  },

在product组件点击跳转到item详情页面,会报错!原因是因为详情页面需要接受id、collectionName

所以我们需要将这两个字段传递给item

list.wxml

<view class="list">
  <block wx:for="{{list}}" wx:key="id">
    <product item="{{item}}" collectionName="{{key}}"/> 
  </block>
</view>

product.js

properties: {
    item:{
      type:Object  //接受外部传入的item,并且是对象类型
    },
    collectionName:{
      type:String
    }
  },
  
methods: { 
    //点击product的时候跳转方法
    clickHandler(){
      wx.navigateTo({
        url: '/pages/item/item?id='+this.properties.item.id+"&collectionName="+this.properties.collectionName,
      })
    }
  }

6-5 实现搜索search页面

<view class="container">
  <view class="header">
    <input
      class="search"
      placeholder="{{subtitle}}" 
      value="{{search}}"
      bindchange="handlerSearch"
      placeholder-class="search-placeholder"
    ></input>
  </view>
  <view class="list">
    <product
      wx:for="{{list}}"
      wx:key="id"
      collectionName="top250"
      item="{{item}}" 
    />
  </view>
  
  <!--调用load-more组件-->
  <load-more loading="{{loading}}" isLoadMore="{{isLoadMore}}"></load-more>
</view>

search/search.js

import douban from "../../utils/douban.js"
Page({

  /**
   * 页面的初始数据
   */
  data: {
    subtitle:"请输入查询内容",
    search:null,//默认查询内容为空
    list:[],
    start:0,
    count:6,
    loading:false,//默认没有加载
    isLoadMore:false //解决开始的时候显示的没有更多数据问题
  },

  //搜索方法(焦点失去的时候)
  handlerSearch(e){
    if(!e.detail.value.trim()){ //如果用户没有输入内容
      this.setData({
        list:[],
        start:0,
        search:null,
        isLoadMore:false
      })
      return;
    }
    this.setData({
      list:[],//每次搜索新内容的时候,都需要清空列表数组
      start:0,
      isLoadMore:true,
      search:e.detail.value //输入的搜索的值
    })
    this.loadList()
  },

  //加载数据
  async loadList(){
    //修改loading状态
    this.setData({loading:true})
    let res = await douban({
      collectionName: "top250", 
      data:{
        start: this.data.start, //0
        count: this.data.count, //6
        q:this.data.search    //相当于从0-20条数据里面取title包含’的’电影
      }
    })
    let result = []
    res.data.map(item => {
      result.push({
        id: item.id,  //电影的id
        image: item.images.small, //电影图片
        average: item.rating.average, //电影评分
        title: item.title,    //电影标题
        original_title: item.original_title, //电影英文标题
        year: item.year,   //电影年份
        directors: item.directors  //电影导演数组
      })
    }) 
    this.setData({
      list: this.data.list.concat(result),
      loading:false //修改了loading状态
    })
  },

  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom: function () {
    this.setData({
      isLoadMore:true, 
      start:++this.data.start
    })
    this.loadList() 
  },
})

后续封装了load-more组件

{
  "navigationStyle":"custom",
  "navigationBarTitleText": "搜索",
  "usingComponents": {
    "load-more":"/components/load-more/load-more"
  }
}

load-more/load-more组件需要接受外部传入的属性

properties: {
    loading:{
      type:Boolean
    },
    isLoadMore:{
      type:Boolean
    }
},
<view class="tips" wx:if="{{isLoadMore}}">
  <view wx:if="{{loading}}">
    <image class="image" src="/images/loading.gif"></image>
    <text class="text">玩命加载...</text>
  </view>
  <view wx:else>
    <text class="text">————没有更多数据...————</text>
  </view>
</view>

七. 小程序多端框架uniapp

​ uniapp taro wepy mpvue kbone

uniapp:

​ vue语法,跨端开发 (H5、小程序、app) 支持打包app(原生app) 如果熟悉vue的话,非常推荐学习uniapp

开发规范:

​ vue语法规范 + uni内置组件 + uni.api() + uni的一些ui库 + flex等布局

通过 HBuilderX 可视化界面

可视化的方式比较简单,HBuilderX内置相关环境,开箱即用,无需配置nodejs。

开始之前,开发者需先下载安装如下工具:

HBuilderX是通用的前端开发工具,但为uni-app做了特别强化。

下载App开发版,可开箱即用;如下载标准版,在运行或发行uni-app时,会提示安装uni-app插件,插件下载完成后方可使用。

如使用cli方式创建项目,可直接下载标准版,因为uni-app编译插件被安装到项目下了。

uni-app自带的模板有 Hello uni-app ,是官方的组件和API示例。还有一个重要模板是 uni ui项目模板,日常开发推荐使用该模板,已内置大量常用组件。

img

运行uni-app

  1. 浏览器运行:进入hello-uniapp项目,点击工具栏的运行 -> 运行到浏览器 -> 选择浏览器,即可在浏览器里面体验uni-app 的 H5 版。

    img

  2. 真机运行:连接手机,开启USB调试,进入hello-uniapp项目,点击工具栏的运行 -> 真机运行 -> 选择运行的设备,即可在该设备里面体验uni-app。

    img

    如手机无法识别,请点击菜单运行-运行到手机或模拟器-真机运行常见故障排查指南。 注意目前开发App也需要安装微信开发者工具。

  3. 在微信开发者工具里运行:进入hello-uniapp项目,点击工具栏的运行 -> 运行到小程序模拟器 -> 微信开发者工具,即可在微信开发者工具里面体验uni-app。

    img

    **注意:**如果是第一次使用,需要先配置小程序ide的相关路径,才能运行成功。如下图,需在输入框输入微信开发者工具的安装路径。 若HBuilderX不能正常启动微信开发者工具,需要开发者手动启动,然后将uni-app生成小程序工程的路径拷贝到微信开发者工具里面,在HBuilderX里面开发,在微信开发者工具里面就可看到实时的效果。

    uni-app默认把项目编译到根目录的unpackage目录。

    img

    注意: 微信开发者工具=》安全设置=》服务端口开启

  4. 在支付宝小程序开发者工具里运行:进入hello-uniapp项目,点击工具栏的运行 -> 运行到小程序模拟器 -> 支付宝小程序开发者工具,即可在支付宝小程序开发者工具里面体验uni-app。

    img

  5. 在百度开发者工具里运行:进入hello-uniapp项目,点击工具栏的运行 -> 运行到小程序模拟器 -> 百度开发者工具,即可在百度开发者工具里面体验uni-app。

    img

  6. 在字节跳动开发者工具里运行:进入hello-uniapp项目,点击工具栏的运行 -> 运行到小程序模拟器 -> 字节跳动开发者工具,即可在字节跳动开发者工具里面体验uni-app。

    img

  7. 在QQ小程序开发工具里运行:内容同上,不再重复。

manifest.json文件里面配置

​ 基础配置:填入Dcloud AppId 需要登录获取

​ 图标Logo配置 UI 设计 1024*1024 png图片

​ H5配置: 路由模式选择history /

​ 微信小程序配置: 填入原生AppID

项目打包

发行H5: 选择网站=》H5手机版

img

发行小程序:小程序开发者工具=》上传=》提交审核

发行App:保证hbx是最新版 云端打包

打包的时候会生成unpackge目录

dist/build 所有的打包后的资源

H5:打包后的H5的资源

app-plus:打包后的本地资源

项目结构

uni项目目录或者文件属性对应原生小程序文件
App.vueapp.wxss | app.js
manifest.json(打包配置文件)
pages/index/index.vuepages/index/index.wxss|wxml|js
static(静态资源 video/images)
uni.scss(全局样式变量)
main.js(Vue初始化入口文件)
pages.json(配置页面路由、导航条、选项卡等页面类信息)globalStyleapp.json里面的window项
pages.json(配置页面路由、导航条、选项卡等页面类信息)style对应着每个页面page.json文件

项目中如果使用vuex的话:

store/index.js

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
    state: {},
    mutations: {},
    actions: {}
})
export default store

main.js文件

import Vue from 'vue'
import App from './App'
//引入vuex
import store from './store'
//把vuex定义成全局组件
Vue.prototype.$store = store

Vue.config.productionTip = false
App.mpType = 'app'
const app = new Vue({
    ...App,
	 store
})
app.$mount()

index/index.vue文件

onLoad() {
	console.log(this.$store)
}

后续如果想使用ui库,uni强烈推荐使用 uni-ui组件库,创建项目的时候,就需要勾选ui组件库

uni-ui的链接:https://github.com/dcloudio/uni-ui

<template>
	<view class="container">
		<view class="intro">本项目已包含uni ui组件,无需import和注册,可直接使用。在代码区键入字母u,即可通过代码助手列出所有可用组件。光标置于组件名称处按F1,即可查看组件文档。</view>
		<text class="intro">详见:</text>
		<uni-link :href="href" :text="href"></uni-link>
		
		<uni-title title="上报统计数据"></uni-title>
		<uni-title type="h1" title="h1 一级标题 "></uni-title>
		<uni-title type="h1" title="h1 一级标题" color="#027fff"></uni-title>
		<uni-title type="h2" title="h2 居中" align="center"></uni-title>
		
		
		<!-- 一般用法 -->
		<uni-grid :column="3">
		    <uni-grid-item>
		        <text class="text">文本</text>
		    </uni-grid-item>
		    <uni-grid-item>
		        <text class="text">文本</text>
		    </uni-grid-item>
		    <uni-grid-item>
		        <text class="text">文本</text>
		    </uni-grid-item>
		</uni-grid>
		
		<!-- 不带边框并矩形显示 -->
		<uni-grid :column="3" :show-border="false"  :square="false">
		    <uni-grid-item>
		        <text class="text">文本</text>
		    </uni-grid-item>
		    <uni-grid-item>
		        <text class="text">文本</text>
		    </uni-grid-item>
		    <uni-grid-item>
		        <text class="text">文本</text>
		    </uni-grid-item>
		    <uni-grid-item>
		        <text class="text">文本</text>
		    </uni-grid-item>
		    <uni-grid-item>
		        <text class="text">文本</text>
		    </uni-grid-item>
		    <uni-grid-item>
		        <text class="text">文本</text>
		    </uni-grid-item>
		</uni-grid>
	</view>
</template>

<script>
	export default {
		data() {
			return {
				href: 'https://uniapp.dcloud.io/component/README?id=uniui'
			}
		},
		methods: {

		}
	}
</script>

<style>
	.container {
		padding: 20px;
		font-size: 14px;
		line-height: 24px;
	}
</style>

项目改装

1.静态资源&全局样式

​ images ==> static

​ 云函数我还是采用小程序的云函数,没用uni自己的云函数,这样运行只能在小程序里面运行是Ok的

​ app.wxss==>app.vue的style里面

2. 修改pages.json文件

​ window ===> globalStyle

​ style =====> 每个页面的page.json

​ tabbar ===> 注意iconPath or selectedIconPath的图片路径(/static/images/)

3. App.vue文件
export default {
		async onLaunch(){
		  if (!wx.cloud) {
		    console.error('请使用 2.2.3 或以上的基础库以使用云能力')
		  } else {
		    wx.cloud.init({
		      env: 'node-78c4ee',
		      traceUser: true,
		    })
		  }
		
		  //测试login云函数是否可用
		  // let res = await wx.cloud.callFunction({
		  //   name:"login",
		  // })
		  // console.log("res====》",res)
		  let storage = uni.getStorageSync("douban_welcome")
		  if(storage){
		    uni.switchTab({
		      url: '/pages/board/board',
		    }) 
		  }  
		}
	} 

我们还是采用了wx.cloud 没有使用unicloud ? 因为unicloud必须创建uni自己的云开发。

4.更改welcome欢迎页面
<template>
	<view class="container">
	  <swiper class="welcome" indicator-dots indicator-color="#ccc">
	        <swiper-item
	          class="swiper-item"
			  v-for="(item,index) in movies"
	          :key="item.id"
	        >
	          <image class="slide-image" :src="item.image"/>
	          <button 
	            v-if="movies.length-1 === index" 
	            class="start"
	            @tap="clickHandler"
	          >立即体验</button>
	        </swiper-item>
	    </swiper>
	</view>
</template>

<script>
	const db = wx.cloud.database()
	const in_theaters = db.collection("in_theaters")
	export default {
		data() {
			return {
				movies: []
			}
		},
		methods: {
			//点击立即体验
			clickHandler(){
			  uni.switchTab({
			    url: '/pages/board/board'
			  })
			  //写入storage
			  uni.setStorageSync("douban_welcome", true)
			}
		},
		onLoad: async function (options) {
		  //从云数据库里面取正在热映的数据
		  let res = await in_theaters
		    .where({})
		    .limit(3)
		    .get()
		  let result = [];
		  res.data.map(item=>{
		    result.push({
		      id:item.id,
		      image:item.images.large
		    })
		  })
		  // this.setData({
		  //   movies:result
		  // })
		  this.movies = result
		},
	}
</script>

<style scoped>
.container{
  height:100%;
}
.welcome{
  height:100%;
}
.welcome .swiper-item{
  height:100%;
}
.swiper-item .slide-image{
  width: 100%;
  height: 100%;
}

.start{
  position: absolute;
  bottom: 100px;
  left:50%;
  width:150px;
  transform: translateX(-75px);
  font-size: 20px;
}
</style>

5.更改board页面

<template>
	<view class="container">
	  <view class="slide"> 
	    <swiper circular indicator-dots class="swp">
	      <swiper-item
	        v-for="item,index of banner.content"
	        :key="item.id"
	      > 
	        <navigator open-type="navigate" :url="'/pages/item/item?id='+item.id+'&collectionName='+banner.key">
	          <image class="nav-img" :src="item.image"></image>
	        </navigator>
	      </swiper-item>
	    </swiper>
	  </view> 
	
	  <view class="board">
	    <navigator
	      v-for="(item,index) in list"
	      :key="key"
	      :url="'/pages/list/list?key='+item.key+'&title='+item.title"
	    >
	      <view class="board-item">
	        <text class="board-item-title">{{item.title}}</text>
	        <image class="arrow" src="/static/images/arrowright.png"></image>
	      </view>
	    </navigator>
	  </view>
	</view>
</template>

<script>
	const db = wx.cloud.database()
	export default {
		data() {
			return {
				banner:{  //上面轮播图的数据
				  key:"coming_soon",
				  title:"即将上映",
				  content:[]  //[{id,image},{},{}]
				},
				list:[
				  { key: "coming_soon", title: "即将上映" },
				  { key: "top250", title: "排行榜" },
				  { key: "in_theaters", title: "正在热映" }
				]
			}
		},
		onLoad: async function (options) {
		  let res = await db.collection(this.banner.key)
		          .limit(3)
		          .get()
		  let result = []
		  res.data.map(item=>{
		    result.push({
		      id:item.id,
		      image:item.images.large
		    })
		  })
		  // this.setData({
		  //   "banner.content":result
		  // })
		  this.banner.content = result;
		}
	}
</script>

<style scoped>
.container{
  display: flex;
  flex: 1;
  flex-direction: column;
  box-sizing: border-box;
}
.slide .swp{
  height:400rpx;
}
.slide .nav-img{
  width:100%;
  height:400rpx;
}

.board-item{
  display: flex;
  border:1px solid #999;
  margin:40rpx;
  padding: 40rpx;
}
.board-item .board-item-title{
  flex:1
}

.board-item .arrow{
  width:40rpx;
  height:40rpx;
}
</style>

6. 更改item页面
let app = getApp(); 
let db = wx.cloud.database()

//根据数据库集合查询数据
//collectionName:集合名字
//id  电影的唯一id
//q   电影的名字
export default ({
  collectionName,id=null,data={start:0,count:20,q:null},method='get',loadingTop,loadingCenter 
})=>{
  return new Promise((resolve,reject)=>{
    //显示loading
    if(loadingTop){
      uni.showNavigationBarLoading()
      uni.setNavigationBarTitle({
        title: '加载中...',
      })
    }
    if(loadingCenter){
      uni.showLoading({
        title: '加载中...',
      })
    }

    //查询条件  id  q进行查询
    let where = {}
    let title = {
      $regex:'.*'+data.q, //包含data.q就可以
      $options:'i'        //忽略大小写
    }
    where = id ? {...where,id} : where 
    where = data.q ? {...where,title} : where

    //根据集合查询对应的数据
    db.collection(collectionName)
      .where(where)  //查询条件 
      .skip(data.start * data.count) 
      .limit(data.count)
      .get(
        {
          success(res) {
            resolve(res)
          },
          fail(err){
            reject(err)
          },
          complete(){
            if(loadingTop) uni.hideNavigationBarLoading()
            if(loadingCenter) uni.hideLoading()
          }
        }
      )
  })
}
<template>
	<view class="container">
	  <block v-if="detail.title">
	    <image mode="aspectFill" class="background" :src="detail.images.large"></image>
	    <view class="meta"> 
	      <image @tap="clickImage" class="poster" :src="photos[0]"></image>    
	      <text class="title">{{title}}({{detail.year}})</text>
	      <text class="info">评分:{{detail.rating.average || "暂无评分"}}</text>
	      <text class="info">导演:<block v-for="item in detail.directors" :key="item.id">{{item.name}} </block></text>
	      <text class="info">主演:<block v-for="item of detail.casts" :key="item.id">{{item.name}} </block></text> 
	    </view>
	    <view class="summary">
	      <text class="label">摘要:</text>
	      <text class="content">{{detail.summary}}</text>
	    </view>
	  </block>
	  <view v-else>
	    <image src="/static/images/loading.gif"></image>
	  </view>
	</view>
</template>

<script>
	import douban from "../../utils/douban.js"
	export default {
		data() {
			return {
				photos:[],  //电影详情剧照
				detail:"",  //电影的所有的信息
				title:''   //电影的标题
			}
		},
		methods: {
			//点击剧照
			clickImage(){
			  uni.previewImage({
			    urls: this.photos,
			  })
			},
		},
		onLoad: function (options) {
		  let {id,collectionName} = options;
		  douban({
		    collectionName,
		    id,
		    loadingTop:true
		  }).then(res=>{
		    //通过where条件查找数据,返回的是一个数组
		    let detail = res.data[0]
		    let photos = []
		    detail.casts.map(item=>{
		      //如果item.avatars存在,再给photos数组添加大图
		      if(item.avatars){
		        photos.push(item.avatars.large)
		      }
		    })
			this.photos = photos
			this.detail = detail
			this.title = detail.title
		    //设置导航的标题
		    uni.setNavigationBarTitle({
		      title: this.title
		    })
		  })  
		}
	}
</script>

<style scoped>
.background{
  position: fixed;
  left:0;
  top:0;
  width:100%;
  height:100%;
  z-index: -1;
  opacity: .1;
}

.meta{
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 50rpx 40rpx;
}
.meta .poster{
  width:100%;
  height:800rpx;
  margin:20rpx;
}
.title{
  font-size: 42rpx;
  color:#222;
}
.info{
  font-size: 28rpx;
  color:#444;
  margin-top: 18rpx;
}

.summary{
  width:90%;
  margin:0 auto;
}
.summary .label{
  display: block;
  font-size: 34rpx;
  margin-bottom: 20rpx;
}
.summary .content{
  font-size: 30rpx;
  color:#555;
  line-height: 60rpx;
}
</style>

7.更改list页面
<template>
	<view class="list">
	  <block v-for="item in list" :key="item.id">
	    <!--使用自定义组件product,需要将item传递给它-->
	    <!-- <product :item="item" :collectionName="key"/> -->
		<view>1111111</view>
	  </block>
	</view>
</template>

<script>
	import douban from "../../utils/douban.js"
	export default {
		data() {
			return {
				title:"",
				key:"",
				list:[]
			}
		},
		methods: {
			update(){
			  douban({
			    collectionName:this.key,
			    loadingTop: true
			  }).then(res=>{
			    let result = []
			    res.data.map(item=>{
			      result.push({
			        id:item.id,  //电影的id
			        image:item.images.small, //电影图片
			        average:item.rating.average, //电影评分
			        title:item.title,    //电影标题
			        original_title: item.original_title, //电影英文标题
			        year:item.year,   //电影年份
			        directors:item.directors  //电影导演数组
			      })
			    })
				this.list = result
			    //设置导航栏标题
			    uni.setNavigationBarTitle({
			      title: this.title,
			    })
			
			    //需要停止下拉刷新
			    uni.stopPullDownRefresh()
			  })
			}
		},
		onLoad: function (options) {
		  let {title,key} = options;
		  this.title = title
		  this.key = key
		  //数据的渲染
		  this.update();
		},
		onPullDownRefresh: function () {
		  this.update()
		}
	}
</script>

创建product组件 (components/product/product.vue)

<template>
	<view class="item" @tap="clickHandler">
	  <image class="poster" :src="item.image"></image>
	  <view class="meta">
	    <text class="title">{{item.title}}</text>
	    <text class="sub-title">{{item.original_title}} ({{item.year}})</text>
	    <view class="directors">导演:<block v-for="ite in item.directors" :key="ite.id">{{ite.name}}</block></view>
	  </view>
	  <view class="rating">{{item.average}}</view>
	</view>
</template>

<script>
	export default {
		//需要将小程序的properties更改成vue的props,来接受外部传入的属性,并且进行验证
		props: {
		  item:{
		    type:Object  //接受外部传入的item,并且是对象类型
		  },
		  collectionName:{
		    type:String
		  }
		},
		methods:{
			clickHandler(){
			  //获取props里面的数据,直接通过this获取即可。
			  uni.navigateTo({
			    url: '/pages/item/item?id='+this.item.id+"&collectionName="+this.collectionName,
			  })
			}
		}
	}
</script>

<style lang="scss">
.item{
  display: flex;
  padding: 20rpx 40rpx;
  border-bottom: 1px solid #ccc;
}
.item .meta{
  flex: 1;
}
.item .poster{
  width:128rpx;
  height:168rpx;
  margin-right:20rpx;
}

.item .title{
  font-size: 26rpx;
}
.item .title,.item .sub-title{
  display: block;
  margin-bottom: 15rpx;
}
.item .sub-title{
  width: 340rpx;
  text-overflow: ellipsis;
  white-space: nowrap;
  overflow: hidden;
}

.item .rating{
  display: inline-block;
  width: 40rpx;
  height:40rpx;
  font-size: 28rpx;
  font-weight: bold;
  background: #f00;
  color: #fff;
  padding: 10rpx;
  border-radius: 20rpx;
}
</style>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

别来…无恙

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

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

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

打赏作者

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

抵扣说明:

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

余额充值