學習小程式從“你”開始

SongsongDeng發表於2017-12-08

最近的十幾天中在接觸小程式,從看別人的開源專案,到現在自己做一個專案,整個過程中心情是有起有落,也學到了很多東西,接下來和大家一起分享自己的學習過程,一起交流,一起學習:

選題

在做專案的開始,我們首先要做的事就是選擇主題了,無論我們是選擇仿一個專案,還是選擇自己原創一個專案,都要面對選擇主題,對不同層次的學習者來說,主題的選擇的思考不同。對於自己來說,還是一個初入小程式的新人,我就說說我自己現在對選題的看法,作為一個新手,我更多的是偏向選擇一個自己感覺容易上手的專案,例如先仿一個開源專案,熟悉小程式的一些元件、API等,也就是熟悉小程式的一些開發套路,不要為了做專案而去做專案,要清楚做專案的目的是什麼,是學習,還是 完成老闆任務,還是為了更多的star等等,這個得自己去思考。

說了這麼多還沒說自己做了什麼,我做的是仿知乎,目的在於想通過這次學習對小程式有一個更好的認識,這次的學習也是在前輩的鋪墊下進一步的學習,學習到了很多前輩的想法,感覺很不錯。下面我和大家分享整個專案編寫過程我的一些思考,遇到的問題和看法等等。

專案已實現功能:

  • 列表式渲染資料
  • 上拉重新整理
  • 下拉載入更多
  • 頁面跳轉
  • 傳參頁面跳轉
  • 按鈕點選彈窗
  • 發表評論
  • 圖片輪播
  • 頂部導航等等

專案效果:

底部tabBar切換

學習小程式從“你”開始

首頁切換

學習小程式從“你”開始

上拉重新整理下拉載入

學習小程式從“你”開始

點選事件及頁面跳轉

學習小程式從“你”開始

評論功能

學習小程式從“你”開始

上面是目前專案已經實現的部分,其他功能在日後會繼續實現。

專案的初心

在整個專案開始之前,我思考過這個問題,我寫這個專案是為什麼,這是自己寫專案的動力,自己現在還處於學習階段,更多的是想通過這個專案自己能夠學到什麼,程式設計技巧,程式設計思想,對小程式的熟悉程度等等,所以自己在寫程式碼的時候多去用用之前自己沒有接觸過的東西,例如commonJS中的檔案引入的方法同時也使用了ES6中模組化引入的方法等等,很多人可能不理解為什麼要這麼用,明明可以那樣做。對於一個學習者來說,要儘可能的在一個專案中多用到不同的方法,讓自己知道有這麼個東西的存在並學會掌握方便日後的專案中的使用,這才實現了做這個專案的價值。即對現在的我來說,仿知乎這個專案的初心是為了學習更多自己沒有接觸到的東西,讓自己對程式設計有進一步的瞭解。

專案介紹

專案起步

專案開始的時候我首先思考的問題就是檔案排版,一個完整的專案應該對檔案有一個合理的結構,需要模組化,增強專案的可讀性,操作和以後維護起來也就更加的方便了。看看自己的檔案的目錄:

學習小程式從“你”開始      學習小程式從“你”開始    學習小程式從“你”開始   學習小程式從“你”開始    學習小程式從“你”開始

學習小程式從“你”開始

上面就是自己專案的主要目錄了,按照自己的想法對其分解,但是還是存在著很多的問題,編寫的並不是很好,很多的功能的實現程式碼沒有單獨的用不同的檔案區分開,都是在一個檔案中編寫,這需要進一步的優化,模組化在程式設計中是一個挺重要的思想,可以很好的實現程式碼的重用性,可以節約一定的開發時間。最近也在看看前端工作流的一些東西,專案目錄也是分為開發目錄和上線目錄,可以通過babel、gulp、webpack等對開發檔案的一些處理,也是挺不錯的一種思想,對這瞭解的還不是很多,還在學習中,以後專案開發中可以用,增加自己對企業級開發的實踐,這也是大家可以學習的一個方向。

後臺資料方面

開發專案中不可缺少的就是資料了,現在的專案中的頁面不再可能是靜態頁面了,把資料給寫si了,這沒有任何價值,同時也增加了程式設計的工作量,程式碼也很冗長。這就需要模擬後臺資料,可以實現列表式渲染資料,減少了很多的工作量,這就出現了一個問題,怎麼模擬後臺資料,用什麼去模仿資料,很多人會用第三方提供的,例如使用easy-mock,通過wx.request()來獲取資料,實現頁面載入資料,相信這種方式大家都會用。如果在本地寫假資料,那我們又該用什麼寫,怎樣獲取資料,對一個初學者來說應該是不太清楚的(大佬除外),這個就是我們可以學習的地方,學會用不一樣的方式去做一件事,這就會實現做這個專案的目的。

說到這裡,資料應該是放在js檔案中,一般後臺資料都是JSON格式,所以放在js檔案最為合理了,這時問題又出現了,我們怎麼獲取裡面的資料呢?想到這個我也不曉得怎麼獲取裡面的資料,看到前輩有用到require()的方式獲取資料,想想這個是什麼東西,開發經驗不足,不曉得這個是什麼東西,自己就會主動的去了解這個是什麼東西,原來這個是node中CommonJS中的模組實現,js之前並沒有很好的實現模組化程式設計,幾乎所有的程式碼都寫在一個檔案中,CommonJS的出現,實現了JS的模組化,同時自己也曉得了ES6中也有了屬於自己模組化的方式了,使用import、export方式實現模組化程式設計,感覺自己又學到了,在自己的專案中就都有用到這兩種方式來獲取資料:

學習小程式從“你”開始  學習小程式從“你”開始 學習小程式從“你”開始學習小程式從“你”開始

學習小程式從“你”開始

看上面的圖片,就可以看到我兩種方式在一個專案中都是有使用到的,你可能沒有看懂下哦貼出來的是什麼,你不需要看懂,現在快去看看CommonJS和ES6中模組化的知識,你又會學到東西的!!!有人就會不理解,幹嘛要在本地寫假資料啊,這不在佔儲存量嗎,為什麼要用兩種模組化的方式啊,一種不就行了嗎等等問題,其實我做的不是“專案”,我更多的是想通過這個專案我能學到什麼東西,這裡我知道了兩種模組化的方式,然後我可以在後面多花點時間對著兩種模組化方式深入學習,這個就是我想要的結果,真正的專案開發中就不要把假資料放在本地,也不要一件事情同時使用兩種方式去做,現在可以玩玩,哈哈哈哈哈哈哈!!!!!

引用第三方框架問題

很多人肯定也思考過做專案是否使用第三方框架,還是自己寫原生程式碼,這個問題就要看自己的想法了,我就說說我自己的看法,我現在接觸前端的時間不長,很多的東西都不是很清楚,像wxss的樣式想自己去寫,多熟悉樣式屬性,其實讓我用第三方的框架我也不是很會用,但是還是要多去用,要“會”用框架。在這個專案中大部分的wxss檔案都是自己寫的,到了後面有的功能的樣式,我也用了第三方框架,像小程式中常用的UI框架中有weui,這個很好用,微信團隊開發的一個框架,提供了很多的元件,可以減少很多的開發時間。

我的態度是,如果是學習的態度那就自己寫原生程式碼這樣提升我認為是比較快的,如果是實際開發專案,那就是能用框架那就用框架,不要自己造輪子。

專案主要功能實現過程中的思考

小程式開發模式和我們傳統的開發模式很不相同,傳統的開發中我們一般是使用dom操作來動態的改變頁面,讓我感覺的是一種查詢的方式,使用dom操作,找到某個元素然後再改變該元素的行為,從而改變了頁面的狀態,而小程式的開發模式是MVVM,資料繫結頁面,資料的改變從而使得頁面狀態發生改變,這個傳統的開發很不相同,這個在小程式開發很容易踩坑,自己在這個專案中就踩到過這個坑,要理解好MVVM模式。

  • 按鈕點選彈窗事件

<block wx:for="{{feed}}" wx:for-index="idx" wx:for-item="item" wx:key="idx" data-idx="{{idx}}" >
  <view  class="feed-item">      
     <view class="feed-source">
       <!--遮罩層-->
       <view class="drawer_screen" bindtap="hide" data-statu="close" wx:if="{{showModalStatus}}"></view>
       <!--彈窗事件觸發-->
       <view bindtap="powerDrawer" data-statu="open" data-answerId="{{item.answer_id}}">
           <image class="item-more" mode="aspectFit" src="../../images/more.png"></image>
       </view>
     </view>
     <!--彈窗頁面-->
     <view animation="{{animationData}}" data-answerId="{{item.answer_id}}" class="drawer_box" wx:if="{{showModalStatus&&item.isSelected}}">
        <view class="drawer_shield">遮蔽這個問題</view>
        <view class="drawe_report">舉報</view>
     </view>
  </view>
</block>複製程式碼

var util = require('../../utils/util.js');const app = getApp();
Page({ // 頁面初始資料data: {
//  資料來源feed: [],//  更多按鈕 觸發彈窗
showModalStatus: false ,
},
// 彈窗觸發事件powerDrawer: function (e) { 
  // 獲取資料來源
  let feed = this.data.feed;// 得到按鈕點選時設定的資料值 data-answerId
let answer_id = e.currentTarget.dataset.answerid;// 得到按鈕點選時設定的資料值 data-statu
let currentStatu = e.currentTarget.dataset.statu;
// 遍歷資料來源
for(let key of feed)
{
   if(key.answer_id === answer_id){      key.isSelected = true;
   }
}
this.setData({
   feed:feed,
});
// 彈出窗
this.util(currentStatu);}
})複製程式碼

//資料來源模板
var next = {
  "data": [
        {
          "topic": "教育",          "answer_id": 1,
          ...
        },
        {
           "topic": "教育",
           "answer_id": 2,
           ...
        },
        {
           ...
        },
        ...
    ]
}複製程式碼

上面就是點選按鈕彈窗事件的主要程式碼,因為做的是列表式資料渲染,基本頁面的佈局只寫了一個,通過js中的資料繫結,可以將資料來源中的所有的資料都可以匯入頁面中,這樣可以減少很多的工作量。現在就和大家分享我在寫這個觸發事件遇到的問題,大家看下面的圖就清楚問題在哪裡了:

學習小程式從“你”開始

看到圖就曉得了問題來了,單獨點選一個,其他框也觸發了彈窗事件,這是做列表式渲染資料都容易遇到的問題,遇到的坑,為什麼會出現這種問題呢,原因很簡單,因為在寫頁面佈局的時候,我們是通過<block wx:for=""></block>動態填充資料的,基本的樣式只寫了一個,每一個資料都有bindtap觸發事件

學習小程式從“你”開始

起初遇到這個問題,我想的辦法是,資料來源中的資料是寫在陣列中,每一資料都有自己固定的"answer_id" ,然後我在觸發彈窗時填入一個資料data-answerId="{{item.answer_id}}",設定的值也為answer_id,我就想通過查詢的方式,找到每一個資料的answer_id再和觸發按鈕時的設定的資料進行對比,如果值一樣,就彈出其自身的窗,然而並沒有解決問題,下面是最初設計的程式碼:

學習小程式從“你”開始

這就是想通過查詢的方式來解決問題,沒有做到,原因是你每次查詢的值和你觸發時設定的值都是一樣的,所以是解決不了問題的,這種做法就還停留在傳統的開發設計,如dom操作,不斷的查詢,找到某個值,然後再改變它。單純的使用這種做法在小程式有些難度來解決問題了,其實要正確的理解MVVM模式,這個問題就很好解決了,資料繫結頁面,資料改版頁面的狀態。

解決這個問題的方法就是為每一個資料新增一個布林值,觸發自身的按鈕事件時其布林值為true,其他的資料的布林值為false

學習小程式從“你”開始

學習小程式從“你”開始

這樣的寫法就很好的解決了問題,查詢操作和資料繫結操作一起解決問題。

  • 評論功能

<view class="comment-bd">
  <view class="ordinaryComment">     <text>評論</text>
  </view>
 <block wx:for="{{item.ordinaryComment}}" wx:key="index">   <view class="user-comment">    <view class="user-avatar">       <image src="{{item.feed_source_img}}"></image>
    </view>
    <view class="comment-content">
      <view class="user-name">        <text>{{item.feed_source_name}}</text>      </view>    <view class="answer-content">       <text>{{item.content}}</text>    </view>
    <view class="comment-action">      <view class="like dot">         <text>點贊 {{item.good_num}}</text>      </view>      <view class="comment dot">         <text>回覆{{item.comment_num}}</text>      </view>     <view class="time">        <text>{{item.time}}</text>      </view></view>
</view>
</block>
<view class="comment-ft">   <view class="commentInput">
       <input type="text" value="{{content}}" bindinput="onTextChanged" placeholder="請輸入評論" placeholder-class="placeholderClass" />   </view>
   <view class="commentBtn">
       <text bindtap="onSendClicked" data-questionId="{{item.question_id}}">釋出</text>   </view></view>  複製程式碼

var util = require('../../utils/util.js');
let myComment = '';
Page({
   data: {     comment: [],    content: "", },
onTextChanged: function(e){
     //獲取文字框的值,即輸入的評論的內容
    myComment = e.detail.value; },
onSendClicked: function(e){
//獲取觸發時設定資料的值
let question_id = e.target.dataset.questionid;
var that = this,conArr = [];
//定時器,100ms後觸發
setTimeout(function(){
//將評論的基本資訊存入陣列
 if(myComment.length > 0){
     conArr.push({     "feed_source_img": "../../images/icon9.jpeg",     "feed_source_name": "zero",     "time": util.formatTime(new Date()),     "good_num": "0",     "comment_num": "0",     "content": myComment     })
//從資料來源中獲取評論頁面的所有資料
var feed = util.getData2();
let comment_data = feed.comment;
//找到指定頁面的評論資料
const comment = comment_data.filter((comment) => {
   return question_id == comment.question_id;})
//將新增的評論的基本資訊陣列conArr合併到資料來源中評論資料的陣列comment[0].ordinaryComment中var commentContent = comment[0].ordinaryComment.concat(conArr);
//將新加入的conArr陣列放在源陣列中的第一位,便於觸發提交評論時評論內容出現在頁面的第一欄
var newCommentContent = commentContent.reverse();var newComment = comment[0];
comment[0].ordinaryComment = newCommentContent;
that.setData({
comment: comment,
content: ""
})
}
 },100)
},
})複製程式碼

上面就是評論功能的主要程式碼,要實現這個功能主要解決的問題是找到指定問題的評論頁面,通過Array.filter()方法可以找到指定問題的評論頁面,然後又解決的問題是將填寫的評論資訊加到資料來源中評論資料的陣列comment[0].ordinaryComment中,通過Array.concat()方法可以實現,最後就是將新的資料展示到頁面上,更新頁面狀態,其中還有一個地方主要注意:如何將輸入的評論資訊,顯示在評論欄的第一欄,Array.reverse()可以解決這個問題,這樣就比較好的實現了這個功能。

  • 其他功能總結

像比較常見的功能還有首頁頂部的tab切換,可以使用swiper-item元件和bindtap進行事件繫結,可以實現這種tab切換的效果,下拉重新整理的可以使用scroll-view元件,元件裡面提供了很多的屬性可以實現很多的功能,還有基本的彈窗功能的元件有wx.showToast()、wx.showActionSheet(OBJECT)、wx.showModal(OBJECT)等等,這些元件都可以看官方文件學習,學習利用基本元件。

  • 相關文件和工具

 1.小程式開發文件    學會使用開發文件,多看開發文件,熟悉元件,避免自己不必要的麻煩

 2. commonJS學習   提供比較強的模組化的學習

 3. ES6模組化 屬於自己的模組化開發

 4. iconfont   @font-face 學會使用CSS3 font-size屬性 頁面圖片不再是png格式了,值得學習

 5. weui  學會使用第三方框架,小程式需要學習weui

 6. 小程式開發者工具  小程式開發工具

結束

這次的學習學到了挺多東西的,要想清除做這個專案的目的是什麼,這個專案我的目的就是為了學習,曉得了自己缺少什麼,什麼需要去加強學習的,在整個專案的完成過程中,其實感覺到了自己的功利心,希望自己快點把專案做完,這個在學習的過程中是很不好的,忘記了自己做專案的初心,作為一個學習者,我們應該多想想做這個專案能給自己帶來什麼,我可以通過行動具體的給自己帶來哪些幫助,我們應該要實現這個專案對自己的最大效益,這才是這個專案的存在價值,要對得起這個專案,不要僅僅趨於我做了這個專案,做好了,我不管了,需要不忘初心的學習!!!!!

最後附上這個專案的github地址和個人的聯絡方式,我們可以一起交流學習,共同進步

專案地址:github.com/DengSongson…

個人郵箱:DengSongsong1010@163.com

wx: dss1000010

如果覺得這篇文章和專案有好處,歡迎star哦,謝謝大家!!!



相關文章