uniapp 微信小程序自定义分享图片

news2024/11/17 16:29:35

场景:微信小程序用户,点击小程序里商品的分享按钮时,想要不同的商品展示不用的分享内容,比如分享图片上展示商品的图片、价格等信息。分享的UI图如下: 

 

实现方法:

1. 分享按钮:<button open-type="share">onShareAppMessage(OBJECT)

2. 自定义内容:因为onShareAppMessage的imageUrl参数的支持的是本地文件路径、代码包文件路径或者网络图片路径 ,所以这里实现自定义的分享的方法是结合canvas画布uni.createCanvasContext(canvasId, this),将画好的内容利用uni.canvasToTempFilePath(object, component)导出生成指定大小的图片,再将返回的文件路径赋值给imageUrl,即可实现。

 具体可看官网:分享 | uni-app官网 、uni.createCanvasContext(canvasId, this) | uni-app官网、uni-app官网、uni.canvasToTempFilePath(object, component) | uni-app官网

代码:先贴上画布的代码,这里画了三种自定义分享的内容,样式在代码下方。

1. 新建一个组件文件:ShareCanvas.vue

<template>
  <view class="ShareCanvas">
    <view class="canvas">
      <canvas canvas-id="shareCanvas" />
    </view>
  </view>
</template>

<script>
export default {
  name: 'ShareCanvas',
  methods: {
    // 订单分享
    setOrderCanvas(info) {
      return new Promise(async (resolve, reject) => {
        console.log('订单分享-info', info);
        try {
          const ctx = uni.createCanvasContext('shareCanvas', this)
          // 绘制背景图
          ctx.setFillStyle('#19C161')
          ctx.fillRect(0, 0, 211, 170) // 保证宽高比是 5:4

          // 绘制文本信息
          ctx.setFontSize(21);
          ctx.setTextAlign('left')
          ctx.setFillStyle('#FFFFFF')
          ctx.fillText('我买好啦!', 9, 32)

          // 浅绿色背景
          this.setRadius(ctx, 10, 106, 11, 97, 27) // 加圆角
          ctx.setFillStyle('#EFF9F1')
          ctx.fill()
          // ctx.fillRect(106, 11, 97, 27) // x, y, width, height

          ctx.setFontSize(14);
          ctx.setTextAlign('center')
          ctx.setFillStyle('#19C161')
          ctx.fillText('跟团号:' + info.followNum, 155, 30)

          this.setRadius(ctx, 3, 9, 49, 194, 106)
          ctx.setFillStyle('#FFFFFF')
          ctx.fill()
          // ctx.fillRect(9, 49, 194, 106) // 不设置圆角的时候这么画有背景色的矩形

          // 画商品图
          ctx.save();
          this.setRadius(ctx, 5, 17, 59, 85, 85)
          ctx.clip();//画了圆 再剪切 原始画布中剪切任意形状和尺寸。一旦剪切了某个区域,则所有之后的绘图都会被限制在被剪切的区域内
          try {
            const { path } = await this.getImge(info.orderCartInfos[0].productImg)
            ctx.drawImage(path, 17, 59, 85, 85)
          } catch (error) {
            console.error(error);
          }
          ctx.restore();

          if (info.teamLeaderUser && info.teamLeaderUser.avatar) {
            // 团长头像
            ctx.save();
            this.setRadius(ctx, 5, 110, 60, 25, 25)
            ctx.clip(); // 画了圆 再剪切 原始画布中剪切任意形状和尺寸。一旦剪切了某个区域,则所有之后的绘图都会被限制在被剪切的区域内
            try {
              const { path } = await this.getImge(info.teamLeaderUser.avatar)
              ctx.drawImage(path, 110, 60, 25, 25)
            } catch (error) {
              console.error(error);
            }
            ctx.restore();
          }

          if (info.teamLeaderUser && info.teamLeaderUser.nickname) {
            // 团长昵称
            ctx.setFontSize(12);
            ctx.setTextAlign('left')
            ctx.setFillStyle('#96999B')
            ctx.fillText(info.teamLeaderUser.nickname.length > 4 ? info.teamLeaderUser.nickname.slice(0, 4) + '...' : info.teamLeaderUser.nickname, 140, 76)
          }

          ctx.setFontSize(14);
          ctx.setTextAlign('center')
          ctx.setFillStyle('#FB7415')
          ctx.fillText(`¥${info.orderCartInfos[0].unitPrice}`, 152, 105)

          this.setRadius(ctx, 10, 115, 118, 75, 26)

          const grd = ctx.createLinearGradient(115, 118, 115, 144)
          grd.addColorStop(0, '#FDAC2F')
          grd.addColorStop(0.5, '#FDA72C')
          grd.addColorStop(1, '#FB5615')

          // 橙色按钮背景
          ctx.setFillStyle(grd)
          // ctx.fillRect(230/2, 218/2, 149/2, 53/2) // x, y, width, height
          ctx.fill()

          ctx.setFontSize(12);
          ctx.setTextAlign('center')
          ctx.setFillStyle('#FFFFFF')
          ctx.fillText('去看看 >', 152, 135)

          ctx.draw(false, (() => {
            setTimeout(() => {
              uni.canvasToTempFilePath({
                canvasId: 'shareCanvas',
                success: (res) => {
                  return resolve(res.tempFilePath)
                },
                fail: function (error) {
                  console.log('fail----fail', error);
                  //TODO
                  return reject(error)
                }
              }, this)
            }, 500);
          }))
        } catch (error) {
          console.log('画图失败error', error);
          return reject(error)
        }
      })
    },
    // 商品分享
    setGoodsShareCanvas(info) {
      console.log('商品分享--info', info);
      return new Promise(async (resolve, reject) => {
        try {
          const ctx = uni.createCanvasContext('shareCanvas', this)
          // 绘制背景图
          ctx.setFillStyle('#FFFFFF')
          ctx.fillRect(0, 0, 211, 170)

          // 团长头像
          ctx.save();
          this.setRadius(ctx, 5, 0, 0, 30, 30)
          ctx.clip(); // 画了圆 再剪切 原始画布中剪切任意形状和尺寸。一旦剪切了某个区域,则所有之后的绘图都会被限制在被剪切的区域内
          try {
            const { path } = await this.getImge(info.avatar)
            ctx.drawImage(path, 0, 0, 30, 30)
          } catch (error) {
            console.error(error);
          }
          ctx.restore();

          // 团长昵称
          ctx.setFontSize(12);
          ctx.setTextAlign('left')
          ctx.setFillStyle('#96999B')
          ctx.fillText(info.nickname.length > 11 ? info.nickname.slice(0, 11) + `${info.pinkId ? '...的团' : '...'}` : info.nickname + '的团', 35, 18)

          // 商品1图
          ctx.save();
          this.setRadius(ctx, 3, 0, 35, 211, 211)
          ctx.clip(); // 画了圆 再剪切 原始画布中剪切任意形状和尺寸。一旦剪切了某个区域,则所有之后的绘图都会被限制在被剪切的区域内
          try {
            const { path } = await this.getImge(info.image)
            ctx.drawImage(path, 0, 35, 211, 211)
          } catch (error) {
            console.error(error);
          }
          ctx.restore();

          // 绿色背景
          ctx.setFillStyle('#19C161')
          ctx.fillRect(0, 130, 131, 40) // x, y, width, height

          ctx.setFontSize(16);
          ctx.setTextAlign('center')
          ctx.setFillStyle('#FFFFFF')
          ctx.fillText(`¥${info.pinkId ? info.pinkPrice : info.price}起`, 65, 130 + 18)

          ctx.setFontSize(12);
          ctx.setTextAlign('center')
          ctx.setFillStyle('#FFFFFF')
          ctx.fillText(`¥${info.otPrice}`, 65, 130 + 34)

          // 划线
          ctx.beginPath()
          ctx.setLineWidth(1);
          ctx.setStrokeStyle('#FFFFFF')
          ctx.moveTo(40, 130 + 30)
          ctx.lineTo(90, 130 + 30)
          ctx.stroke()

          // 深绿色背景
          ctx.setFillStyle('#19AF5C')
          ctx.fillRect(131, 130, 211 - 131, 40)

          if (info.pinkId) {
            // 立即跟团按钮
            ctx.setFontSize(16);
            ctx.setTextAlign('center')
            ctx.setFillStyle('#FFFFFF')
            ctx.fillText(`立即跟团`, 131 + (211 - 131) / 2, 130 + 26)
          } else {
            // 已团数量
            ctx.setFontSize(12);
            ctx.setTextAlign('center')
            ctx.setFillStyle('#FFFFFF')
            ctx.fillText(`已团 ${this.getSales(info.sales)} 件`, 131 + (211 - 131) / 2, 130 + 25)
          }

          ctx.draw(false, (() => {
            uni.canvasToTempFilePath({
              canvasId: 'shareCanvas',
              success: (res) => {
                return resolve(res.tempFilePath)
              },
              fail: function (error) {
                console.log('fail----fail', error);
                //TODO
                return reject(error)
              }
            }, this)
          }))
        } catch (error) {
          uni.hideLoading()
          console.log('画图失败error', error);
          return reject(error)
        }
      })
    },
    // 团分享
    setGroupShareCanvas(info) {
      console.log('团分享-info', info);
      return new Promise(async (resolve, reject) => {
        try {
          const ctx = uni.createCanvasContext('shareCanvas', this)
          // 绘制背景图
          ctx.setFillStyle('#FFFFFF')
          ctx.fillRect(0, 0, 211, 170)

          if (info.productImageList.length == 1) {
            // 团长头像
            ctx.save();
            this.setRadius(ctx, 5, 0, 0, 30, 30)
            ctx.clip(); // 画了圆 再剪切 原始画布中剪切任意形状和尺寸。一旦剪切了某个区域,则所有之后的绘图都会被限制在被剪切的区域内
            try {
              const { path } = await this.getImge(info.avatar)
              ctx.drawImage(path, 0, 0, 30, 30)
            } catch (error) {
              console.error(error);
            }
            ctx.restore();

            // 团长昵称
            ctx.setFontSize(12);
            ctx.setTextAlign('left')
            ctx.setFillStyle('#96999B')
            ctx.fillText((info.nickname.length > 11 ? info.nickname.slice(0, 11) + '...' : info.nickname) + '的团', 35, 18)

            // 商品1图
            ctx.save();
            this.setRadius(ctx, 3, 0, 35, 211, 211)
            ctx.clip(); // 画了圆 再剪切 原始画布中剪切任意形状和尺寸。一旦剪切了某个区域,则所有之后的绘图都会被限制在被剪切的区域内
            try {
              const { path } = await this.getImge(info.productImageList[0])
              ctx.drawImage(path, 0, 35, 211, 211)
            } catch (error) {
              console.error(error);
            }
            ctx.restore();
          }

          if (info.productImageList.length >= 2) {
            // 团长头像
            ctx.save();
            this.setRadius(ctx, 5, 0, 0, 42, 42)
            ctx.clip(); // 画了圆 再剪切 原始画布中剪切任意形状和尺寸。一旦剪切了某个区域,则所有之后的绘图都会被限制在被剪切的区域内
            try {
              const { path } = await this.getImge(info.avatar)
              ctx.drawImage(path, 0, 0, 42, 42)
            } catch (error) {
              console.error(error);
            }
            ctx.restore();

            // 团长昵称
            ctx.setFontSize(12);
            ctx.setTextAlign('left')
            ctx.setFillStyle('#96999B')
            ctx.fillText((info.nickname.length > 10 ? info.nickname.slice(0, 10) + '...' : info.nickname) + '的团', 47, 25)

            // 商品1图
            ctx.save();
            this.setRadius(ctx, 3, 0, 51, 69, 69)
            ctx.clip(); // 画了圆 再剪切 原始画布中剪切任意形状和尺寸。一旦剪切了某个区域,则所有之后的绘图都会被限制在被剪切的区域内
            try {
              const { path } = await this.getImge(info.productImageList[0])
              ctx.drawImage(path, 0, 51, 69, 69)
            } catch (error) {
              console.error(error);
            }
            ctx.restore();

            // 商品2图
            ctx.save();
            this.setRadius(ctx, 3, 69 + 2, 51, 69, 69)
            ctx.clip(); // 画了圆 再剪切 原始画布中剪切任意形状和尺寸。一旦剪切了某个区域,则所有之后的绘图都会被限制在被剪切的区域内
            try {
              const { path } = await this.getImge(info.productImageList[1])
              ctx.drawImage(path, 69 + 2, 51, 69, 69)
            } catch (error) {
              console.error(error);
            }
            ctx.restore();

            if (info.productImageList.length >= 3) {
              // 商品3图
              ctx.save();
              this.setRadius(ctx, 3, 69 * 2 + 4, 51, 69, 69)
              ctx.clip(); // 画了圆 再剪切 原始画布中剪切任意形状和尺寸。一旦剪切了某个区域,则所有之后的绘图都会被限制在被剪切的区域内
              try {
                const { path } = await this.getImge(info.productImageList[2])
                ctx.drawImage(path, 69 * 2 + 4, 51, 69, 69)
              } catch (error) {
                console.error(error);
              }
              ctx.restore();
            }
          }

          // 绿色背景
          ctx.setFillStyle('#19C161')
          ctx.fillRect(0, 128, 211, 42) // x, y, width, height

          ctx.setFontSize(16);
          ctx.setTextAlign('center')
          ctx.setFillStyle('#FFFFFF')
          ctx.fillText(`立即跟团`, 211 / 2, 128 + 26)

          ctx.draw(false, (() => {
            uni.canvasToTempFilePath({
              canvasId: 'shareCanvas',
              success: (res) => {
                return resolve(res.tempFilePath)
              },
              fail: function (error) {
                console.log('fail----fail', error);
                //TODO
                return reject(error)
              }
            }, this)
          }))
        } catch (error) {
          console.log('画图失败error', error);
          return reject(error)
        }
      })
    },
    /**
     * 设置圆角矩形
     *
     * @param ctx 绘图上下文
     * @param cornerRadius 圆角半径
     * @param width 矩形宽度
     * @param height 矩形高度
     * @param x 矩形左上角的 x 坐标
     * @param y 矩形左上角的 y 坐标
     * @returns 无返回值
     */
    setRadius(ctx, cornerRadius, x, y, width, height) {
      // 开始绘制路径
      ctx.beginPath();
      // 绘制最左侧的圆角
      ctx.arc(x + cornerRadius, y + cornerRadius, cornerRadius, Math.PI, Math.PI * 1.5);
      // 绘制顶部边缘
      ctx.moveTo(x + cornerRadius, y);
      ctx.lineTo(x + width - cornerRadius, y);
      ctx.lineTo(x + width, y + cornerRadius);
      // 绘制最右侧的圆角
      ctx.arc(x + width - cornerRadius, y + cornerRadius, cornerRadius, Math.PI * 1.5, Math.PI * 2);
      // 绘制右侧边缘
      ctx.lineTo(x + width, y + height - cornerRadius);
      ctx.lineTo(x + width - cornerRadius, y + height);
      // 绘制最下侧的圆角
      ctx.arc(x + width - cornerRadius, y + height - cornerRadius, cornerRadius, 0, Math.PI * 0.5);
      // 绘制底部边缘
      ctx.lineTo(x + cornerRadius, y + height);
      ctx.lineTo(x, y + height - cornerRadius);
      // 绘制最左侧的圆角
      ctx.arc(x + cornerRadius, y + height - cornerRadius, cornerRadius, Math.PI * 0.5, Math.PI);
      // 绘制左侧边缘
      ctx.lineTo(x, y + cornerRadius);
      ctx.lineTo(x + cornerRadius, y);
      // 闭合路径
      ctx.closePath();
    },
    // 获取图片地址
    getImge(path) {
      // 利用promise异步转同步,否则可能显示不了~
      return new Promise((resolve, reject) => {
        uni.getImageInfo({
          src: path,
          success: function (res) {
            if (res && res.path) {
              resolve(res)
            } else {
              reject(false)
            }
          },
          fail: function (res) {
            reject(res)
          }
        })
      })
    },
    getSales(sales) {
      return sales >= 10000 ? sales / 10000 + 'w+' : sales
    },
  }
}
</script>

<style lang="scss" scoped>
// 隐藏画布
.ShareCanvas {
  position: absolute;
  top: -200px;
  z-index: -1;
  opacity: 0;
  .canvas canvas {
    width: 211px;
    height: 170px; // +16
  }
}
</style>

2. 在分享按钮的页面使用这个画布组件。

onShareAppMessage 方法的内容:

注意:

  1. onShareAppMessage 方法要和 onLoad 等生命周期函数同级
  2. 因为里面画布生成图片是异步的,我在上面用Promise处理了,这里需要async await接收~
async onShareAppMessage(res) {
    const { id, title, avatar, nickname, productDetailList } = this.detailInfo
    if (res.target && res.target.id) { // 分享商品
      console.log('分享商品');
      const item = productDetailList.find(p => p.id == res.target.id) || {}
      try {
        uni.showLoading({ title: '分享信息生成中', mask: true })
        const imageUrl = await this.$refs.ShareCanvas.setGoodsShareCanvas({ ...item, avatar, nickname, pinkId: id }) // 用不同的画布画样式,就调对应的方法名,注意里面需要的参数要传对
        uni.hideLoading()
        return {
          title: item.storeName || '好物多多,快来选购啦~',
          path: '/pages/home/index', // 这里是你的分享里面的跳转地址
          imageUrl: imageUrl || ''
        }
      } catch (error) {
        uni.hideLoading()
      }
    } else {
      // 分享团
      console.log('分享团', productDetailList);
      try {
        uni.showLoading({ title: '分享信息生成中', mask: true })
        const productImageList = productDetailList.map(item => item.image)
        const imageUrl = await this.$refs.ShareCanvas.setGroupShareCanvas({ avatar, nickname, productImageList }) // 用不同的画布画样式,就调对应的方法名,注意里面需要的参数要传对
        uni.hideLoading()
        return {
          title: title || '好物多多,快来选购啦~',
          path: '/pages/home/index', // 这里是你的分享里面的跳转地址
          imageUrl: imageUrl || ''
        }
      } catch (error) {
        uni.hideLoading()
      }
    }
  },

setOrderCanvas()方法的样式 

 

setGoodsShareCanvas()方法的样式

setGroupShareCanvas()方法的样式

画画的时候,要是找不准xy的位置,可以从这三种样式里选一个样式接近的再慢慢修改~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1839116.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

朋友圈新功能:实现定时发圈,自动跟圈

1.多号同时发圈 可以选择多个号同时发圈&#xff0c;提高工作效率。 2.定时发布 可以一次性设置完很多天的朋友圈&#xff0c;选好发送时间就可以解放双手。 3.一键转发 点击转发&#xff0c;可直接跳转到编辑页面。无需复制粘贴。 4.自动转发&#xff08;跟圈&#xff09; …

ATFX汇市:英国5月核心CPI年率下降0.4百分点,GBPUSD不跌反涨

ATFX汇市&#xff1a;据英国统计局数据&#xff0c;英国5月核心CPI年率为3.5%&#xff0c;低于前值3.9%&#xff1b;英国5月名义CPI年率为2%&#xff0c;低于前值2.3%。核心CPI年率和名义CPI年率相比前值分别下降0.4个百分点和0.3百分点&#xff0c;意味着英国的通胀率仍处于快…

android中的JNI的DEMO

一&#xff1a;源代码 native-lib.cpp #include "native-lib.h"JNIEXPORT jint JNICALL Java_com_example_jnidemo_MainActivity_add(JNIEnv* env, jobject, jint a, jint b) {return a b; }JNIEXPORT jint JNICALL Java_com_example_jnidemo_MainActivity_subtra…

【Win】双系统新体验:Hyper-V上macOS安装攻略

在虚拟化的世界里&#xff0c;Hyper-V是探索不同操作系统的一扇大门。尽管macOS并不是Hyper-V官方支持的来宾操作系统&#xff0c;但这并未阻挡技术探索者的脚步。他们通过不懈努力&#xff0c;开辟出了一条条通往macOS的非官方路径。这些路径或许曲折&#xff0c;却为那些渴望…

《QT从基础到进阶·七十二》基于Qt开发的文件保险柜工具并支持文件各种加密和解密

1、概述 源码放在文章末尾 该项目实现了文件各种加密和解密的功能&#xff0c;能够有效的保障文件的安全&#xff0c;主要包含如下功能&#xff1a; 1、支持所有 AES 密钥长度&#xff1b; AES_128 AES_192 AES_256 2、支持ECB、CBC、CFB、OFB四种模式&#xff1b; 3、支持ZER…

【学习】程序员资源网站

1 书栈网 简介&#xff1a;书栈网是程序员互联网IT开源编程书籍、资源免费阅读的网站&#xff0c;在书栈网你可以找到很多书籍、笔记资源。在这里&#xff0c;你可以根据热门收藏和阅读查看大家都在看什么&#xff0c;也可以根据技术栈分类找到对应模块的编程资源&#xff0c;…

构建高效的大数据量延迟任务调度平台

目录 引言系统需求分析系统架构设计 总体架构任务调度模块任务存储模块任务执行模块 任务调度算法 时间轮算法优先级队列分布式锁 数据存储方案 关系型数据库NoSQL数据库混合存储方案 容错和高可用性 主从复制数据备份与恢复故障转移 性能优化 水平扩展缓存机制异步处理 监控与…

深度解析“科技信贷”:构建科技支行的五维模型

科技信贷是指金融机构为支持科技创新、技术改造和设备更新等领域提供的专项信贷服务&#xff0c;旨在促进科技企业的发展和技术的进步。科技信贷在推动科技企业和创新项目发展方面具有重要作用&#xff0c;其特点在于提供定制化的金融支持&#xff0c;以满足科技创新链条中的融…

nginx+tomcat负载均衡、动静分离群集【☆☆☆☆☆】

Nginx是一款非常优秀的HTTP服务器软件&#xff0c;性能比tomcat更优秀&#xff0c;它支持高达50 000个并发连接数&#xff0c;拥有强大的静态资源处理能力&#xff0c;运行稳定&#xff0c;内存、CPU等系统资源消耗非常低。目前很多大型网站都应用Nginx服务器作为后端网站程序的…

项目四 OpenStack身份管理

任务一 理解身份服务 1.1 •Keystone的基本概念 • 认证 &#xff08; Authentication &#xff09; —— 确认 用户身份的过程&#xff0c;又称身份验证 。 • 凭证 &#xff08; Credentials &#xff09; —— 又 称凭据&#xff0c;是用于确认用户身份的数据 。 • 令牌 …

小林图解系统-二.硬件结构 2.5CPU是如何执行任务的?

CPU如何读取数据的&#xff1f; CPU访问L1 Cache速度比访问内存快100倍&#xff0c;有高速缓存的目的&#xff1a;把Cache作为CPU与内存之间的缓存层&#xff0c;减少对内存的访问频率 所有CPU Cache Line是CPU从内存读取数据到Cache的单位。 64字节 CPU加载数组里面连续的多…

【千帆AppBuilder】你有一封邮件待查收|未来的我,你好吗?欢迎体验AI应用《未来信使》

我在百度智能云千帆AppBuilder开发了一款AI原生应用&#xff0c;快来使用吧&#xff01;「未来信使」&#xff1a;https://appbuilder.baidu.com/s/Q1VPg 目录 背景人工智能未来的信 未来信使功能介绍Prompt组件 千帆社区主要功能AppBuilderModelBuilder详细信息 推荐文章 未来…

【APP移动端性能测试】第一节.APP应用架构、环境和敏捷开发模型介绍

文章目录 前言一、APP应用架构二、APP项目环境 2.1 后端项目环境 2.2 前端项目环境三、Scrum敏捷开发模型 3.1 Scrum敏捷模型基础介绍 3.2 Scrum敏捷开发开发流程总结 前言 一、APP应用架构 &#xff08;1&#xff09;APP应用架构 &#xff08;2&#xff0…

C++240618

1> 思维导图 2> 完善对话框&#xff0c;点击登录对话框&#xff0c; 如果账号和密码匹配&#xff0c;则弹出信息对话框&#xff0c;给出**提示”登录成功“** &#xff0c;提供一个 **OK按钮**&#xff0c;用户点击**OK后**&#xff0c;**关闭登录界面**&#xff0c; 跳转…

Canonical Juju 的一个奇怪编排部署

一周前的一个项目扩容出现了异常&#xff0c;进行了操作回滚&#xff0c;未对线上业务造成损失。 现象是这样的&#xff1a; 通过基于 Canonical Juju-GUI 在一组节点上部署了某个组件&#xff0c;在把这组节点添加到集群后&#xff0c;有4个节点上出现了同一组件的2个instanc…

Postman文件数据导入导出

前言 不同的接口测试工具如Postman、Apipost、Apifox创建的接口文档都是互通的&#xff0c;都可以互相兼容使用。我们就不需要在3个不同测试工具都去创建&#xff0c;只要在一个工具上创建&#xff0c;想要在其他接口测试工具上使用就运用导入和导出功能即可。 Postman、Apip…

爆赞!GitHub首本Python开发实战背记手册,标星果然百万名不虚传

Python (发音:[ paiθ(ə) n; (US) paiθɔn ] n. 蟒蛇&#xff0c;巨蛇 )&#xff0c;是一种面向对象的解释性的计算机程序设计语言&#xff0c;也是一种功能强大而完善的通用型语言&#xff0c;已经具有十多年的发展历史&#xff0c;成熟且稳定。Python 具有脚本语言中最丰富…

【接口自动化测试】第二节.Requests库和接口对象封装

文章目录 前言一、Requests库 1.1 Requests介绍 1.2 Requests发送请求 1.3 Requests查看响应 1.4 案例1登录接口调试-获取验证码 1.5 案例2登录接口调试-登录 1.6 归纳小结二、接口对象封装 2.1 当前代码待优化问题 2.2 接口对象封装思…

互联网应用主流框架整合之SpingMVC运转逻辑及高级应用

Spring MVC处理器的执行过程 在SpringMVC的流程中&#xff0c;它会把控制器的方法封装为处理器(Handler)&#xff0c;为了更加灵活&#xff0c;SpringMVC还提供了处理器的拦截器&#xff0c;从而形成了一条包括处理器和拦截器的执行链&#xff0c;即HandlerExecutionChain&…

Linux-安装及管理程序

目录 一、Linux应用程序基础 1、应用程序与系统命令的关系 2、 典型应用程序的目录结构 3、常见的软件包封装类型 二、RPM包管理工具 1、RPM包管理器 2、RPM软件包 ​3、RPM的命令格式 4、RPM命令的常用选项 5、RPM安装 三、 yum安装 1、yum源介绍 1.1、本地yum源 …