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 发布示例效果

前端

image-20220506110732527

image-20220506110756754

后端

  • GET 获取临时COS密钥(临时密钥需要有上传和删除的权限)(APIView)

    image-20220506121816866

    • 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 首页--复杂版

image-20220514165141925

  • 刚进入页面,获取最新的前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 文章详细页面

1578909213667

  • 展示详细信息
    • 轮播图
    • 新闻信息
    • 在页面上展示所有的一级评论
    • 添加一条评论
    • 多级评论(不用做)
posted @ 2022-05-17 01:14  Edmond辉仔  阅读(284)  评论(0)    收藏  举报