Flask 与小程序 的图片数据交互 过程及探讨研究学习

今天不知道怎么的,之前拿编程浪子地作品抄过来粘上用好好的,昨天开始照片突的就不显示了。

今天不妨再耐味地细细探究一下微信小程序wxml 和flask服务器端是怎么jpg图片数据交互的。

mina/pages/food/index.wxml

XML 复制代码
<!--index.wxml-->
<!--1px = 750/320 = 2.34rpx;-->
<view class="container">
  <!--轮播图-->
  <view class="swiper-container">
    <swiper class="swiper_box" autoplay="{{autoplay}}" interval="{{interval}}" duration="{{duration}}" bindchange="swiperchange">
      <block wx:for="{{banners}}" wx:key="id">
        <swiper-item>
          <image bindtap="tapBanner" data-id="{{item.id}}" src="{{item.pic_url}}" class="slide-image" width="750rpx" height="562.5rpx" />
        </swiper-item>
      </block>
    </swiper>
    <view class="dots">
      <block wx:for="{{banners}}" wx:key="unique">
        <view class="dot{{index == swiperCurrent ? ' active' : ''}}"></view>
      </block>
    </view>
  </view>
  <!--分类展示-->
  <view class="type-container">
    <scroll-view class="type-navbar" scroll-x="true">
      <view class="type-box" wx:for-items="{{categories}}" wx:key="id">
        <view id="{{item.id}}" class="type-navbar-item {{activeCategoryId == item.id ? 'type-item-on' : ''}}" bindtap="catClick">
          {{item.name}}
        </view>
      </view>
<!--      这段代码是一个小程序中的一个视图组件,它使用了小程序的模板语法。具体来说,这段代码定义了一个视图组件,其中包含一个view标签,
        该标签具有id属性和class属性,并且绑定了一个tap事件处理函数"catClick"。
    在view标签内部,使用了双花括号语法来插入动态数据,其中item.id和item.name是动态的数据,根据实际情况进行渲染。-->
    </scroll-view>
  </view>
  <!--搜索框-->
  <view class="search-view" style="background:{{ scrollTop === 0 ?'-webkit-linear-gradient(top, rgba(105,195,170, 1), rgba(105,195,170, 0.3))' :( scrollTop<200 ? 'rgba(105,195,170,'+(scrollTop/400+0.3) +')' : 'rgba(105,195,170,1)')  }} ">
    <view class="search-content">
      <image src="/images/search-pic.png" class="search-icon" />
      <input placeholder="请输入搜索内容" class="search-input" maxlength="30" confirm-type="搜索" bindinput='listenerSearchInput'>
      </input>
      <button class='search-btn' bindtap="toSearch">搜索</button>
    </view>
  </view>

  <view class="goods-container">
    <!--    wx:for-items="{{goods}}" 是一个循环遍历的功能,将 goods 数组中的每个元素都渲染成一个 goods-box 组件。-->
    <view class="goods-box" wx:for-items="{{goods}}"  bindtap="toDetailsTap" data-id="{{item.id}}">
      <view class="img-box">
        <image src="{{item.pic_url}}" class="image" mode="aspectFill" lazy-load="true" />
      </view>
      <view class="goods-title">{{item.name}}</view>
      <view style='display:flex;'>
        <view class="goods-price">¥ {{item.min_price}}</view>
        <view wx:if="{{item.price && item.price > 0 && item.min_price != item.price}}" class="goods-price" style='color:#aaa;text-decoration:line-through'>¥ {{item.price}}</view>
      </view>
    </view>
  </view>
  <view hidden="{{loadingMoreHidden ? true : false}}" class="no-more-goods">哥也是有底线的</view>
</view>

如上例代码所示,图片的展示是通过一个image src='{{item.pic_url}}'标签引入的。通常情况下,item是一个对象或数组,它包含了多个属性,其中pic_url就是其中一个属性。在这个例子中,item.pic_url表示图片的URL地址,通过该地址可以加载并显示对应的图片。

总之,image 标签是小程序中用于显示图片的组件,通过 src="{``{item.pic_url}}" 绑定了图片的地址。追根溯源,找goods数组是从哪里传来的。

goods数组是通过小程序端地js文件绑定的一个getBannerAndCat()函数,并将其设置在onshow生命周期里,通过调用getFoodList(),自动进行的数据读取和刷新。

javascript 复制代码
 //解决切换不刷新维内托,每次展示都会调用这个方法
    onShow:function(){
        this.getBannerAndCat();
    },
问题: 这个item对象或数组从何而来?是小程序端的js文件吗?

mina/pages/food/index.js

javascript 复制代码
//index.js
//获取应用实例
var app = getApp();
Page({
    data: {
        indicatorDots: true,
        autoplay: true,
        interval: 3000,
        duration: 1000,
        loadingHidden: false, // loading
        swiperCurrent: 0,
        categories: [],
        activeCategoryId: 0,
        goods: [],
        scrollTop: "0",
        loadingMoreHidden: true,
        searchInput: '',
        p:1,
        processing:false
    },
    onLoad: function () {
        var that = this;
        wx.setNavigationBarTitle({
            title: app.globalData.shopName
        });
    },
    //解决切换不刷新维内托,每次展示都会调用这个方法
    onShow:function(){
        this.getBannerAndCat();
    },
    scroll: function (e) {
        var that = this, scrollTop = that.data.scrollTop;
        that.setData({
            scrollTop: e.detail.scrollTop
        });
    },
    //事件处理函数
    swiperchange: function (e) {
        this.setData({
            swiperCurrent: e.detail.current
        })
    },
    listenerSearchInput:function( e ){
        this.setData({
            searchInput: e.detail.value
        });
    },
    toSearch:function( e ){
        this.setData({
            p:1,
            goods:[],
            loadingMoreHidden:true
        });
        this.getFoodList();
	},
    // tapBanner是一个函数,它用于处理轮播图的点击事件具体的实现逻辑如下:
    tapBanner: function (e) {
        // 首先,通过e.currentTarget.dataset.id获取到当前点击的轮播图的id。
        // 然后,判断id是否为0,如果不为0,则执行以下操作:
        if (e.currentTarget.dataset.id != 0) {
            // 使用wx.navigateTo函数进行页面跳转,跳转到指定的页面。
            wx.navigateTo({
                // 跳转的目标页面是"/pages/food/info",并且通过url参数传递了点击轮播图的id,参数名为id。
                url: "/pages/food/info?id=" + e.currentTarget.dataset.id
            });
        //     这段代码的作用是当用户点击轮播图,如果轮播图的id不为0,则跳转到指定的页面,并将点击轮播图的id作为参数传递给标页面。
        }
    },
    // toDetailsTap是一个函数,它是在小程序中用于点击事件的回调函数。当触发点击事件时,会执行该函数。
    toDetailsTap: function (e) {
        // 该函数的作用是跳转到指定的页面。在函数内部,通过调用wx.navigateTo方法来实现页面跳转。
        // 其中,url参数指定了跳转的目标页面路径,通过拼接字符串的方式将参数id传递给目标页面。
        // 总结一下,toDetailsTap函数的作用是在点击事件发生时,跳转到指定的页面,并将参数id传递给目标页面。
        wx.navigateTo({
            url: "/pages/food/info?id=" + e.currentTarget.dataset.id
        });
    },
    getBannerAndCat: function () {
        var that = this;
        // 使用微信小程序的wx.request方法发送一个请求。
        wx.request({
            // 请求的URL是通过app.buildUrl("/food/index")方法构建的
            url: app.buildUrl("/food/index"),
            // 请求头部信息通过app.getRequestHeader()方法获取
            header: app.getRequestHeader(),
            // 请求成功后,会将返回的数据保存在resp变量中。
            success: function (res) {
                var resp = res.data;
                // 如果返回的code不等于200,会通过app.alert方法弹出一个提示框显示返回的错误信息,并结束函数的执行。
                if (resp.code != 200) {
                    app.alert({"content": resp.msg});
                    return;
                }
                // 如果返回的code等于200,会将返回的banner_list和cat_list数据分别保存在banners和categories变量中,
                that.setData({
                    banners: resp.data.banner_list,
                    categories: resp.data.cat_list
                });
                // 并调用getFoodList方法
                that.getFoodList();
            }
        });
    },
    // 这段代码是一个小程序中的一个函数,名为catClick。它的作用是在点击某个分类时,根据点击的分类id更新数据,并调用getFoodList函数获取对应分类的商品列表。
    catClick: function (e) {
        this.setData({
            // 通过e.currentTarget.id获取点击的分类id。
            activeCategoryId: e.currentTarget.id
        });
        // 使用setData方法更新数据,将activeCategoryId设置为点击的分类id。
        this.setData({
            // 将loadingMoreHidden设置为true,p设置为1(表示当前页数为1),goods设置为空数组(清空商品列表)。
            loadingMoreHidden: true,
            p:1,
            goods:[]
        });
        // 调用getFoodList函数获取对应分类的商品列表。
        this.getFoodList();
    },
    onReachBottom: function () {
        var that = this;
        setTimeout(function () {
            that.getFoodList();
        }, 500);
    },
    // 通过发送请求获取食品列表,并将获取到的数据更新到页面上。
    getFoodList: function () {
        var that = this;
        // 首先,函数会检查是否正在处理其他请求,如果是,则直接返回,避免重复请求。
        if( that.data.processing ){
            return;
        }
        // 接着,函数会检查是否还有更多数据需要加载,如果没有,则直接返回。
        if( !that.data.loadingMoreHidden ){
            return;
        }
        // 然后,函数会将processing标志设置为true,表示正在处理请求。
        that.setData({
            processing:true
        });
        // 接下来,函数会发送一个请求到服务器,请求的URL是"/food/search",并且会带上一些参数,
        // 如cat_id(食品分类ID)、mix_kw(搜索关键词)、p(页码)等。
        wx.request({
            url: app.buildUrl("/food/search"),
            header: app.getRequestHeader(),
            data: {
                cat_id: that.data.activeCategoryId,
                mix_kw: that.data.searchInput,
                p: that.data.p,
            },
            // 当服务器返回响应时,函数会判断响应的状态码是否为200,如果不是,则弹出一个提示框显示错误信息,并返回。
            success: function (res) {
                var resp = res.data;
                if (resp.code != 200) {
                    app.alert({"content": resp.msg});
                    return;
                }
                // 如果响应的状态码为200,则从响应数据中获取到食品列表,并将其与之前已有的食品列表进行合并。
                var goods = resp.data.list;
                that.setData({
                    goods: that.data.goods.concat( goods ),
                    p: that.data.p + 1,
                    //最后,函数会更新页面上的数据,包括goods(食品列表)、p(页码)和processing(处理状态),
                    // 并将processing标志设置为false,表示请求处理完成。
                    processing:false
                });
                // 判断变量resp.data.has_more的值是否为0。如果resp.data.has_more的值为0,
                // 则执行setData方法,将loadingMoreHidden属性设置为false。
                if( resp.data.has_more == 0 ){
                    that.setData({
                        loadingMoreHidden: false
                    });
                }

            }
        });
    }
});

那接下来,就去flask服务器端看看/food/search路由是什么情况,图片传参是怎么传的。

web/controllers/api/Food.py

python 复制代码
@route_api.route("/food/search" )
def foodSearch():
    resp = {'code': 200, 'msg': '操作成功~', 'data': {}}
    req = request.values
    cat_id = int( req['cat_id'] ) if 'cat_id' in req else 0
    mix_kw = str(req['mix_kw']) if 'mix_kw' in req else ''
    p = int( req['p'] ) if 'p' in req else 1

    if p < 1:
        p = 1

    page_size = 10
    offset = ( p - 1 ) * page_size
    query = Food.query.filter_by(status=1 )
    if cat_id > 0:
        query = query.filter_by(cat_id = cat_id)

    if mix_kw:
        rule = or_(Food.name.ilike("%{0}%".format(mix_kw)), Food.tags.ilike("%{0}%".format(mix_kw)))
        query = query.filter(rule)

    food_list = query.order_by(Food.total_count.desc(), Food.id.desc())\
        .offset( offset ).limit( page_size ).all()

    data_food_list = []
    if food_list:
        for item in food_list:
            tmp_data = {
                'id': item.id,
                'name': "%s"%( item.name ),
                'price': str( item.price ),
                'min_price':str( item.price ),
                'pic_url': UrlManager.buildImageUrl(item.main_image)
            }
            data_food_list.append(tmp_data)
    resp['data']['list'] = data_food_list
    resp['data']['has_more'] = 0 if len( data_food_list ) < page_size else 1
    return jsonify(resp)

common/libs/UrlManager.py

python 复制代码
# -*- coding: utf-8 -*-
import time
from app import app
class UrlManager(object):
    def __init__(self):
        pass
 
    @staticmethod
    def buildImageUrl( path ):
        app_config = app.config['APP']
        url = app_config['domain'] + app.config['UPLOAD']['prefix_url'] + path
        return url
相关推荐
朱友斌5 分钟前
【Golang笔记01】Golang基础语法规则
笔记·学习·golang·go语言·golang笔记
摇摇奶昔x5 分钟前
webpack 学习
前端·学习·webpack
海尔辛29 分钟前
学习黑客Kerberos深入浅出:安全王国的门票系统
学习·安全·kerberos·window
霸王蟹37 分钟前
React 19中如何向Vue那样自定义状态和方法暴露给父组件。
前端·javascript·学习·react.js·typescript
Moonnnn.1 小时前
【数字电路】第七章 脉冲波形的产生与整形电路
笔记·学习
猴子请来的逗比4892 小时前
tomcat查看状态页及调优信息
服务器·学习·tomcat·firefox
贺函不是涵3 小时前
【沉浸式求职学习day43】【Java面试题精选3】
java·开发语言·学习
maray3 小时前
ETL 学习
数据仓库·学习·etl
海尔辛3 小时前
学习黑客Active Directory入门
学习·ad·window
superior tigre4 小时前
C++学习:六个月从基础到就业——C++20:协程(Coroutines)
c++·学习·c++20