vue实现聊天框自动滚动

news2024/11/18 15:43:40

需求   

        1、聊天数据实时更新渲染到页面
        2、页面高度随聊天数据增加而增加
        3、竖向滚动
        4、当用户输入聊天内容或者接口返回聊天内容渲染在页面后,自动滚动到底部
        5、提供点击事件操控滚动条上下翻动

环境依赖

        vue:@vue/cli 5.0.8

        taro:v3.4.1


实现方案

方案一:元素设置锚点,使用scrollIntoView() 方法滑动

         Element 接口的 scrollIntoView()  方法会滚动元素的父容器,使被调用 scrollIntoView()  的元素对用户可见

        1、语法
        element.scrollIntoView(); // 等同于 element.scrollIntoView(true)
        element.scrollIntoView(alignToTop); // alignToTop为Boolean 型参数,true/false
        element.scrollIntoView(scrollIntoViewOptions); // Object 型参数
        2、参数
     (1)alignToTop(可选)
        类型:Boolean

        如果为true,元素的顶端将和其所在滚动区的可视区域的顶端对齐。对应的 scrollIntoViewOptions: {block: “start”, inline: “nearest”}。该参数的默认值为true。
        如果为false,元素的底端将和其所在滚动区的可视区域的底端对齐。对应的scrollIntoViewOptions: {block: “end”, inline: “nearest”}。
      (2)scrollIntoViewOptions (可选)
        类型:对象          

        behavior 【可选】
                定义动画的过渡效果,取值为 auto/smooth。默认为 “auto”。
        block 【可选】
                定义垂直方向的对齐, 取值为 start/center/end/nearest 。默认为 “start”。
        inline 【可选】
                定义水平方向的对齐, 取值为 start/center/end/nearest。默认为 “nearest”。
       代码实现如下:

<template>
  <view class="main" id="main">
    <!--  scroll-y:允许纵向滚动   默认: false | 给scroll-view一个固定高度 |  scroll-into-view: 值应为某子元素id(id不能以数字开头)。设置哪个方向可滚动,则在哪个方向滚动到该元素 -->
    <scroll-view class="mainbody" id="mainbody" scroll-with-animation :scroll-y="true" :scroll-into-view="scrollId" style="height:960px;" :enhanced=true scrollIntoViewAlignment="center"
                 @scrolltoupper="upper" @scrolltolower="lower" @scroll="scroll" :scrollWithAnimation="true">
      <view v-for="(item, index) in contentTypeit.arr" v-bind:key="index"
            :class="['info',  'content-questionBlock']">
        <view :class="['content']" :id="item.id">{{ item.content
          }}
        </view>
      </view>
      <view @click="sendMsg" id="sendMsg"></view>
      <view @click="pageUp" id="pageUp" style="visibility: hidden;"></view>
      <view @click="pageDown" id="pageDown" style="visibility: hidden;"></view>

    </scroll-view>

  </view>
</template>

<script>
import { ref, reactive, toRaw } from 'vue'

export default {
  setup () {
    const contentTypeit = reactive({
      arr: []
    })
    const scrollId = ref('id0') //scroll ID值
    const scrollCursor = ref('id0')

    const number = ref(0)
    //https://blog.csdn.net/weixin_43398820/article/details/119963930

    // 会话内容
    // 获取对话结果
    const sendMsg = function () {
      setContent( 'dfasdfsfsafdsafsafsdfsafsdfsdfdsfsafdsfsadfsafggfdhfhfjgfjhsdgdsfgasfsafdsafsagdhgfhfdhsgdsgdsgdgafsadfdsfdsfsadfhghsdfgsafdsaf')
    }
    // 设置对话内容
    const setContent = function (msg) {
      let idValue = 'id' + number.value
      const currentObjTypeit = {
        'content': msg,
        'id': idValue
      }

      let _arr = toRaw(contentTypeit.arr)
      let _arrTmp = _arr.concat(currentObjTypeit)
      contentTypeit.arr = _arrTmp

      number.value = number.value + 1;
      scrollCursor.value = idValue
      //https://blog.csdn.net/weixin_46511008/article/details/126629361
      setTimeout(() => {
        if (number.value !== 0) {
          let idValueSlide = 'id' + (number.value - 1)
          document.getElementById(idValueSlide).scrollIntoView({
            behavior: 'smooth',
            block: 'center',
            inline: 'end'
          })
        }
      }, 100);

    }

    const scroll = function (e) {
      // console.log('scroll', e)
    }
    const upper = function (e) {
      // console.log('upper', e)
    }
    const lower = function (e) {
      // console.log('lower', e)
    }

    const pageUp = function (e) {
      console.log(scrollCursor.value)
      if (scrollCursor.value === undefined || scrollCursor.value === '' || scrollCursor.value.length < 3) {
        return;
      }

      let scrollCursorValue = scrollCursor.value.substring(2);
      console.log(scrollCursorValue);
      if (scrollCursorValue >= 1) {
        scrollCursorValue = scrollCursorValue - 1;
        scrollCursor.value = 'id' + scrollCursorValue;
      }
      setTimeout(function(){
        if (document.querySelector('#'+ scrollCursor.value) === null) {
          return;
        }
        document.querySelector('#'+ scrollCursor.value).scrollIntoView()
      }, 200);

    }
    const pageDown = function (e) {
      console.log(scrollCursor.value)
      if (scrollCursor.value === undefined || scrollCursor.value === '' || scrollCursor.value.length < 3) {
        return;
      }
      let scrollCursorValue = scrollCursor.value.substring(2);
      console.log(scrollCursorValue);
      if (scrollCursorValue < contentTypeit.arr.length - 1) {
        scrollCursorValue = scrollCursorValue -  (-1)
        scrollCursor.value = 'id' +  scrollCursorValue;
      }
      if (scrollCursorValue === contentTypeit.arr.length - 1) {
        setTimeout(function(){
          if (document.querySelector('#'+ scrollCursor.value) === null) {
            return;
          }
          document.querySelector('#'+ scrollCursor.value).scrollIntoView(false)
        }, 500);
      } else {
        setTimeout(function() {
          if (document.querySelector('#'+ scrollCursor.value) === null) {
            return;
          }
          document.querySelector('#'+ scrollCursor.value).scrollIntoView({
            behavior: "smooth", // 平滑过渡
            block: "end", // 上边框与视窗顶部平齐。默认值
          })
        }, 100);
      }
    }

    return {
      contentTypeit,
      scrollId,
      lower,
      upper,
      scroll,
      sendMsg,
      pageUp,
      pageDown,
    }
  }
}
</script>

<style lang="scss">
.main {
  height: 100%;
  width: 100%;
  background-color: rgba(204, 204, 204, 0.32);
  overflow-x: hidden;
  overflow-y: auto;
}

.mainbody {
  max-width: 100%;
  background-size: contain;
  padding-bottom: 100px;
}

.info {
  display: flex;
  margin: 10px 3%;
}
.content-question {
  color: #0b4eb4;
  background-color: #ffffff;
  padding-left: 20px;
}


.content-questionBlock {
  align-items: center;
}

.content {
  background-color: #fff;
  border-radius: 16px;
  padding: 20px;
  margin-left: 20px;
  max-width: 82%;
  height: 100%;
  font-size: 36px;
  font-family: PingFangSC-Medium, PingFang SC;
  font-weight: 500;
  color: #0a0a27;
  line-height: 60px;
  word-break: break-all;
}
</style>

        效果调试:

      (1)打开浏览器,按下F12进入调试模式;

      (2)在console窗口,多次调用document.getElementById('sendMsg').click(),使得对话内容超出界面高度,可观察到自动滚动效果;

       (3)在console窗口,调用document.getElementById('pageUp').click(),若没有滚动,可调整代码或者调用多次(取决于scrollIntoView()的参数),可观察到向上滚动;接着调用document.getElementById('pageDown').click(),可观察到向下滚动。

        效果图如下:

 方案二: 更改scrollTop取值,进行滚动        

        首先我们需要了解 clientHeightoffsetHeightscrollHeightscrollTop 的概念

        简单介绍:

                clientHeight:网页可见区域高

                offsetHeight:网页可见区域高(包括边线的高)

                scrollHeight:网页正文全文高
                scrollTop:网页被卷去的高

        具体说明:

       (1)clientHeightclientHeightclientHeight:包括padding 但不包括 border、水平滚动条、margin的元素的高度。对于inline的元素来说这个属性一直是0,单位px,为只读元素。

        简单来说就是——盒子的原始高度,具体可参考下图:

      (2)offsetHeight:包括padding、border、水平滚动条,但不包括margin的元素的高度。对于inline的元素来说这个属性一直是0,单位px,为只读元素。

        简单来说就是——盒子的原始高度+padding+border+滚动条,具体可参考下图:

       (3)scrollHeight 这个只读属性是一个元素内容高度的度量,包括由于溢出导致的视图中不可见内容。

        简单来说就是——盒子里面包含的内容的真实高度,具体可参考下图:

 

       (4)scrollTop: 代表在有滚动条时,滚动条向下滚动的距离也就是元素顶部被遮住部分的高度。在没有滚动条时 scrollTop==0 恒成立。单位px,可读可设置。

        MDN解释:一个元素的 scrollTop 值是这个元素的内容顶部(被卷起来的)到它的视口可见内容(的顶部)的距离的度量。当一个元素的内容没有产生垂直方向的滚动条,那它的 scrollTop 值为0,具体可参考下图:

         实现算法:卷起的高度(scrollTop) = 总的内容高度(scrollHeight) - 聊天区域盒子大小 (offsetHeight);

         代码实现如下:

<template>
  <view class="main" ref="scrollContainer" id="main">
    <!--  scroll-y:允许纵向滚动   默认: false | 给scroll-view一个固定高度 -->
    <scroll-view class="mainbody" id="mainbody" scroll-with-animation :scroll-y="true"  style="height:960px;" :enhanced=true scrollIntoViewAlignment="center"
                 @scrolltoupper="upper" @scrolltolower="lower" @scroll="scroll" :scrollWithAnimation="true">
      <view v-for="(item, index) in contentTypeit.arr" v-bind:key="index"
            :class="['info',  'content-questionBlock']">
        <view :class="['content']" :id="item.id">{{ item.content
          }}
        </view>
      </view>
      <view @click="sendMsg" id="sendMsg"></view>
      <view @click="pageUp" id="pageUp" style="visibility: hidden;"></view>
      <view @click="pageDown" id="pageDown" style="visibility: hidden;"></view>

    </scroll-view>

  </view>
</template>

<script>
import { ref, reactive, toRaw } from 'vue'
import Taro from "@tarojs/taro";

export default {
  setup () {
    const contentTypeit = reactive({
      arr: []
    })
    const scrollId = ref('id0') //scroll ID值
    const scrollCursor = ref('id0')

    const scrollCursorStore = ref(0)
    // 自动 scrollTop
    //https://www.cnblogs.com/hmy-666/p/14717484.html  滚动原理与实现
    //由于插入新的消息属于创建新的元素的过程,这个过程是属于异步的,所以为了防止异步创建元素导致获取高度不准确,我们可以等待一段时间,等元素创建完毕之后再获取元素高度
    const scrollDownInterval = function () {
      let idDom = document.getElementById('mainbody')
      console.log("===================scrollTop,clientHeight,scrollHeight,offsetHeight", idDom.scrollTop, idDom.clientHeight, idDom.scrollHeight, idDom.offsetHeight)
      let currentScrollPosition = scrollCursorStore.value;
      Taro.nextTick(() => {
        console.log('scroll start...', idDom.scrollTop)
        let scrollInterval = setInterval(() => {
          if (
            (idDom.scrollTop === idDom.scrollHeight - idDom.offsetHeight) ||
            (idDom.scrollTop > idDom.scrollHeight - idDom.offsetHeight)
          ) {
            scrollCursorStore.value = idDom.scrollTop
            clearInterval(scrollInterval);
            console.log('scroll end...', idDom.scrollTop)
          } else {
            currentScrollPosition =
              currentScrollPosition + 100;
            idDom.scrollTop = currentScrollPosition;
            scrollCursorStore.value = idDom.scrollTop
            console.log('scrolling...', idDom.scrollTop)
          }
        }, 200)
      })
    }

    const number = ref(0)
    //https://blog.csdn.net/weixin_43398820/article/details/119963930

    // 会话内容
    // 获取对话结果
    const sendMsg = function () {
      setContent( 'dfasdfsfsafdsafsafsdfsafsdfsdfdsfsafdsfsadfsafggfdhfhfjgfjhsdgdsfgasfsafdsafsagdhgfhfdhsgdsgdsgdgafsadfdsfdsfsadfhghsdfgsafdsaf')
    }
    // 设置对话内容
    const setContent = function (msg) {
      let idValue = 'id' + number.value
      const currentObjTypeit = {
        'content': msg,
        'id': idValue
      }

      let _arr = toRaw(contentTypeit.arr)
      let _arrTmp = _arr.concat(currentObjTypeit)
      contentTypeit.arr = _arrTmp

      number.value = number.value + 1;
      scrollCursor.value = idValue
      //https://blog.csdn.net/weixin_46511008/article/details/126629361
      scrollDownInterval();

    }

    const scroll = function (e) {
      // console.log('scroll', e)
    }
    const upper = function (e) {
      // console.log('upper', e)
    }
    const lower = function (e) {
      // console.log('lower', e)
    }

    const pageUp = function (e) {
      let idDom = document.getElementById('mainbody')
      console.log("===================", idDom.scrollTop, idDom.clientHeight, idDom.scrollHeight, idDom.offsetHeight)
      let currentScrollPosition = scrollCursorStore.value;
      scrollCursorStore.value = scrollCursorStore.value - 400
      if (scrollCursorStore.value < 0) {
        scrollCursorStore.value = 0;
      }
      Taro.nextTick(() => {
        console.log('scroll start...', idDom.scrollTop)
        let scrollInterval = setInterval(() => {
          if (
            (idDom.scrollTop === scrollCursorStore.value) ||
            (idDom.scrollTop < scrollCursorStore.value)
          ) {
            clearInterval(scrollInterval);
            console.log('scroll end...', idDom.scrollTop)
          } else {
            currentScrollPosition =
              currentScrollPosition - 50;
            idDom.scrollTop = currentScrollPosition;
            console.log('scrolling...', idDom.scrollTop)
          }
        }, 100)
      })
    }
    const pageDown = function (e) {
      let idDom = document.getElementById('mainbody')
      console.log("===================", idDom.scrollTop, idDom.clientHeight, idDom.scrollHeight, idDom.offsetHeight)
      let currentScrollPosition = scrollCursorStore.value;
      scrollCursorStore.value = scrollCursorStore.value + 400
      if (scrollCursorStore.value > (idDom.scrollHeight - idDom.offsetHeight )) {
        scrollCursorStore.value =  idDom.scrollHeight - idDom.offsetHeight;
      }
      Taro.nextTick(() => {
        console.log('scroll start...', idDom.scrollTop)
        let scrollInterval = setInterval(() => {
          if (
            (idDom.scrollTop === scrollCursorStore.value) ||
            (idDom.scrollTop > scrollCursorStore.value)
          ) {

            clearInterval(scrollInterval);
            console.log('scroll end...', idDom.scrollTop)
          } else {
            currentScrollPosition =
              currentScrollPosition - (-50);
            idDom.scrollTop = currentScrollPosition;
            console.log('scrolling...', idDom.scrollTop)
          }
        }, 100)
      })
    }

    return {
      contentTypeit,
      scrollId,
      lower,
      upper,
      scroll,
      sendMsg,
      pageUp,
      pageDown,
    }
  }
}
</script>

<style lang="scss">
.main {
  height: 100%;
  width: 100%;
  background-color: rgba(204, 204, 204, 0.32);
  overflow-x: hidden;
  overflow-y: auto;
}

.mainbody {
  max-width: 100%;
  background-size: contain;
  padding-bottom: 100px;
}

.info {
  display: flex;
  margin: 10px 3%;
}
.content-question {
  color: #0b4eb4;
  background-color: #ffffff;
  padding-left: 20px;
}


.content-questionBlock {
  align-items: center;
}

.content {
  background-color: #fff;
  border-radius: 16px;
  padding: 20px;
  margin-left: 20px;
  max-width: 82%;
  height: 100%;
  font-size: 36px;
  font-family: PingFangSC-Medium, PingFang SC;
  font-weight: 500;
  color: #0a0a27;
  line-height: 60px;
  word-break: break-all;
}
</style>

        效果调试:

      (1)打开浏览器,按下F12进入调试模式;

      (2)在console窗口,多次调用document.getElementById('sendMsg').click(),使得对话内容超出界面高度,可观察到自动滚动效果;

       (3)在console窗口,调用document.getElementById('pageUp').click(),可观察到向上滚动;接着调用document.getElementById('pageDown').click(),可观察到向下滚动。

        效果图如下:

建议

        方案一由于接口支持,滑动效果更平滑,但是翻页只能调到指定锚点,滑动步长不可控,大部分场景不能满足需求。

        方案二可以自行调整翻页的步长,按需滑动至指定高度,不过滑动动画需要自行实现,看起来卡顿感较强。

        总体来说,建议使用方案二。

参考链接:

        https://blog.csdn.net/weixin_46511008/article/details/126629361

        https://www.cnblogs.com/wq805/p/16399600.html

        https://www.cnblogs.com/hmy-666/p/14717484.html

        Taro 文档

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

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

相关文章

两小时搭建属于自己的chatGPT(ChatGLM)免硬件(白嫖)

目录 准备&#xff08;注册&#xff09;: 搭建: API模式: 测试&#xff1a; 总结&#xff1a; 准备&#xff08;注册&#xff09;: 注册modelscope(白嫖)免费使用服务器 https://modelscope.cn/ 按照图片里的选择(选择其他好像不能创建成功) 可以白嫖60多个小时的配置 8…

Java 8 Time 关于java.time包中你可能不知道的使用细节

目录 前言一、时区与时间1. 世界标准时&#xff1a;UTC、GMT、UT2. 地区时&#xff1a;Asia/Shanghai、UTC83. 时区&#xff1a;ZoneId、TimeZone4. 时间偏移量&#xff1a;ZoneOffset5. 时区简称&#xff1a;CTT、PRC 二、主要时间类1. 重要时间接口&#xff1a;Temporal2. 时…

【CocosCreator入门】CocosCreator组件 | Collider(碰撞)组件

Cocos Creator是一款流行的游戏开发引擎&#xff0c;具有丰富的组件和工具&#xff0c;其中碰撞系统组件是该引擎的重要组成部分。该组件可用于检测游戏中各个元素之间的碰撞&#xff0c;例如玩家角色与敌人、子弹与障碍物等。 目录 一、组件介绍 二、组件属性 2.1BoxCollid…

基于SpringBoot+微信小程序的农产品销售平台

基于SpringBoot微信小程序的农产品销售平台 ✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取项目下载方式&#x1f345; 一、项目…

Test Doubles测试替身: Testing in Distributed Systems and Real World

什么是Test Doubles In software testing, we developed unit tests and integration tests to test the codes functionality. However, in the real world, it is very common for a piece of code to interact with external components, for example, databases, public A…

【人工智能概论】pyplot作图中文显示、逐点坐标显示、保存图像

【人工智能概论】pyplot作图中文显示、逐点标记、保存图像 文章目录 【人工智能概论】pyplot作图中文显示、逐点标记、保存图像一. 简单的绘图二. 逐点坐标显示三. 中文显示四. 中文显示可能遇到的问题——缺少字体4.1 下载 SimHei.ttf4.2 复制 SimHei.ttf 到 Matplotlib 的 fo…

好的Robots.txt设计对Google收录有很大的帮助

Robots.txt 文件是用于指导搜索引擎爬虫在网站上爬行的标准。正确地设计 Robots.txt 文件可以帮助 Google 爬虫更好地理解您的网站结构&#xff0c;从而提高您的网站在 Google 搜索引擎上的收录率。 以下是一些设计 Robots.txt 文件的技巧&#xff0c;可以帮助 Google 爬虫更好…

security 报错:There is no PasswordEncoder mapped for the id “null“

security在登录的时候 无法登录成功 首先解读错误 下面百度翻译 安全框架设置了登录验证 说你没有密码编辑器 解决方法 一: 往容器中注册一个PasswordEncoder 解决方法二: 设置用户权限和角色的时候添加方法,加进去一个PasswordEncoder 只需要解决方案的话 下面的内容…

K8S系列之污点和容忍度详细分析

架构图 本篇文档主要介绍污点和容忍度的关系。 污点和容忍度 污点顾名思义就是脏的东西&#xff0c;给节点添加污点来限制pod调度到该节点上&#xff0c;如果pod可以容忍这种污点就可以被调度到有污点的节点上&#xff0c;如果不能容忍就不能被调度到该节点上。 污点作用于节…

排队领奖模式吸引新消费者,电商平台如何创新引流拓客?

在当前的电商市场中&#xff0c;由于竞争日趋激烈&#xff0c;很多电商平台产生了引流拓客缺乏新意的难题&#xff0c;即很难找到新的流量&#xff0c;并且难以把这些流量转化为消费者。在这个瞬息万变的时代&#xff0c;当然是谁有创意谁能吸引消费者&#xff0c;谁才能当道。…

Sequence-to-Sequence Knowledge Graph Completion and Question Answering

[2203.10321] Sequence-to-Sequence Knowledge Graph Completion and Question Answering (arxiv.org) 目录 1 Abstract 2 Introduction 3 KGT5 Model 3.1 Textual Representations & Verbalization 3.2 Training KGT5 for Link Prediction 3.3 Link Prediction Inf…

Inception Network

文章目录 一、Inception Network简介二、CNN的痛点三、Inception Network1. 1x1卷积核1.1 升维/降维&#xff1a;1.2. 调节参数数量&#xff1a;1.3. 增加非线性特性&#xff1a; 2. Inception原始模型3. Inception Module4. Inception Network 四、代码示例 一、Inception Net…

接口自动化测试 vs. UI自动化测试:为什么前者更快,更省力,更稳定?

从入门到精通&#xff01;企业级接口自动化测试实战&#xff0c;详细教学&#xff01;&#xff08;自学必备视频&#xff09; 目录 前言&#xff1a; 一、什么是接口自动化测试和 UI 自动化测试 二、为什么接口自动化测试效率比 UI 自动化测试高 1.执行速度 2.维护成本 3.…

AI人工智能与机器人的探索和应用1.1

文章来源于&#xff1a;https://mp.weixin.qq.com/s/fqivYVdakVKG-zDVfD4Qzg 研究机器人和人工智能的技术已有多年了&#xff0c;想来想去&#xff0c;觉得还是有必要对过往的技术做一些凝练和总结。在此过程中&#xff0c;除了能够将知识系统化&#xff0c;构建自己的知识体系…

三次输错密码后,系统是怎么做到不让我继续尝试的?

故事背景 忘记密码这件事&#xff0c;相信绝大多数人都遇到过&#xff0c;输一次错一次&#xff0c;错到几次以上&#xff0c;就不允许你继续尝试了。 但当你尝试重置密码&#xff0c;又发现新密码不能和原密码重复&#xff1a; 相信此刻心情只能用一张图形容&#xff1a; 虽…

python二次加工标准类型 | 包装与授权

欢迎关注博主 Mindtechnist 或加入【Linux C/C/Python社区】一起学习和分享Linux、C、C、Python、Matlab&#xff0c;机器人运动控制、多机器人协作&#xff0c;智能优化算法&#xff0c;滤波估计、多传感器信息融合&#xff0c;机器学习&#xff0c;人工智能等相关领域的知识和…

洽洽离年轻人更近了,陈先保离百亿KPI呢?

文|螳螂观察 作者|图霖 留给陈先保实现百亿营收的时间不多了。 过去几年&#xff0c;洽洽凭借着在产品端、市场端、供应端的绝对实力&#xff0c;守住了休闲零食行业龙头的地位。但最新发布的2023年第一季度业绩报告&#xff0c;却出现了6年来首次营收、净利双双下降。 报告…

Excel大数据量单元格快速填充

个人简介&#xff1a;一个从会计转行数据分析师的三旬老汉 擅长领域&#xff1a;数据分析、数据仓库、大数据 博客内容&#xff1a;平时会将自己工作中遇到的问题进行归纳总结&#xff0c;分享给各位小伙伴&#xff0c;意在帮助大家少加班、不掉发&#xff0c;让我们相互学习&a…

const/static修饰成员函数+初始化列表

一、const修饰成员函数 首先&#xff0c;我们知道&#xff0c;所有的成员函数&#xff08;除static修饰的&#xff09;&#xff0c;编译器都会隐式传递一个this指针。 它的默认类型为 Type* const this&#xff0c;即this指针只能指向最左边的第一个传入的对象。 const修饰成…

Docker容器体系结构及特点

Docker容器体系结构及特点 Docker是一个应用容器引擎&#xff0c;通过Docker&#xff0c;管理员可以非常方便地对容器进行管理。Docker基于Go语言开发&#xff0c;并且遵从Apache 2.0开源协议。 Docker提供了对容器镜像的打包封装功能。利用Docker&#xff0c;开发者可以将他…