最近的十几天中在接触小程序,从看别人的开源项目,到如今本身作一个项目,整个过程当中心情是有起有落,也学到了不少东西,接下来和你们一块儿分享本身的学习过程,一块儿交流,一块儿学习:javascript
在作项目的开始,咱们首先要作的事就是选择主题了,不管咱们是选择仿一个项目,仍是选择本身原创一个项目,都要面对选择主题,对不一样层次的学习者来讲,主题的选择的思考不一样。对于本身来讲,仍是一个初入小程序的新人,我就说说我本身如今对选题的见解,做为一个新手,我更多的是偏向选择一个本身感受容易上手的项目,例如先仿一个开源项目,熟悉小程序的一些组件、API等,也就是熟悉小程序的一些开发套路,不要为了作项目而去作项目,要清楚作项目的目的是什么,是学习,仍是 完成老板任务,仍是为了更多的star等等,这个得本身去思考。css
说了这么多还没说本身作了什么,我作的是仿知乎,目的在于想经过此次学习对小程序有一个更好的认识,此次的学习也是在前辈的铺垫下进一步的学习,学习到了不少前辈的想法,感受很不错。下面我和你们分享整个项目编写过程个人一些思考,遇到的问题和见解等等。html
上面是目前项目已经实现的部分,其余功能在往后会继续实现。前端
在整个项目开始以前,我思考过这个问题,我写这个项目是为何,这是本身写项目的动力,本身如今还处于学习阶段,更多的是想经过这个项目本身可以学到什么,编程技巧,编程思想,对小程序的熟悉程度等等,因此本身在写代码的时候多去用用以前本身没有接触过的东西,例如commonJS中的文件引入的方法同时也使用了ES6中模块化引入的方法等等,不少人可能不理解为何要这么用,明明能够那样作。对于一个学习者来讲,要尽量的在一个项目中多用到不一样的方法,让本身知道有这么个东西的存在并学会掌握方便往后的项目中的使用,这才实现了作这个项目的价值。即对如今的我来讲,仿知乎这个项目的初心是为了学习更多本身没有接触到的东西,让本身对编程有进一步的了解。java
项目开始的时候我首先思考的问题就是文件排版,一个完整的项目应该对文件有一个合理的结构,须要模块化,加强项目的可读性,操做和之后维护起来也就更加的方便了。看看本身的文件的目录:node
上面就是本身项目的主要目录了,按照本身的想法对其分解,可是仍是存在着不少的问题,编写的并非很好,不少的功能的实现代码没有单独的用不一样的文件区分开,都是在一个文件中编写,这须要进一步的优化,模块化在编程中是一个挺重要的思想,能够很好的实现代码的重用性,能够节约必定的开发时间。最近也在看看前端工做流的一些东西,项目目录也是分为开发目录和上线目录,能够经过babel、gulp、webpack等对开发文件的一些处理,也是挺不错的一种思想,对这了解的还不是不少,还在学习中,之后项目开发中能够用,增长本身对企业级开发的实践,这也是你们能够学习的一个方向。webpack
开发项目中不可缺乏的就是数据了,如今的项目中的页面再也不多是静态页面了,把数据给写si了,这没有任何价值,同时也增长了编程的工做量,代码也很冗长。这就须要模拟后台数据,能够实现列表式渲染数据,减小了不少的工做量,这就出现了一个问题,怎么模拟后台数据,用什么去模仿数据,不少人会用第三方提供的,例如使用easy-mock,经过wx.request()来获取数据,实现页面加载数据,相信这种方式你们都会用。若是在本地写假数据,那咱们又该用什么写,怎样获取数据,对一个初学者来讲应该是不太清楚的(大佬除外),这个就是咱们能够学习的地方,学会用不同的方式去作一件事,这就会实现作这个项目的目的。css3
说到这里,数据应该是放在js文件中,通常后台数据都是JSON格式,因此放在js文件最为合理了,这时问题又出现了,咱们怎么获取里面的数据呢?想到这个我也不晓得怎么获取里面的数据,看到前辈有用到require()的方式获取数据,想一想这个是什么东西,开发经验不足,不晓得这个是什么东西,本身就会主动的去了解这个是什么东西,原来这个是node中CommonJS中的模块实现,js以前并无很好的实现模块化编程,几乎全部的代码都写在一个文件中,CommonJS的出现,实现了JS的模块化,同时本身也晓得了ES6中也有了属于本身模块化的方式了,使用import、export方式实现模块化编程,感受本身又学到了,在本身的项目中就都有用到这两种方式来获取数据:git
看上面的图片,就能够看到我两种方式在一个项目中都是有使用到的,你可能没有看懂下哦贴出来的是什么,你不须要看懂,如今快去看看CommonJS和ES6中模块化的知识,你又会学到东西的!!!有人就会不理解,干吗要在本地写假数据啊,这不在占存储量吗,为何要用两种模块化的方式啊,一种不就好了吗等等问题,其实我作的不是“项目”,我更多的是想经过这个项目我能学到什么东西,这里我知道了两种模块化的方式,而后我能够在后面多花点时间对着两种模块化方式深刻学习,这个就是我想要的结果,真正的项目开发中就不要把假数据放在本地,也不要一件事情同时使用两种方式去作,如今能够玩玩,哈哈哈哈哈哈哈!!!!!es6
不少人确定也思考过作项目是否使用第三方框架,仍是本身写原生代码,这个问题就要看本身的想法了,我就说说我本身的见解,我如今接触前端的时间不长,不少的东西都不是很清楚,像wxss的样式想本身去写,多熟悉样式属性,其实让我用第三方的框架我也不是很会用,可是仍是要多去用,要“会”用框架。在这个项目中大部分的wxss文件都是本身写的,到了后面有的功能的样式,我也用了第三方框架,像小程序中经常使用的UI框架中有weui,这个很好用,微信团队开发的一个框架,提供了不少的组件,能够减小不少的开发时间。
个人态度是,若是是学习的态度那就本身写原生代码这样提高我认为是比较快的,若是是实际开发项目,那就是能用框架那就用框架,不要本身造轮子。
小程序开发模式和咱们传统的开发模式很不相同,传统的开发中咱们通常是使用dom操做来动态的改变页面,让我感受的是一种查找的方式,使用dom操做,找到某个元素而后再改变该元素的行为,从而改变了页面的状态,而小程序的开发模式是MVVM,数据绑定页面,数据的改变从而使得页面状态发生改变,这个传统的开发很不相同,这个在小程序开发很容易踩坑,本身在这个项目中就踩到过这个坑,要理解好MVVM模式。
1.按钮点击弹窗事件
<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
这样的写法就很好的解决了问题,查找操做和数据绑定操做一块儿解决问题。
2.评论功能
<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> </view> </block> </view> <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()能够解决这个问题,这样就比较好的实现了这个功能。
3.其余功能总结
像比较常见的功能还有首页顶部的tab切换,可使用swiper-item组件和bindtap进行事件绑定,能够实现这种tab切换的效果,下拉刷新的可使用scroll-view组件,组件里面提供了不少的属性能够实现不少的功能,还有基本的弹窗功能的组件有wx.showToast()、wx.showActionSheet(OBJECT)、wx.showModal(OBJECT)等等,这些组件均可以看官方文档学习,学习利用基本组件。
此次的学习学到了挺多东西的,要想清除作这个项目的目的是什么,这个项目个人目的就是为了学习,晓得了本身缺乏什么,什么须要去增强学习的,在整个项目的完成过程当中,其实感受到了本身的功利心,但愿本身快点把项目作完,这个在学习的过程当中是很很差的,忘记了本身作项目的初心,做为一个学习者,咱们应该多想一想作这个项目能给本身带来什么,我能够经过行动具体的给本身带来哪些帮助,咱们应该要实现这个项目对本身的最大效益,这才是这个项目的存在价值,要对得起这个项目,不要仅仅趋于我作了这个项目,作好了,我无论了,须要不忘初心的学习,作一个有思想的程序猿!!!!!
最后附上这个项目的github地址和我的的联系方式,咱们能够一块儿交流学习,共同进步
项目地址:https://github.com/DengSongso...
我的邮箱:DengSongsong1010@163.com
wx: dss1000010
若是以为这篇文章和项目有好处,欢迎star哦,谢谢你们!!!