taro开发微信小程序

在京东凹凸实验室开发Taro跨平台早期之前,就已经进行Taro尝鲜了。开发这个实例猫眼电影已经过去几个月了。案例部分使用的是猫眼电影真实线上接口,关于订座的座位数据是自己模拟实现的,案例只供参考学习。

开发环境

操作系统:Window 10  
Taro版本:v0.0.69
Node版本:v8.11.1

运行效果

image

目录分析

src是主要的开发目录,各个文件实现功能如下所示:

├─.idea
│  └─libraries
├─.temp
├─config
└─src
    ├─assets
    │  └─images
    ├─components (公用组件)
    │  ├─Brandbar
    │  ├─Selectbar
    │  ├─Specialbar
    │  └─Toptab
    └─pages
    |    ├─cinema(影院列表)
    |    ├─cinemaDetail(影院详情页)
    |    ├─content(电影介绍)
    |    ├─detail(电影详情页)
    |    ├─map(影院地图定位页)
    |    ├─movies(电影列表页)
    |    ├─order(电影票订单页)
    |    ├─person(用户登录页)
    |    ├─position(地理位置选择页)
    |    ├─search(电影/影院搜索页)
    |    ├─seat(影院座位页)
    |    └─user(用户中心)
    |__app.js(入口配置文件)
    |__app.scss
    |__index.html

入口配置文件app.js分析

Movies列表页是微信小程序的首页,下面代码中config配置的是小程序中所有使用的页面定义路由。下面重点介绍几个比较重要的关键点微信小程序页。

import Taro, { Component } from "@tarojs/taro";
import Movies from "./pages/movies/movies";
import "./app.scss";
class App extends Component {
  config = {
    //访问路由文件定义
    pages: [
      "pages/movies/movies",
      "pages/person/person",
      "pages/cinema/cinema",
      "pages/position/position",
      "pages/search/search",
      "pages/detail/detail",
      "pages/content/content",
      "pages/cinemaDetail/cinemaDetail",
      "pages/map/map",
      "pages/seat/seat",
      "pages/user/user",
      "pages/order/order"
    ],
    //小程序顶部设置
    window: {
      backgroundTextStyle: "light",
      navigationBarBackgroundColor: "#e54847",
      navigationBarTitleText: "猫眼电影",
      navigationBarTextStyle: "white",
      enablePullDownRefresh: true
    },
    //底部tab导航栏配置
    tabBar: {
      color: "#333",
      selectedColor: "#f03d37",
      backgroundColor: "#fff",
      borderStyle: "black",
      list: [
        {
          pagePath: "pages/movies/movies",
          text: "电影",
          iconPath: "./assets/images/index.png",
          selectedIconPath: "./assets/images/index_focus.png"
        },
        {
          pagePath: "pages/cinema/cinema",
          text: "影院",
          iconPath: "./assets/images/themeOld.png",
          selectedIconPath: "./assets/images/theme.png"
        },
        {
          pagePath: "pages/person/person",
          text: "我的",
          iconPath: "./assets/images/person.png",
          selectedIconPath: "./assets/images/personSelect.png"
        }
      ]
    }
  };
  render() {
    // Movies小程序入口文件
    return <Movies />;
  }
}

Taro.render(<App />, document.getElementById("app"));

Movies电影列表页

getCities()是获取当前定位的城市的路由,因为在猫眼电影小程序抓包中没有抓取到获取当前定位的地址接口,所以在猫眼电影H5端获取到了所有城市的数据。之前用了easyMock模拟数据接口,现在不能使用了。不过现在在微信小程序的云开发,可以把数据模拟上去。其中TopTab是正在热映和即将上映的两个分类总的组件。

// movies页
export default class Movies extends Component {
  config = {
    navigationBarTitleText: "猫眼电影"
  };
  constructor(props) {
    super(props);
  }
  componentDidMount() {
    this.getCities();
  }
  getCities() {
    Taro.request({
      url:
        "https://www.easy-mock.com/mock/5ba0a7f92e49497b37162e32/example_copy/cities_copy_1541385673090",
      method: "GET",
      header: {
        Accept: "application/json, */*",
        "Content-Type": "application/json"
      }
    }).then(res => {
      if (res.statusCode == 200) {
        let data = res.data.data.data.data;
        Taro.setStorageSync("cities", data);
      }
    });
  }
  render() {
    return (
      <View className="movies">
        <Toptab />
      </View>
    );
  }
}

Toptab分类页

其中即将上映和正在热映,做了一个tab组件主要重点的代码是:


 <View className="tabItemContent" hidden={this.state.currentNavtab === 0?false:true}>
 <!-- 正在热映情况-->
 </View>
 <View className="tabItemContent" hidden={this.state.currentNavtab === 1?false:true}>
 <!--即将上映情况-->
 </View>

其中currentNavTab控制即将上映和正在热映的section显隐,hidden是taro官方案例提供的推荐实现tab标签组件的方式。使用其他方法亦可。该页主要实现电影列表的影评价和推荐指数,价格等。微信小程序中基本所有接口都依赖于cityId,也就是在movies页获取定位地址。下面getMoviesOnList是获取真实线上猫眼电影的接口,需要伪造请求header

getMoviesOnList(){
    let cityId = this.state.id
    Taro.showLoading({
      title:"加载中"
    });
    Taro.request({
      url:"https://m.maoyan.com/ajax/movieOnInfoList?token=",
      method:"GET",
      header:{
        "Cookie":`_lxsdk_cuid=164b6cae2cac8-02b7b032f571b5-39614706-1fa400-164b6cae2cbc8; v=3; iuuid=1A6E888B4A4B29B16FBA1299108DBE9CA19FF6972813B39CA13A8D9705187374; revrev=76338a29; _lx_utm=utm_source%3DBaidu%26utm_medium%3Dorganic; webp=true; __mta=3463951.1532075108184.1533098338076.1533118040602.20; _lxsdk=1A6E888B4A4B29B16FBA1299108DBE9CA19FF6972813B39CA13A8D9705187374; from=canary; selectci=true; __mta=3463951.1532075108184.1533118040602.1533118773295.21; _lxsdk_s=164f4f4c9e9-45e-d1b-46%7C%7C50; ci=${cityId}`
      }
    }).then(res=>{
      if(res.statusCode == 200){
        Taro.hideLoading();
        res.data.movieList.forEach((value)=>{
          let arr = value["img"].split("w.h");
          value["img"] = arr[0]+"128.180"+  arr[1]
        });
        this.setState({
          onList:res.data.movieList,
          startIndex:res.data.movieList.length,
          lastIndex:res.data.total -1,
          movieIds:res.data.movieIds
        });
      }else{
        this.setState({
          onList:null,
          movieIds:null
        })
      }
    })
  }

seat(影院座位页)

自己模拟实现了一个推荐座位与选座功能。为了实现座位信息选择,使用了二维数组对座位信息已选和未选,其中0代表该处拥有座位、E代表该处为空。其中数组的行代表了影院的第几排,嵌套的数组的索引代表了第几列。

[
    [0,0,0,0,0,0],
    [E,0,0,E,0,0],
    [0,0,0,0,0,0],
    [E,0,0,E,0,0]
]

初始化座位信息,https://m.maoyan.com/ajax/seatingPlan?timestamp=${Date.now()}获取猫眼电影线上座位信息接口,cityId是当前定位城市ID,ci是影院ID。initParams是获取线上座位信息接口,seatData是获取到的影院座位信息,需要对座位信息做进一步的加工。遍历座位信息,如果字段st为N,则arr设置为0(代表具有座位并未选),为E则为该处不具有座位。

 initParams(){
    const params = this.$router.params;
    const self = this;
    Taro.setNavigationBarTitle({
      title:params.cinemaName
    })
    Taro.showLoading({
      title:"加载中..."
    });
    Taro.request({
      url:`https://m.maoyan.com/ajax/seatingPlan?timestamp=${Date.now()}`,
      method:'post',
      header:{
        'Cookie': 'uuid_n_v=v1; iuuid=26F6BA50506A11E9A973FDD3C7EBDF0E29C7297EC72D4F77A53F9445EF0EE9F3; webp=true; ci=20%2C%E5%B9%BF%E5%B7%9E; _lxsdk_cuid=169be42cf28c8-098c7e821e63bd-2d604637-3d10d-169be42cf29c8; _lxsdk=26F6BA50506A11E9A973FDD3C7EBDF0E29C7297EC72D4F77A53F9445EF0EE9F3; from=canary; uid=124265875; token=9P1-5VoykD_qrpBxpTvSoVhMwzQAAAAAJwgAAE2za6eVZdI-oORrTHb8dP4JEMYCiza0zSSNoRkHx4qajm2Nu6ClhU00u5A1avIySg; __mta=250960825.1553675243337.1553675275840.1553675275842.6; user=124265875%2C9P1-5VoykD_qrpBxpTvSoVhMwzQAAAAAJwgAAE2za6eVZdI-oORrTHb8dP4JEMYCiza0zSSNoRkHx4qajm2Nu6ClhU00u5A1avIySg; _lxsdk_s=169be42cf2b-ca7-4ca-570%7C%7C14'
      },
      data:{
        cityId:params.cityId,
        ci:params.ci,
        seqNo:params.seqNo
      }
    }).then(res=>{
      if(res.statusCode ==200){
        Taro.hideLoading();
        const seatData = res.data.seatData;
        const seatArray = [];
        seatData.seat.sections[0].seats.map(item=>{
          let  arr = [];
          item["columns"].map(seat=>{
            if(seat["st"] == "N"){
              arr.push('0');
            }else{
              arr.push('E')
            }
          })
          seatArray.push(arr);
        })
        self.setState({
          seatData:seatData,
          seatArray:seatArray
        });
      }
    })
  }

做了影院座位信息是否为空筛选之后,接下来就是选座功能。其中影院座位的选择与取消使用了buySeat进行保存。selectSeat函数是选择座位,row:代表选择第几行,column代表第几列,item是该座位是否被选的信息(0为未选表示可选择、2为已选表示不可再选)

selectSeat(row,column,item){
    const self = this;
    const arr = this.state.seatArray;
    // item代表该座位是否可选
    if(item == 0){
      if(self.state.buySeat.length ==4){
        Taro.showToast({
          title: '最多选择4个座位',
          duration: 2000
        })
        return false;
      }else{
        let  buySeat = self.state.buySeat;
        arr[row][column]= '2';
        buySeat.push({
          "row":row,
          "column":column
        });
        self.setState({
          buySeat:buySeat,
          seatArray:arr
        })
      }
    }else{
      arr[row][column]= '0';
      const  buySeat = this.state.buySeat;
      let tmpArr = this.state.buySeat;
      buySeat.map((value,index)=>{
        if(value["row"]== row && value["column"]== column){
          tmpArr.splice(index,1);
          self.setState({
            buySeat:tmpArr,
            seatArray:arr
          })
        }
      })
    }
  }

推荐座位功能实现,getRecomment是推荐位实现,现在至于1人、2人、3人、4人推荐。情侣位实现没有抓取到猫眼的推荐接口信息。

  selectAll(seats){
    const self = this;
    seats.map(item=>{
      let row = parseInt(item.rowId.split('0')[0]);
      let column = parseInt(item.columnId.split('0')[0]);
      let itemIndex = self.state.seatArray[row][column];
      self.selectSeat(row,column,itemIndex);
    })

  }
  getRecomment(recomment,num){
    switch(num){
      case 1:this.selectAll(recomment.bestOne.seats);break;
      case 2:this.selectAll(recomment.bestTwo.seats);break;
      case 3:this.selectAll(recomment.bestThree.seats);break;
      case 4:this.selectAll(recomment.bestFour.seats);break;
    }
  }

content电影详情页

电影详情是一部电影简略介绍。主要实现了,电影主要简略描述和预告片的播放关闭,实现比较简单。getDetailData是获取电影详情数据接口。其中获取到img路径直接获取不到图片数据,需要对路径进行改写,如下代码所示:

 getDetailData(){
    Taro.showLoading({
      title:"加载中"
    });
    Taro.request({
      url:`https://m.maoyan.com/ajax/detailmovie?movieId=${this.state.params.id}`
    }).then(res=>{
      if(res.statusCode == 200){
        Taro.hideLoading();
        let data = res.data.detailMovie;
        let arr = data["img"].split("w.h");
        data["img"] = arr[0]+"128.180"+  arr[1];
        for(let index in data.photos){
          let photo = data.photos[index];
          let arr = photo.split('w.h');
          data.photos[index] = arr[0]+'180.140'+arr[1];
        }
        this.setState({
          detailMovie:data
        });
      }
    }).catch(err=>{
      console.log(err.message);
    })
  }

在今天这个充满恋爱酸臭味日子,满怀期待地水完这篇短文。如果觉得喜欢的话,可不可以给我new个对象。说错了,应该是new个star~。

github地址: https://github.com/Harhao/miniProgram

骚气
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,126评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,254评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,445评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,185评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,178评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,970评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,276评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,927评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,400评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,883评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,997评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,646评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,213评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,204评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,423评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,423评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,722评论 2 345