WX06--功能开发--动态发布页、首页、动态详情页01
day06 小程序功能开发
1 发布页
1.1 发布流程的问题
-
方式一
1.打开图片进行本地预览 2 输入文字 & 选择相应的信息 3 点击发布按钮 3.1 将本地图片上传到 腾讯云对象存储中COS(oss),并将COS中的图片地址返回。 3.2 将COS中的图片URL和文字等信息一起提交到后台。 # BUG: 在3.2步骤时可能拿不到COS中的图片,因为3.1上传图片是异步请求 js中的执行顺序: 同步>异步>回调
function onClickSubmit(){ // 耗时1分钟,不会阻塞。 wx.request({ url:"...", success:function(res){ console.log(res) } }) console.log(123); }
-
方式二(推荐)
1 打开图片进行本地预览 2 将本地图片上传到 腾讯云对象存储中COS 3 输入文字 & 选择相应的信息 4 发布: 必须上传完毕之后,才允许点击发布按钮。
1.2 组件:进度条
<progress percent="{{percent1}}" ></progress>
<progress percent="{{percent2}}" activeColor="#DC143C" ></progress>
1.3 修改data中的局部数据
<view>-----案例------</view>
<view>点击按钮完成,将图片1的进度条更新为80%</view>
<view wx:for="{{imageList}}">
<view>{{item.title}}</view>
<progress percent="{{item.percent}}" ></progress>
</view>
<button bindtap="changePercent" >点击</button>
data: {
percent1:20,
percent2:50,
imageList:[
{ id: 1, title: "图片1", percent: 20 },
{ id: 1, title: "图片2", percent: 30 },
{ id: 1, title: "图片3", percent: 60 },
]
},
changePercent:function(){
// 方式1:索引取值修改: 错误 不支持
this.setData({
imageList[0].person: 80
});
// 方式2:复制后再修改: 可以,由于需要全部修改,所以性能差。
var dataList = this.data.imageList;
dataList[0].percent = 80;
this.setData({
imageList: dataList
});
// 方式3:特定语法:[""] 推荐
var num = 2;
this.setData({
["imageList[0].percent"]:80,
["imageList[" + num + "].percent"]: 90,
["imageList[1].title"]:"突突突突突"
})
},
1.4 发布示例效果
前端
后端
-
GET 获取临时COS密钥(临时密钥需要有上传和删除的权限)(APIView)
-
url
url(r'^oss/credential/$', auth.OssCredentialView.as_view()),
-
view
class OssCredentialView(APIView): def get(self, request, *args, **kwargs): from utils.tencent.oss import get_credential return Response(get_credential())
-
-
GET 获取话题接口
-
url
url(r'^topic/$', topic.TopicView.as_view()),
-
序列化
class TopicSerializer(ModelSerializer): class Meta: model = models.Topic fields = "__all__"
-
view(读取所有的话题)
- APIView
- ListAPIView(推荐)
class TopicView(ListAPIView): serializer_class = TopicSerializer queryset = models.Topic.objects.all().order_by('-count')
-
-
POST 提交 新闻信息
-
url
url(r'^news/$', news.NewsView.as_view()),
-
序列化
class CreateNewsTopicModelSerializer(serializers.Serializer): key = serializers.CharField() cos_path = serializers.CharField() class CreateNewsModelSerializer(serializers.ModelSerializer): imageList = CreateNewsTopicModelSerializer(many=True) class Meta: model = models.News exclude = ['user', 'viewer_count', 'comment_count'] def create(self, validated_data): image_list = validated_data.pop('imageList') news_object = models.News.objects.create(**validated_data) data_list = models.NewsDetail.objects.bulk_create( [models.NewsDetail(**info, news=news_object) for info in image_list] ) news_object.imageList = data_list if news_object.topic: news_object.topic.count += 1 news_object.save() return news_object
-
view(读取所有的话题)
- APIView
- CreateAPIView(推荐)
class NewsView(CreateAPIView): serializer_class = CreateNewsModelSerializer def perform_create(self, serializer): new_object = serializer.save(user_id=1) return new_object
-
1.5 JS闭包--解决for循环给异步传参的问题
// 一、问题:
由于request是异步请求(同步任务执行后,才会从任务栈开始执行),请求还没有开始,循环已经执行完;
所以按照下面代码打印 三次结果值都是 索引 2
var dataList = ['aa','bb','bb']
for(var index in dataList){
wx.request({
url:'xxx',
sucess:function(res){
console.log(index) // 三次都是2
}
})
}
// 二、解决办法--闭包:
使用闭包函数来解决该问题: 通过在for循环内部创建一个自执行函数,函数的局部名称空间会保存当次循环的索引
for(var index in dataList){
// 定义闭包函数 也可以定义在循环体外部
function fn(data){
wx.request({
url:'xxx',
sucess:function(res){
console.log(data)
}
})
}
// 执行闭包函数
fn(index)
}
// 闭包+自执行函数格式: ()()
for (var index in dataList) {
(function(data){
wx.request({
url: 'xxxxx',
success: function (res) {
console.log(data);
}
})
})(index)
}
// 三、解决办法--let来解决(就是把声明函数用let来声明) 试试
for(let index in dataList){
wx.request({
url:'xxx',
sucess:function(res){
console.log(index)
}
})
}
2 首页--简单版
获取前10条新闻(动态/心情,无需分页)
- url
- view(ListAPIView)
- 序列化
django model_to_dict() 方法
# model_to_dict() 可以将orm的model表,转化字典形式,但默认会跳过有editable=False属性字段的展示,
# 对于有auto_now_add=True和auto_now=True属性的 datetime字段 会默认添加editable=False隐藏属性
from django.forms import model_to_dict
model_to_dict(model_obj, exclude=['create_time', 'update_time'])
# 源码函数:
def model_to_dict(instance, fields=None, exclude=None):
# 参数instance是对象实例,fields是指定需要哪些字段,exclude是指定排除哪些字段,exclude比fields优先级高。
3 首页--复杂版
-
刚进入页面,获取最新的前5条。id倒序 切片[:5] 或id 正序 切片[-5:]
-
下拉刷新--获取最新
-
全局配置
{ "window": { "backgroundTextStyle": "dark", "navigationBarTitleText": "大保健", "enablePullDownRefresh": false // 所有页面 } }
-
局部配置
{ "usingComponents": {}, "enablePullDownRefresh": true }
-
停止当前页面下拉刷新 动作
wx.stopPullDownRefresh();
-
-
上滑翻页--获取历史
# 问题:onReachBottom()的触发:
1.如果你页面的内容不填满整个页面是触发不了onreachbottom的,
页面高度超过屏幕(出现滚动条)时才可能触发onReachBottom事件
2.“在触发距离内滑动期间,本事件只会被触发一次”
上拉触发该事件一次后,如果页面没有回到触发距离以外(即滑回去足够距离),
再怎么上拉都不会重新触发该事件,必须滑上去再滑下来才行。所以并不是任意滑动都能触发事件。
- 后端
# 小程序端的数据筛选:
原本前端数据展示,是根据分页展示的;
但小程序端有不适用:
1.不是分页展示,数据是根据上拉下滑操作逐渐增加的
2.首页先是展示五条,若此时新增一条,第一页的第五条数据,变成第二页的第六条数据,
下滑获取历史时,此时展示第二页数据,就会重复第五条数据
# 解决核心思想:
小程序端数据展示,不用分页类,而是手动记录最大最小id,然后使用过滤类 进行过滤
- 下拉刷新--获取最新:记录当前的max_id,刷新时,后端 大于max_id,再取10条或全部
- 上滑翻页--获取历史:记录当前的min_id,刷新时,后端 小于min_id,再取10条或全部
# 老师版 (有问题,下滑获取历史没有效果,因为首次获取就全部的数据了,没有id更小的数据)
class ReachBottomFilter(BaseFilterBackend):
def filter_queryset(self, request, queryset, view):
min_id = request.query_params.get('minId')
if not min_id:
return queryset
return queryset.filter(id__lt=min_id)
class PullDownRefreshFilter(BaseFilterBackend):
def filter_queryset(self, request, queryset, view):
max_id = request.query_params.get('maxId')
if not max_id:
return queryset
return queryset.filter(id__gt=max_id).reverse()
# 自己版 (两种过滤,下拉和上滑写在一起,但每次都只返回5条)
class PageFilter(BaseFilterBackend):
def filter_queryset(self, request, queryset, view):
max_id = request.query_params.get('maxId') # 获取条件值
min_id = request.query_params.get('minId')
# 如果有max_id, 说明是下拉更新,则返回大于该id的五条数据
if max_id:
queryset = queryset.filter(id__gt=max_id)
# 如果有min_id, 说明是上滑历史,则返回小于该id的五条数据
if min_id:
queryset = queryset.filter(id__lt=min_id)
return queryset[:5] # 返回过滤完的5条数据
4 文章详细页面
- 展示详细信息
- 轮播图
- 新闻信息
- 在页面上展示所有的一级评论
- 添加一条评论
- 多级评论(不用做)