JS听到了爆燃的回响

Window对象

BOM(浏览器对象模型)

BOM是浏览器对象模型

Window对象是一个全局对象,也可以说是JS中的顶级对象

像是document、alert()、console.log()都是window的属性

所有通过var定义在全局作用域的变量、函数都会变成window对象的属性和方法

window对象下的属性和方法调用的时候可以省略window

定时器-延时函数

JS内定了一个用来让代码延迟执行的函数,叫setTimeout

语法:

setTimeout仅仅执行一次,就可以理解为把一段代码延迟执行,平时的时候省略window

清除延时函数:

延时器需要等待,所以后面的代码先执行

每次调用延时器都会产生新的延时器

和之前的定时器对比一下:

 

5s钟之后消失的广告

我们需要让5s之后广告自动消失(真的会有这么良心的广告吗,我以为起手三十秒)

我们需要设置延时函数、隐藏元素

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .box{
            position: relative;
            width: 300px;
            height: 300px;
            background-color: pink;
            margin: 0 auto;
        }
        .button{
            position: absolute;
            right: 10px;
            top: 10px;
            width: 20px;
            height: 20px;
            background-color: skyblue;
            color: white;
            text-align :center;
            line-height: 20px;
        }
    </style>
</head>
<body>
    <div class="box">
        <div class="button">
            x
        </div>
    </div>
    <script>
        let timer = setTimeout(function(e){
            const box = document.querySelector('.box')
            box.style.display = 'none'
        },5000)
    </script>
</body>
</html>

是很简单的小例子捏 

JS执行机制

经典面试题,看看JS的执行机制:

 都一样

是132的配置

JS的一大特点是单线程

JavaScript 是为处理页面中用户的交互,以及操作 DOM 而诞生的。

比如我们对某个 DOM 元素进行添加和删除操作,不能同时进行。 应该先进行添加,之 后再删除。 单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。

这样所导致的问题是: 如果 JS 执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞的感觉

为了解决这个问题,利用了多核CPU的计算能力,H5提出了Web Worker标准,允许JS脚本创建多个线程,所以JS中出现了同步和异步

同步的任务都在主线程上执行,形成一个执行栈

而异步是通过回调函数实现的

异步任务的三种类型:

1、普通事件,如 click、resize 等

2、资源加载,如 load、error 等

3、定时器,包括 setInterval、setTimeout 等

异步任务相关添加到任务队列中 

 

先执行栈中的同步任务,异步任务放入任务队列中

一旦执行栈中的所有同步任务执行完毕,系统就按次序读取任务队列中的异步任务,被读取的异步任务结束等待状态,进入执行栈开始执行

主线程不断的重复获得任务,执行任务,再获取任务,执行任务,这种机制被称为事件循环

location对象

location的数据类型是对象,它拆分并保存了URL地址的各个组成部分

href属性获取完整的URL地址,对它赋值的时候用于地址的跳转

 

5s之后跳转页面

需求:用户点击可以跳转,如果不点击,就5s之后自动跳转,要求里面有秒数倒计时

分析:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>
        setTimeout(function () {
            location.href = 'https://www.bilibili.com/'
        }, 5000)
    </script>
</body>

</html>

易如反掌孩子们

hash属性获取地址中的哈希值,符号#后main的部分

 

经常用于不刷新页面显示不同页面,比如网易云音乐

reload用来刷新当前页面,传入的参数为true的时候表示强制刷新:

其实也很像fflush 

总结一下就是:

navigator对象

navigator的数据类型是对象,该对象下记录了浏览器自身的相关信息

常用的属性方法:

可以通过userAgent检测浏览器的版本和平台

histroy对象

history 的数据类型是对象,主要管理历史记录, 该对象与浏览器地址栏的操作相对应,如前进、后退、历史记录等

有一些常用的属性和方法:

它在实际开发中很少用,但是在OA办公系统里很常见 

本地存储

本地存储介绍

以前我们页面写的数据一刷新页面就没了

随着互联网的快速发展,基于网页的应用越来越普遍,同时也变得越来越复杂,为了满足各种各样的需求,会经常在本地存储大量的数据,HTML规范提出了相关解决方案

数据存储在用户浏览器中

设置读取方便,甚至页面刷新不丢失数据

容量较大,sessionStorage和localStorage约 5M 左右

常用的使用场景:

https://todomvc.com/examples/vanilla-es6/

页面刷新数据不丢失 

本地存储分类

能够使用localStorage 把数据存储的浏览器中

作用就是可以将数据永久存储在本地(用户的电脑), 除非手动删除,否则关闭页面也会存在

可以多窗口(页面)共享(同一浏览器可以共享)

以键值形式存储使用

这是它的语法:

我们如何在浏览器查看本地数据呢?

sessionStorage:

特性是生命周期是关闭浏览器窗口

在同一个窗口(页面)下的数据可以共享

 以键值对的形式存储使用

用法和localStorage基本相同

存储复杂数据类型

本地只能存储字符串,无法存储复杂的数据类型

我们存储复杂的数据类型需要将复杂数据类型转换成JSON字符串并存储到本地

 JSON.stringify(复杂数据类型)

 <script>
        const goods = {
            name:'小米13',
            price:3999
        }
        localStorage.setItem('goods',JSON.stringify(goods))
    </script>

但是这样就存在问题:本地存储里面取出来的是字符串,不是对象,无法直接使用

所以我们要把取出来的字符串转换为对象

语法: JSON.parse(JSON字符串)

 <script>
        const goods = {
            name:'小米13',
            price:3999
        }
        localStorage.setItem('goods',JSON.stringify(goods))
        const obj = JSON.parse(localStorage.getItem('goods'))
        console.log(obj)
    </script>

综合案例

还是按照学生信息表的样子,但这次我们要求的是刷新页面后数据不丢失

分析:

需求1:读取本地数据

如果本地存储有数据,则返回JSON.parse()之后的对象

如果本地存储没有数据,则声明一个空的数组

 

 <script>
    // 参考数据
    const initData = [
      {
        stuId: 1,
        uname: '迪丽热巴',
        age: 22,
        salary: '12000',
        gender: '女',
        city: '北京',
        time: '2099/9/9 08:08:08'
      }
    ]
    localStorage.setItem('data', JSON.stringify(initData))
    // localStorage.setItem('data', JSON.stringify(initData))
    // 1. 渲染业务
    // 1.1 先读取本地存储的数据
    // (1). 本地存储有数据则记得转换为对象然后存储到变量里面,后期用于渲染页面
    const arr = JSON.parse(localStorage.getItem('data')) || []
    // (2). 如果没有数据,则用 空数组来代替,上面用了逻辑中断
    
  </script>

主要就是那两行代码 

需求2:渲染模块

 字符串拼接有新的思路(效果更高,开发常用的写法)

利用map()和join()数组方法实现字符串拼接

数组中的map方法:

map可以处理数据并且返回新的数组

 

 数组中的join方法

join()方法用于把数组中的所有元素转换一个字符串

数组元素是通过参数里面指定的分隔符进行分割的

渲染页面步骤:

渲染页面部分:

 // 利用map和join方法来渲染页面
    function render() {
      // 利用map遍历数组,返回对应tr的数组
      // 把数组转换为字符串
      // 把生成的字符串追加给tbody
      const trArr = arr.map(function (ele) {
        return `
         <tr>
        <td>${ele.stuId}</td>
        <td>${ele.uname}</td>
        <td>${ele.age}</td>
        <td>${ele.gender}</td>
        <td>${ele.salary}</td>
        <td>${ele.city}</td>
        <td>${ele.time}</td>
        <td>
          <a href="javascript:">
            <i class="iconfont icon-shanchu"></i>
            删除
          </a>
        </td>
        </tr>`
      })

      // 把数组转换为字符串join
      // 把生成的字符串追加给tbody
      tbody.innerHTML = trArr.join('')

    //  统计总共有几条数据
    document.querySelector('.title span').innerHTML = arr.length
    }

 接下来我们实现一下录入模块:

 

 // 新增业务
    // form表单注册提交事件,阻止默认行为
    const info = document.querySelector('.info')
    const uname = document.querySelector('.uname')
    const age = document.querySelector('.age')
    const salary = document.querySelector('.salary')
    const gender = document.querySelector('.gender')
    const city = document.querySelector('.city')
    info.addEventListener('submit', function (e) {
      e.preventDefault()
      // 非空判断
      if(!uname.value || !age.value || !salary.value)
    {
       return alert('输入内容不能为空')
    }
    // 给arr数组追加对象,里面存储表单获取过来的数据
    arr.push({
        stuId: arr.length+1,
        uname: uname.value,
        age: age.value,
        salary: salary.value,
        gender: gender.value,
        city: city.value,
        time: new Date().toLocaleString()
        // 获取当前的时间
    })
    // 渲染页面和重置表单
    render()
    this.reset()
    })

但是上面的数据没存在本地存储,所以我们修改一下

我的代码出错就在这

因为没有事先初始化渲染页面,就是这里出现了问题

 然后这个就是问题所在,只有新增的时候才能有办法

   // 把数组转换为字符串join
      // 把生成的字符串追加给tbody
      tbody.innerHTML = trArr.join('')

      //  统计总共有几条数据
      document.querySelector('.title span').innerHTML = arr.length
    }

    render()    //初始化渲染页面,就是这里出了问题

    // 新增业务
    // form表单注册提交事件,阻止默认行为
    const info = document.querySelector('.info')
    const uname = document.querySelector('.uname')
    const age = document.querySelector('.age')
    const salary = document.querySelector('.salary')
    const gender = document.querySelector('.gender')
    const city = document.querySelector('.city')

    info.addEventListener('submit', function (e) {
      e.preventDefault()
      // 非空判断
      if(!uname.value || !age.value || !salary.value)
    {
       return alert('输入内容不能为空')
    }
    // 给arr数组追加对象,里面存储表单获取过来的数据
    arr.push({
        stuId: arr.length+1,
        uname: uname.value,
        age: age.value,
        salary: salary.value,
        gender: gender.value,
        city: city.value,
        time: new Date().toLocaleString()
        // 获取当前的时间
    })
    // 渲染页面和重置表单
    render()
    this.reset()

    // 把数组重新存入到本地存储里面,要转换成为JSON字符串存储
    localStorage.setItem('data',JSON.stringify(arr))
    })

然后我们制作删除模块:

    // 删除业务模块
    // 首先采取时间委托形式,给tbody注册点击事件
    tbody.addEventListener('click',function(e){
      if(e.target.tagName === 'A')
    {
      // 得到当前点击的索引号,渲染数据的时候 ,动态给a链接添加自定义属性比如data-id
      console.log(e.target.dataset.id)
    }
    // 确认框确认是否真的要删除
    if(confirm('你确定要删除这条数据就行'))
    {
      // 根据索引号,利用splice删除数组这条数据
      arr.splice(e.target.dataset.id,1)
      // 重新渲染页面
      render()
      // 把最新arr数组存入本地存储
      localStorage.setItem('data',JSON.stringify(arr))
    }
    })

关于stuId的处理问题:

 

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <meta http-equiv="X-UA-Compatible" content="ie=edge" />
  <title>学生就业统计表</title>
  <link rel="stylesheet" href="./iconfont/iconfont.css">
  <link rel="stylesheet" href="./css/index.css" />
</head>

<body>
  <h1>学生就业统计表</h1>
  <form class="info" autocomplete="off">
    <input type="text" class="uname" name="uname" placeholder="姓名" />
    <input type="text" class="age" name="age" placeholder="年龄" />
    <input type="text" class="salary" name="salary" placeholder="薪资" />
    <select name="gender" class="gender">
      <option value="男">男</option>
      <option value="女">女</option>
    </select>
    <select name="city" class="city">
      <option value="北京">北京</option>
      <option value="上海">上海</option>
      <option value="广州">广州</option>
      <option value="深圳">深圳</option>
      <option value="曹县">曹县</option>
    </select>
    <button class="add">
      <i class="iconfont icon-tianjia"></i>添加
    </button>
  </form>

  <div class="title">共有数据<span>0</span>条</div>
  <table>
    <thead>
      <tr>
        <th>ID</th>
        <th>姓名</th>
        <th>年龄</th>
        <th>性别</th>
        <th>薪资</th>
        <th>就业城市</th>
        <th>录入时间</th>
        <th>操作</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>1</td>
        <td>迪丽热巴</td>
        <td>23</td>
        <td>女</td>
        <td>12000</td>
        <td>北京</td>
        <td>2099/9/9 08:08:08</td>
        <td>
          <a href="javascript:">
            <i class="iconfont icon-shanchu"></i>
            删除
          </a>
        </td>
      </tr>
    </tbody>
  </table>
  <script>
    // 参考数据
    // const initData = [
    //   {
    //     stuId: 1,
    //     uname: '迪丽热巴',
    //     age: 22,
    //     salary: '12000',
    //     gender: '女',
    //     city: '北京',
    //     time: '2099/9/9 08:08:08'
    //   }
    // ]
    // localStorage.setItem('data', JSON.stringify(initData)) ,没必要进行重复填写
    // localStorage.setItem('data', JSON.stringify(initData))
    // 1. 渲染业务
    // 1.1 先读取本地存储的数据
    // (1). 本地存储有数据则记得转换为对象然后存储到变量里面,后期用于渲染页面
    const arr = JSON.parse(localStorage.getItem('data')) || []
    // (2). 如果没有数据,则用 空数组来代替,上面用了逻辑中断
    const tbody = document.querySelector('tbody')

    // 利用map和join方法来渲染页面
    function render() {
      // 利用map遍历数组,返回对应tr的数组
      // 把数组转换为字符串
      // 把生成的字符串追加给tbody
      const trArr = arr.map(function (ele,index){
        return `
         <tr>
        <td>${ele.stuId}</td>
        <td>${ele.uname}</td>
        <td>${ele.age}</td>
        <td>${ele.gender}</td>
        <td>${ele.salary}</td>
        <td>${ele.city}</td>
        <td>${ele.time}</td>
        <td>
          <a href="javascript:" data-id="${index}">
            <i class="iconfont icon-shanchu"></i>
            删除
          </a>
        </td>
        </tr>`
      })

      // 把数组转换为字符串join
      // 把生成的字符串追加给tbody
      tbody.innerHTML = trArr.join('')

      //  统计总共有几条数据
      document.querySelector('.title span').innerHTML = arr.length
    }

    render()    //初始化渲染页面,就是这里出了问题

    // 新增业务
    // form表单注册提交事件,阻止默认行为
    const info = document.querySelector('.info')
    const uname = document.querySelector('.uname')
    const age = document.querySelector('.age')
    const salary = document.querySelector('.salary')
    const gender = document.querySelector('.gender')
    const city = document.querySelector('.city')

    info.addEventListener('submit', function (e) {
      e.preventDefault()
      // 非空判断
      if(!uname.value || !age.value || !salary.value)
    {
       return alert('输入内容不能为空')
    }
    // 给arr数组追加对象,里面存储表单获取过来的数据
    arr.push({
        stuId: arr.length ? arr[arr.length - 1].stuId + 1 : 1,
        uname: uname.value,
        age: age.value,
        salary: salary.value,
        gender: gender.value,
        city: city.value,
        time: new Date().toLocaleString()
        // 获取当前的时间
    })
    // 渲染页面和重置表单
    render()
    this.reset()

    // 把数组重新存入到本地存储里面,要转换成为JSON字符串存储
    localStorage.setItem('data',JSON.stringify(arr))
    })

    // 删除业务模块
    // 首先采取时间委托形式,给tbody注册点击事件
    tbody.addEventListener('click',function(e){
      if(e.target.tagName === 'A')
    {
      // 得到当前点击的索引号,渲染数据的时候 ,动态给a链接添加自定义属性比如data-id
      console.log(e.target.dataset.id)
    }
    // 确认框确认是否真的要删除
    if(confirm('你确定要删除这条数据就行'))
    {
      // 根据索引号,利用splice删除数组这条数据
      arr.splice(e.target.dataset.id,1)
      // 重新渲染页面
      render()
      // 把最新arr数组存入本地存储
      localStorage.setItem('data',JSON.stringify(arr))
    }
    })
    

  </script>
</body>

</html>

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Linux】死锁、读写锁、自旋锁

文章目录 1. 死锁1.1 概念1.2 死锁形成的四个必要条件1.3 避免死锁 2. 读者写者问题与读写锁2.1 读者写者问题2.2 读写锁的使用2.3 读写策略 3. 自旋锁3.1 概念3.2 原理3.3 自旋锁的使用3.4 优点与缺点 1. 死锁 1.1 概念 死锁是指在⼀组进程中的各个进程均占有不会释放的资源…

单片机学习笔记 15. 串口通信(理论)

更多单片机学习笔记&#xff1a;单片机学习笔记 1. 点亮一个LED灯单片机学习笔记 2. LED灯闪烁单片机学习笔记 3. LED灯流水灯单片机学习笔记 4. 蜂鸣器滴~滴~滴~单片机学习笔记 5. 数码管静态显示单片机学习笔记 6. 数码管动态显示单片机学习笔记 7. 独立键盘单片机学习笔记 8…

MyBatis异常体系中ErrorContext和ExceptionFactory原理分析

&#x1f3ae; 作者主页&#xff1a;点击 &#x1f381; 完整专栏和代码&#xff1a;点击 &#x1f3e1; 博客主页&#xff1a;点击 文章目录 exceptions包分包设计ExceptionFactory类介绍为什么使用工厂不是直接new呢&#xff1f;【统一的异常处理机制】【异常的封装与转化】【…

【Canvas与雷达】点鼠标可暂停金边蓝屏雷达显示屏

【成图】 【代码】 <!DOCTYPE html> <html lang"utf-8"> <meta http-equiv"Content-Type" content"text/html; charsetutf-8"/> <head><title>点鼠标可暂停金边蓝屏雷达显示屏 Draft1</title><style typ…

Spark Optimization —— Reducing Shuffle

Spark Optimization : Reducing Shuffle “Shuffling is the only thing which Nature cannot undo.” — Arthur Eddington Shuffle Shuffle Shuffle I used to see people playing cards and using the word “Shuffle” even before I knew how to play it. Shuffling in c…

数据结构 (22)哈夫曼树及其应用

前言 哈夫曼树&#xff08;Huffman Tree&#xff09;&#xff0c;又称最优二叉树或最优树&#xff0c;是一种特殊的二叉树结构&#xff0c;其带权路径长度&#xff08;WPL&#xff09;最短。 一、哈夫曼树的基本概念 定义&#xff1a;给定N个权值作为N个叶子结点&#xff0c;构…

Android Studio安装TalkX AI编程助手

文章目录 TalkX简介编程场景 TalkX安装TalkX编程使用ai编程助手相关文章 TalkX简介 TalkX是一款将OpenAI的GPT 3.5/4模型集成到IDE的AI编程插件。它免费提供特定场景的AI编程指导&#xff0c;帮助开发人员提高工作效率约38%&#xff0c;甚至在解决编程问题的效率上提升超过2倍…

泷羽sec-shell脚本(全) 学习笔记

声明&#xff01; 学习视频来自B站up主 **泷羽sec** 有兴趣的师傅可以关注一下&#xff0c;如涉及侵权马上删除文章&#xff0c;笔记只是方便各位师傅的学习和探讨&#xff0c;文章所提到的网站以及内容&#xff0c;只做学习交流&#xff0c;其他均与本人以及泷羽sec团队无关&a…

开发者如何使用GCC提升开发效率IMG操作

看此篇前请先阅读https://blog.csdn.net/qq_20330595/article/details/144134160?spm1001.2014.3001.5502 stb_image库配置 https://github.com/nothings/stb 代码 #define STB_IMAGE_IMPLEMENTATION #include "stb_image.h" #define STB_IMAGE_WRITE_IMPLEM…

vue3【实战】面包屑【组件封装】Breadcrumb (根据菜单自动生成,实时响应路由变化,添加顺滑的过渡动画)

效果预览 技术方案 vue3 ( vite | TS | vueUse | AutoImport ) Element Plus UnoCSS 技术要点 根据当前路由查询所有父级路由 /*** 从树状列表中获取指定节点的所有父节点** param treeList 树状列表&#xff0c;包含多个节点* param value 目标节点的路径值* param parents…

pdf也算是矢量图——pdf大小调整--福昕pdf

有时候需要把pdf作为矢量图放到latex论文中&#xff0c;有时候需要裁剪掉空白的部分&#xff0c;就需要用福昕pdf进行编辑&#xff0c; 参考文章&#xff1a;福昕高级PDF编辑器裁切工具怎么用&#xff1f;裁切工具使用方法介绍_福昕PDF软件工具集 (foxitsoftware.cn)

【k8s】kubelet 的相关证书

在 Kubernetes 集群中&#xff0c;kubelet 使用的证书通常存放在节点上的特定目录。这些证书用于 kubelet 与 API 服务器之间的安全通信。具体的位置可能会根据你的 Kubernetes 安装方式和配置有所不同&#xff0c;下图是我自己环境【通过 kubeadm 安装的集群】中的kubelet的证…

Java项目Docker部署

docker将应用程序与该程序的依赖打包在一个文件里。运行这个文件就会生成一个虚拟容器&#xff0c;就不用担心环境问题&#xff0c;还可以进行版本管理、复制修改等。 docker安装 由于在CentOS下安装docker最常用&#xff0c;所以以Linux环境安装为主 1.安装工具包 缺少依赖…

【数据结构与算法】排序算法(上)——插入排序与选择排序

文章目录 一、常见的排序算法二、插入排序2.1、直接插入排序2.2、希尔排序( 缩小增量排序 ) 三、选择排序3.1、直接选择排序3.2、堆排序3.2.1、堆排序的代码实现 一、常见的排序算法 常见排序算法中有四大排序算法&#xff0c;第一是插入排序&#xff0c;二是选择排序&#xff…

Flink四大基石之Time (时间语义) 的使用详解

目录 一、引言 二、Time 的分类及 EventTime 的重要性 Time 分类详述 EventTime 重要性凸显 三、Watermark 机制详解 核心原理 Watermark能解决什么问题,如何解决的? Watermark图解原理 举例 总结 多并行度的水印触发 Watermark代码演示 需求 代码演示&#xff…

虚拟机docker记录

最近看了一个up的这个视频&#xff0c;感觉docker真的挺不错的&#xff0c;遂也想来搞一下&#xff1a; https://www.bilibili.com/video/BV1QC4y1A7Xi/?spm_id_from333.337.search-card.all.click&vd_sourcef5fd730321bc0e9ca497d98869046942 这里我用的是vmware安装ubu…

[ACTF2020 新生赛]BackupFile--详细解析

信息搜集 让我们寻找源文件&#xff0c;目录扫描&#xff1a; 找到了/index.php.bak文件&#xff0c;也就是index.php的备份文件。 后缀名是.bak的文件是备份文件&#xff0c;是文件格式的扩展名。 我们访问这个路径&#xff0c;就会直接下载该备份文件。 我们把.bak后缀删掉…

AD单通道AD多通道

AD单通道接线图 滑动变阻器的内部结构 左边和右边的两个引脚接的是电阻的两个固定端&#xff0c;中间这个引脚接的是滑动抽头&#xff0c;电位器外边这里有个十字形状的槽可以拧&#xff0c;往左拧&#xff0c;抽头就往左靠&#xff0c;往右拧&#xff0c;抽头就往右靠。所以外…

解决Ubuntu DNS覆盖写入127.0.0.53

ubuntu22.04解析网址时报错如图所示&#xff1a; 因为/etc/resolve.conf中存在 nameserver 127.0.0.53回环地址造成循环引用 原因&#xff1a; ubuntu17.0之后特有&#xff0c;systemd-resolvd服务会一直覆盖 解决方法&#xff1a; 1、修改resolv.config文件中的nameserver…

hint: Updates were rejected because the tip of your current branch is behind!

问题 本地仓库往远段仓库推代码时候提示&#xff1a; error: failed to push some refs to 192.168.2.1:java-base/java-cloud.git hint: Updates were rejected because the tip of your current branch is behind! refs/heads/master:refs/heads/master [rejected] (…