手把手教你開發小程序

若是以爲事情太複雜無從下手,就分紅許多許多個小步進行好了 ---尼古斯拉

下載與安裝

小程序下載地址html

安裝過程很是簡單直接下一步就好了。git

核心文件解釋

app.json

app.json 文件以下:github

{
      "pages":[
        "pages/index/index",
        "pages/logs/logs"

      ],
      "window":{
        "backgroundTextStyle":"light",
        "navigationBarBackgroundColor": "#fff",
        "navigationBarTitleText": "WeChat",
        "navigationBarTextStyle":"black"
      },
      "tabBar": {
        "color": "#858585",
        "selectedColor": "#000000",
        "backgroundColor": "#ffffff",
        "list": [ 
          {
            "pagePath": "pages/index/index",
            "text": "首頁",
            "iconPath": "/img/tab_home.png",
            "selectedIconPath": "/img/tab_home-active.png"
          },
          {
            "pagePath": "pages/logs/logs",
            "text": "日誌",
            "iconPath": "/img/tab_category.png",
            "selectedIconPath": "/img/tab_category-active.png"
          }
          ]
        }
    }
  • pages 是整個小程序的頁面配置路徑,只有在這裏配置了的頁面路徑才能生效使用;
  • window 是配置整個小程序窗口風格的;
  • tabBar 是配置底部兩個菜單的;

組件化開發搜索欄

先看效果:web

clipboard.png

點擊
clipboard.pngjson

發生了什麼?咱們發現首頁有一個搜索欄,其實這至關於一個導航的圖標,點擊之後才跳轉到了真正的搜索頁面。因爲他們的樣式是同樣的,咱們打算要開發一個組件,而後在各自的頁面引用這個組件,就能夠達到代碼複用的目的。這個很重要,由於小程序主打的就是"輕型應用",整個程序不超過2M,因此代碼能省則省。兩個頁面除了樣式大致差很少,可是又有不同的地方,這就涉及了邏輯判斷,如何作呢?且看我慢慢道來。小程序

開發searchbar組件備用api

首頁有了,導航的這個圖標得咱們本身開發吧,如何作呢?
點擊小加號->新建目錄->右鍵新建component,填上值就能夠了。
小加號在哪呢?數組

clipboard.png
而後就是這個組件內容的開發啦,這裏只貼出核心部分,樣式什麼的的我稍後上傳到github,本身看。網絡

<view class="searchbar">
  <navigator url='/pages/search/search' class='search-navigator'></navigator>
</view>

咱們使用<navigator>標籤告訴小程序跳轉到url所指的頁面組件作好了,接下來咱們應用它。app

首頁應用searchbar組件

index.json文件中告訴小程序咱們要使用這個組件

{
  "usingComponents": {
    "searchbar": "/components/searchbar/searchbar"
  }
}

接下來打標籤直接使用,爲了區分使用view做個標記

<searchbar></searchbar>
<view>這是首頁</view>

而後咱們還須要新建一個search.wxml頁面及其組件,如何新建呢?
還記得以前咱們說過的app.json文件嗎,這個文件有個pages屬性管理全部的頁面,如今咱們增長一條pages/search/search保存刷新,頁面就自動建好了。search.wxml引用組件的過程和首頁相同,這裏不過多敘述。

"pages":[
    "pages/index/index",
    "pages/search/search",
    "pages/logs/logs"
  ]

最後咱們要實現的是在首頁只顯示導航的圖標,在搜索欄顯示一個輸入框,如何作呢?

找到searchbar.wxml頁面,多加一個view、它裏面是一個輸入框,輸入框樣式什麼的本身看,不是本文的重點。

<view class="searchbar">
  <navigator url='/pages/search/search' class='search-navigator'></navigator>
  <view class="search-input-group">
    <input class='search-input' placeholder='搜索' bindinput='onInputEvent'></input>
  </view>
</view>

接下來咱們作的事情就是,若是是首頁引用這個組件就顯示圖標,搜索頁引用就顯示輸入框。

找到searchbar.js文件,在組件的屬性列表properties這一項新增一個屬性isnavigator,它的類型是 Boolean,初始值爲false

properties: {
    isnavigator: {
      type: Boolean,
      value: false
    }
  }

接下來在searchbar.wxml應用這個屬性

<view class="searchbar">
  <navigator wx:if="{{isnavigator}}" url='/pages/search/search' class='search-navigator'></navigator>
  <view wx:else class="search-input-group">
    <input class='search-input' placeholder='搜索' bindinput='onInputEvent'></input>
  </view>
</view>

表示屬性值爲ture的時候就顯示圖標,false的時候就顯示輸入框。

接下來咱們要去index.wxml改下插件的屬性值

<searchbar isnavigator="{{true}}"></searchbar>

因爲默認值爲false、search.wxml就不用改了。這樣,首頁加載就顯示圖標,搜索頁加載就顯示輸入框。別看簡單,初次開發思路不清晰也挺費勁,容易亂。就這樣咱們就學會了組件化思想和使用邏輯判斷,是否是很厲害呢。

首頁佈局與數據獲取

完成效果以下

clipboard.png

分析:首頁的主要部分爲紅色大框部分,其中包括了標題、主體、星星三個小框框,只要把這個大框開發好了,其他的都是這個大框的重複。咱們打算把這個大框開發成一個獨立的組件,因爲星星在後面其餘地方有複用,星星這個部分咱們也開發成一個獨立的組件。

首頁組件的開發
在components目錄下新建目錄indexmodule,再新建component
接下進行indexmodule.wxml頁面的編寫。

標題和滾動條佈局

<view class='module-group'>
  <view class='module-top'>
    <view class='module-title'>電影</view>
    <navigator class='module-more'>更多</navigator>
  </view>
  <scroll-view class='module-scroll-view'>
    <navigator class='item-navigator' url="">
      <view class='item-group'>
        <view class='thumbnail-group'>
          <image class='thumbnail' src='https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2544987866.webp'></image>
        </view>
        <view class='item-title'>阿麗塔</view>
      </view>
    </navigator>
  </scroll-view>
</view>

在`index.json告訴小程序咱們要使用這個組件

{
  "usingComponents": {
    "searchbar": "/components/searchbar/searchbar",
    "indexmodule": "/components/indexmodule/indexmodule"
  }
}

index.wxml引入

<indexmodule></indexmodule>

效果以下:

clipboard.png
頁面包括了標題和滾動條,還差星星,下面咱們開發星星組件,並在這個頁面引入。

星星的佈局

代碼以下:

<view class='rate-group'>
  <image  wx:for="{{[1,2,3]}}" src="/images/rate_light.png"></image>
  <image  src='/images/rate_half.png'></image>
  <image  src='/images/rate_gray.png'></image>
  <text>7.0</text>
</view>

接下來在indexmodule.json告訴小程序咱們要引用這個組件。

{
  "component": true,
  "usingComponents": {
    "stars": "/components/stars/stars"}
}

最後在indexmodule.json直接引用就行了

<navigator class='item-navigator' url="">
      <view class='item-group'>
        <view class='thumbnail-group'>
          <image class='thumbnail' src='https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2544987866.webp'></image>
        </view>
        <view class='item-title'>阿麗塔</view>
      </view>
      <stars></stars>
</navigator>

效果以下:

clipboard.png

根據評分動態渲染星星

<stars rate="9"></stars>

打開stars.js文件,添加一個屬性rate,類型爲Number,默認值爲0

properties: {
    rate: {
      type: Number,
      value: 0
    }
  }

處理邏輯:

lifetimes: {
    attached: function () {
      var that = this;
      var rate = that.properties.rate;
      var intRate = parseInt(rate);
      var light = parseInt(intRate / 2);
      var half = intRate % 2;
      var gray = 5 - light - half;
      var lights = [];
      var halfs = [];
      var grays = [];
      for (var index = 1; index <= light; index++) {
        lights.push(index);
      }
      for (var index = 1; index <= half; index++) {
        halfs.push(index);
      }
      for (var index = 1; index <= gray; index++) {
        grays.push(index);
      }
      var ratetext = rate && rate > 0 ? rate.toFixed(1) : "未評分"
      that.setData({
        lights: lights,
        halfs: halfs,
        grays: grays,
        ratetext: ratetext
      });
    }
  }

動態渲染出來:

<image  wx:for="{{lights}}" src="/images/rate_light.png"></image>
  <image  wx:for="{{halfs}}"src='/images/rate_half.png'></image>
  <image  wx:for="{{grays}}"src='/images/rate_gray.png'></image>

動態數據加載和渲染

index.js中使用wx.request請求數據:

onLoad: function () {
   var that=this;
   wx.request({
     url: 'https://m.douban.com/rexxar/api/v2/subject_collection/movie_showing/items?count=7',
     success: function (res) {
       var movies = res.data.subject_collection_items;
       that.setData({
         movies: movies
         });
       console.log(movies);
     }
   })
  }

indexmodule.js添加屬性,它的類型爲數組類型:

items:{
      type:Array,
      value:[]
    }

index.wxml給這個屬性賦值:

<indexmodule  items="{{movies}}"></indexmodule>

而後在indexmoduel.wxml就可使用啦:

<navigator class='item-navigator' url="" wx:for="{{items}}" wx:key="{{item.title}}">
      <view class='item-group'>
        <view class='thumbnail-group'>
          <image class='thumbnail' src='{{item.cover.url}}'></image>
        </view>
        <view class='item-title'>{{item.title}}</view>
      </view>
      <stars rate="{{item.rating.value}}"></stars>
</navigator>

效果以下:

clipboard.png

wx:key

框架會確保他們被從新排序,而不是從新建立,以確保使組件保持自身的狀態,而且提升列表渲染時的效率。

結論:for 循環的時候必需要有wx:key以保持本身的特徵和狀態,key 的值能夠是字符串或者數字,並且須要在列表中是惟一的。在寫的時候,直接寫這個 property 的名字就能夠了,若是循環中的 item 自己,好比說循環的是一個數組,使用*this指代自己就能夠了。

列表頁以及網絡請求重構

若是在個點邏輯轉不過來、或是效果沒出來,先放下好了,回過頭來再看忽然就明白了 --尼古斯拉

點擊更多,效果以下:
分析:因爲列表中每一項和首頁滑動欄的每一項是同樣的,所以咱們抽取出來,單獨做爲一個itemview組件。而後在首頁和列表頁均可以調用,達到複用的目的。

itemview組件

頁面佈局很簡單,把以前在indexmodule.wxml寫過的複製過來就好了

<navigator class='item-navigator' url="">
  <view class='item-group'>
    <view class='thumbnail-group'>
      <image class='thumbnail' src='{{item.cover.url}}'></image>
    </view>
    <view class='item-title'>{{item.title}}</view>
    <stars rate="{{item.rating.value}}"></stars>
  </view>
</navigator>

記得在itemview.json告訴小程序咱們要使用星星組件哦

"usingComponents": {
    "stars": "/components/stars/stars"
  }

最後在indexmodule.wxml使用這個組件

"usingComponents": {
   "itemview": "/components/itemview/itemview"
  }
<scroll-view class='module-scroll-view' scroll-x="{{true}}">
   <itemview wx:for="{{items}}" wx:key="{{item.title}}" item="{{item}}"></itemview>
</scroll-view>

列表頁

<searchbar isnavigator="{{true}}"></searchbar>
<view class='container'>
  <itemview wx:for="{{items}}" wx:key="{{item.title}}" item="{{item}}"></itemview>
</view>
"usingComponents": {
    "searchbar": "/components/searchbar/searchbar",
    "itemview": "/components/itemview/itemview"
 }

頁面構成很是簡單,不過多敘述。

網絡請求重構

咱們要作的事情很簡單,把全部的網絡請求放在一個文件統一完成,而後根據不一樣的參數在不一樣的頁面完成渲染。

一、在utils目錄新建urls.js文件統一存放因此url,記得導出。

const globalUrls = {
  movieList: "https://m.douban.com/rexxar/api/v2/subject_collection/movie_showing/items",
  tvList: "https://m.douban.com/rexxar/api/v2/subject_collection/tv_hot/items",
  showList: "https://m.douban.com/rexxar/api/v2/subject_collection/tv_variety_show/items"
}
export { globalUrls }

在utils目錄新建network.js完成全部的請求,須要導入urls.jsglobalUrls,完成業務處理後記得導出。

import { globalUrls } from "urls.js";
const network = {
  // 獲取電影列表
  getMovieList: function (params) {
    params.url = globalUrls.movieList;
    this.getItemList(params);
  },
  //獲取電視劇列表
  getTVList: function (params) {
    params.url = globalUrls.tvList;
    this.getItemList(params);
  },
  // 獲取綜藝列表
  getShowList: function (params) {
    params.url = globalUrls.showList;
    this.getItemList(params);
  }, 
  getItemList: function (params) {  
    var count = params.count ? params.count : 7;
    wx.request({
      url: params.url,
      data: {
        count: count
      },
      success: function (res) {
        var items = res.data.subject_collection_items;
        if (params && params.success) {
          params.success(items);
        }
      }
    });
  }
}
export { network }

定義了四個方法,其中getItemList是幹活的方法,其餘的根據不一樣的url來引用這個方法,即可以獲取不一樣的數據。

首頁引用數據:
首頁引用數據是在index.js中的onLoad中寫代碼,記得要引用network.jsnetwork

import { network } from "../../utils/network.js";
//獲取應用實例
Page({
  data: {  
  },
  onLoad: function (options) {
    var that = this;
    // 電影
    network.getMovieList({
      success: function (movies) {
        that.setData({
          movies: movies
        });
      }
    });
    // 電視劇
    network.getTVList({
      success: function (tvs) {
        that.setData({
          tvs: tvs
        });
      }
    });

    // 綜藝
    network.getShowList({
      success: function (shows) {
        that.setData({
          shows: shows
        });
      }
    });
  }
})

數據渲染很簡單,參照前面就好了,就是把變量的值傳過去而已,不羅嗦。

列表頁引用數據:

<!-- 電影 -->
<indexmodule title="電影" items="{{movies}}" moreurl="/pages/list/list?type=movie"></indexmodule>

<!-- 電視劇 -->
<indexmodule title="電視劇" items="{{tvs}}" moreurl="/pages/list/list?type=tv" ></indexmodule>

<!-- 綜藝 -->
<indexmodule title="綜藝" items="{{shows}}" moreurl="/pages/list/list?type=show"></indexmodule>

咱們在首頁index.wxmlmoreurl屬性賦值時添加了一個一個參數type做爲區分,稍候既能夠在請求數據的list.js拿到type的值,而後就能夠根據type的值不一樣從而請求不一樣的數據。

list.js請求數據的代碼以下:

onLoad: function (options) {
    var that = this;
    var type = options.type;
    var title = "";
    wx.showLoading({
      title: '正在加載中...',
    })
    if (type === "movie") {
      // 請求電影的數據
      network.getMovieList({
        success: function (items) {
          that.setData({
            items: items
          });
          wx.hideLoading();
        },
        count: 1000
      });
      title = "電影";
    } else if (type === 'tv') {
      // 請求電視劇的數據
      network.getTVList({
        success: function (items) {
          that.setData({
            items: items
          });
          wx.hideLoading();
        },
        count: 1000
      });
      title = "電視劇";
    } else {
      // 請求綜藝的數據
      network.getShowList({
        success: function (items) {
          that.setData({
            items: items
          });
          wx.hideLoading();
        },
        count: 1000
      });
      title = "綜藝";
    }
    wx.setNavigationBarTitle({
      title: title,
    })
  }

記得要引入network,怎麼引不用囉嗦了吧。

這樣,列表頁以及網絡重構就所有完成了,剛開始作可能有些陌生,不要緊,慢慢來。

小插曲:

clipboard.png

點開更多發現怎麼這樣子的?
查資料發現是flex-wrap:wrap 控制水平折行排列的,可我也寫了呀,哪確定是什麼地方影響了。
後來發現

clipboard.png
這裏也定義了一個container樣式,刪掉就行了。這個教訓告訴咱們知識必定要全面呀,知識全面思路才清晰。

詳情頁佈局以及數據加載

相關文章
相關標籤/搜索