Vue2电商项目(二) Home模块的开发;(还需要补充js节流和防抖的回顾链接)

news2024/12/23 23:21:29

文章目录

  • 一、Home模块拆分
    • 1. 三级联动组件TypeNav
    • 2. 其余组件
  • 二、发送请求的准备工作
    • 1. axios的二次封装
    • 2. 统一管理接口API----跨域
    • 3. nprogress进度条
  • 三、 vuex模块开发
  • 四、TypeNav三级联动组件开发
    • 1. 动态展示三级联动数据
    • 2. 三级联动 动态背景
      • (1)、方式一:CSS样式
      • (2)、方式二:JS
    • 3. 控制二三级数据隐藏与显示--绑定style样式
    • 4. 三级联动的节流和防抖
    • 5. 三级联动路由跳转及传参
      • (1)、编程式导航+事件委托--自定义属性
    • 6、 Search模块三级联动显示与隐藏
      • (1)、Search模块使用TypeNav组件
      • (2)、控制TypeNav的显示与隐藏
      • (3)、鼠标移入移出与TypeNav的显示与隐藏
      • (4)、三级联动显示与隐藏的动画效果
    • 7、 TypeNav重复发送请求的优化
    • 8. 合并Search页面的query与params参数
  • 六、Home首页的ListContainer和Floor组件
    • 1. 搭建mock
    • 2. 搭建ListContainer组件
      • (1)、 mock虚拟数据的ajax请求
      • (2)、 获取轮播图数据
      • (3)、 搭建轮播图
        • - 创建Swiper实例的讨论
    • 3. 搭建Floor组件
      • (1)、封装api、发送请求
      • (2)、 动态数据渲染页面
      • (3)、 Floor组件里的轮播图
      • (4)、 封装轮播图

一、Home模块拆分

通过对Home模块页面的分析,Home模块可包括7个组件
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1. 三级联动组件TypeNav

由于这个组件在Home页面、Search页面、Detail页面中都使用了,所以把该组件注册为全局组件。
好处:只需要注册一次,就可以在任何地方使用

全局注册:Vue.component('组件名',组件)
在这里插入图片描述

2. 其余组件

拆分的时候注意样式CSS、结构HTML及图片资源
在这里插入图片描述
记录一个Bug,在ListContainer组件里,右侧的广告图片不显示(宋仲基那个图)
原因是浏览器安装的屏蔽广告插件把这个广告屏蔽了,所以报错。
参考博客:GET http://localhost:8080/***.png net::ERR_BLOCKED_BY_CLIENT 无法加载图片_localhost图片加载不出来-CSDN博客

二、发送请求的准备工作

1. axios的二次封装


(1)、为什么要对axios进行二次封装
  对axios二次封装可配置响应拦截器、请求拦截器:分别在收到服务器数据时或进行发送请求操作之前进行一些业务逻辑处理。

(2)、二次封装

  • 安装axios:npm install axios
    在这里插入图片描述

  • 创建src/api/request.js文件夹,进行二次封装

    // 本文件用于对axios二次封装
    import axios from 'axios'
    
    // 1. 利用axios方法create创建一个axios实例
    let requests = axios.create({
      // 配置实例属性
      // 1.1 基础路径,因为请求路径里都有api,所以这里设置基础路径
      baseURL: '/api',
      // 1.2 设置请求超时的时间。请求时间超过5s,则请求失败
      timeout: 5000
    });
    
    // 2. 配置请求拦截器
    // 请求拦截器检测到请求,在请求发出去之前做一些事情
    requests.interceptors.request.use((config) => {
      // config:配置对象,其中header请求头属性很重要
      return config;
    })
    
    // 3. 配置响应拦截器
    requests.interceptors.response.use((res) => {
      // 请求成功的回调函数
      return res.data
    }, (error) => {
      // 响应失败的回调
      return Promise.reject(new Error('falie'))
    })
    
    // 暴露axios实例
    export default requests
    

    对于axios,可参考NPM中关于axios的文档

2. 统一管理接口API----跨域

创建文件src/api/index.js,封装好发送请求的方法,发送请求时直接调用方法即可。

// src/api/index.js
// 本文件对于API接口进行统一管理
import requests from './request'

// 三级联动
// 请求地址:/api/product/getBaseCategoryList,请求方法:get
export const reqCategoryList = () => {
// 发请求:axios发送请求返回结果Promise对象;
//axios二次封装里以及写了basedUrl,所以这里就不用写/api了
return requests({ url: '/product/getBaseCategoryList', method: 'get' })

测试方法:

// main.js
import { reqCategoryList } from './api'
reqCategoryList()

(1)、测试遇到的跨域问题:
跨域是指请求的 协议、域名、端口号不同
前端项目本地服务器:http://localhost:8080/#/home
后台服务器:http://gmall-h5-api.atguigu.cn

解决跨域 (具体细节回顾博客:配置代理服务器):

// vue.config.js
 devServer: {
    proxy: {
      '/api': {
        target: 'http://gmall-h5-api.atguigu.cn',
      }
    }
  }

请求成功:
在这里插入图片描述

3. nprogress进度条

nprogress:页面加载进度条。只要项目当中发请求,进度条就开始往前动,服务器数据返回之后,进度条结束。

  • 安装进度条插件:npm install nprogress
  • statrt():进度条开始
  • done():进度条结束
  • 在请求及响应拦截器中使用(进度条的颜色等样式可以修改,直接在css文件里修改即可)
    在这里插入图片描述

三、 vuex模块开发

Vuex具体细节看这篇博客:Vuex

这个项目中的vuex采用模块化开发,分别建立homesearch两个小仓库,然后放入store这个大仓库里。

// 小仓库
// store/home/index.js     store/search/index.js
export default {
  // 开启命名空间
  namespaced: true,
  state: {},
  actions: {},
  mutations: {},
  getters: {}
}

store大仓库:

在这里插入图片描述
main.js引入Vuex

// 引入Vuex
import store from '@/store'
new Vue({
  // KV一致时省略V
  router,
  store,
  render: h => h(App),
}).$mount('#app')

四、TypeNav三级联动组件开发

1. 动态展示三级联动数据

向后台发送请求,获取三级联动的数据,渲染到页面上
在这里插入图片描述
TypeNav组件挂载完毕,就发送请求

mounted () {
    // 通知vuex发送请求,获取数据,存储在store中;dispatch('模块名/方法名')
    this.$store.dispatch('home/categoryList')
},

home小仓库里,将请求来的数据保存在state里:

//home/index.js
  state: {
    categoryList: []
  },
  actions: {
    // 获取三级联动的列表
    async categoryList (context) {
      let result = await reqCategoryList()
      if (result.code === 200) {
        // 请求成功
        context.commit('CATEGORTLIST', result.data)
      }
    }
  },
  mutations: {
    CATEGORTLIST (state, categoryList) {
      // 将获取成功的数据保存起来
      state.categoryList = categoryList
    }
  },

TypeNav组件读取vuex中请求来的数据

import { mapState } from 'vuex' 
computed: {
    // 获取State数据
    ...mapState('home', ['categoryList'])
  },

通过循环遍历的方式将categoryList渲染到页面上
在这里插入图片描述
这里发现一个小bug;一级分类的数据多了一个,视频里请求到16个,结果获取到17个了,多了一个样式就变了;
解决:只用categoryList里的前16个,一级v-for的代码改成:

v-for="(c1, index) in categoryList.slice(0, 16)"

2. 三级联动 动态背景

在这里插入图片描述
需求1:鼠标移动到哪个词条,哪个词条背景颜色改变。离开时,背景颜色消失。
需求2:但是当鼠标由第一个词条图书、音像..移动到全部商品分类时,第一个词条的颜色不变。

(1)、方式一:CSS样式

.item:hover{
    background-color:skyblue
}

这种方式能够实现需求1,但实现不了需求2

(2)、方式二:JS

设置mouseentermouseleave事件及currentIndex属性,该属性默认值是-1;

当鼠标移入词条时,获取当前词条的index,存入currentIndex。当index === currentIndex时,给当前词条添加样式。

当鼠标移除词条时,再次将currentIndex设为-1;

<div
   class="item"
   v-for="(c1, index) in categoryList.slice(0, 16)"
   :key="c1.categoryId"
   @mouseenter="changeBg(index)"
   :class="{ cur: index === currentIndex }"
 >
 <!----一级分类a标签---->
 <!----二级分类内容---->
  <!----三级分类内容---->
 </div>
<script>
  data () {
    return {
      currentIndex: -1
    }
  },
  methods: {
    changeBg (index) {
      this.currentIndex = index
    },
    leaveIndex () {
      this.currentIndex = -1
    }
  }
</script>>
<style>
  .cur {
    background-color: skyblue;
  }
</style>

为实现需求2,将全部商品分类与下方三级联动数据包裹在一个div里,将鼠标移出事件添加在这个div里

 <div @mouseleave="leaveIndex">
    <h2 class="all">全部商品分类</h2>
     <div>..三级联动数据...</div>
</div>

3. 控制二三级数据隐藏与显示–绑定style样式

在这里插入图片描述

4. 三级联动的节流和防抖

1、什么是节流和防抖
  事件触发的非常频繁时,每一次的触发,回调函数都要去执行。但是如果触发的十分频繁而回调函数内部有计算等其他内容,则很可能出现浏览器卡顿,导致只有几次触发得到响应。

节流:在规定的间隔时间范围内不会重复触发回调,把频繁触发变为少量触发。

防抖:前面的所有的触发都被取消,也就是如果有连续快速的触发,只会执行一次。

应用:某些轮播图,快速点击切换图片时,可进行防抖或节流。

防抖:用户操作频繁,无关规定时间长短,期间只执行一次。
节流:用户操作很频繁,但是把频繁的操作变成少量操作【可以给浏览器充裕的时间解析代码】即规定时间执行一次。

具体看JS博客

2、三级联动节流
当鼠标快速从上往下移动时(即用户操作频繁),并不是所有词条的mouseenter事件都被触发。
在这里插入图片描述
节流采用lodash库提供的函数,由于vue中包含了lodash,所以不用提前安装

// 全部功能函数引入
 import _ from 'lodash'
// 或采用 按需引入
import throttle from 'lodash/throttle' 

methods:{
      /*
      正常情况(用户慢慢操作):鼠标进入每一个一级分类的h3,都会触发鼠标进入事件
      非正常情况(用户操作很快):只有部分触发进入事件,这是由于用户行为过快,导致浏览器反应不过来。
      如果当前回调函数中有一些大量业务,则有可能出现卡顿
      */
  // 这里的throttle回调函数别用箭头函数,可能出现上下文this问题
   changeBg: throttle(function (index) {
      this.currentIndex = index
      console.log('鼠标进入词条' + index);
	}, 50) 
}

5. 三级联动路由跳转及传参

需求:用户点击三级联动中的一级分类、二级分类、三级分类时,Home模块跳转到Search模块,并且在路由跳转时,将categoryNamecategoryId携带过去

在这里插入图片描述

1、路由跳转的方式

(1)、声明式导航router-link

router-link本质上是一个组件,当服务器的数据返回之后,会循环创建、渲染出很多的router-link实例组件。由于三级联动中链接较多,一瞬间创建很多组件实例十分消耗内存。因此采用router-link会出现卡顿现象。

(2)、编程式导航

 可通过添加监听点击事件实现路由跳转。但是每个a标签都要绑定自己的回调,这样不太好。
 只绑定一个回调要比绑很多回调要好,所以考虑采用事件委托的方式。事件委托是将点击事件添加到父节点中,这样任意子节点的事件都会冒泡到父节点,进而父节点的触发点击事件、调用回调函数。回顾事件委托:WebAPI(二)、事件委托

综上,采用编程式导航+事件委托的方式实现路由跳转。而这种方式存在两个问题。

(1)、编程式导航+事件委托–自定义属性

问题:

1.事件委托是把全部的子节点【h3、dt、dl】的事件都委派给父节点,如何确定点击的一定是a标签呢

2.即使确定点击的是a标签,如何区分是一级、二级、三级分类的标签。

解决方法:采用自定义属性
回顾自定义属性:WebAPI(一)、自定义属性

给a标签加上自定义属性,通过event.target.dataset获取到这些自定义属性

在这里插入图片描述
选择div父节点,绑定点击事件
在这里插入图片描述

// 跳转search页面
goSearch (event) {
    // 解构赋值,只有a标签才有这些自定义属性
    const { categoryname, category1id, category2id, category3id } = event.target.dataset
    // 组装参数
    let location = { name: 'search' }
    let query = { categoryName: categoryname }
    // 当前这个if语句:一定是a标签才会进入
    if (categoryname) {
        if (category1id) {  // 一定是a标签:一级分类
            query.category1Id = category1id
        } else if (category2id) {   // 一定是a标签:二级分类
            query.category2Id = category2id
        } else {  // 一定是a标签:三级分类
            query.category3Id = category3id
        }
    }
    // 给location对象配置上query属性
    location.query = query
    this.$router.push(location)
}

6、 Search模块三级联动显示与隐藏

Search页面也有一个三级联动,且刚进入这个界面时,三级联动数据并不展示。鼠标移入全部商品分类时展示数据,离开时隐藏数据。

(1)、Search模块使用TypeNav组件

由于TypeNav组件是一个全局组件,直接使用即可

在这里插入图片描述

(2)、控制TypeNav的显示与隐藏

可以在TypeNav中使用v-show来决定TypeNav是显示还是隐藏。新增一个属性isShow
在这里插入图片描述
当由Home页面进入Search页面时,TypeNav组件会再重新挂载,所以在TypeNav挂载时(即钩子函数mounted),通过当前的路由信息,就决定这个组件是该显示还是隐藏。TypeNav是非路由组件,其$route信息是当前路由组件的信息。如果当前路由不是Home模块,即路径不是/home时,则隐藏。
在这里插入图片描述

(3)、鼠标移入移出与TypeNav的显示与隐藏

  当鼠标移入全部商品分类这一大块内容时,无论是home页面还是search页面,TypeNav都是显示的,所以isShow=true
   当鼠标移出这部分时,home页面中,这部分不隐藏。其他页面中,还是要隐藏起来。所以鼠标事件的回调函数如下图所示:

在这里插入图片描述

(4)、三级联动显示与隐藏的动画效果

transition标签:
在这里插入图片描述

// 过渡
// 进入的起点,离开的终点
.sort-enter,
.sort-leave-to {
  opacity: 0;
}
// 进入及离开的过程
.sort-enter-active,
.sort-leave-active {
  transition: all 0.3s linear;
}
// 进入的终点,离开的起点
.sort-enter-to,
.sort-leave {
  opacity: 1;
}

7、 TypeNav重复发送请求的优化

由于多个页面都使用了TypeNav组件,当进入Home页面时,TypeNav加载一次。进入Search页面时又加载一次。而三级联动数据的请求写在了TypeNav组件的mounted函数里,所以切换页面时会重复发送请求,而数据都是一样的,发一次请求就够了,没必要多次发送。

解决方法:请求写在根组件(App.vue)里

在这里插入图片描述
根组件只加载一次,所以只发送一次请求。

8. 合并Search页面的query与params参数

目前跳往Search页面的情况有两种:

  • Header组件中,输入关键词,点击搜索。跳转到Search页面(携带params参数)
  • TypeNav组件中,点击分类,跳转到Search页面(携带query参数)。
    在这里插入图片描述
    但是当先通过点击三级联动的链接跳转到搜索页面(有query参数),再通过关键词搜索(携带params参数)跳转Search页面时,三级联动的参数则会不见。

比如通过三级联动点击"手机",跳转到搜索页面,路径显示为:

localhosr:8080/#/search?categoryName=手机&category3Id=61

然后再通过搜索框搜索"华为":

localhosr:8080/#/search/华为

解决方法:将Header.vue里的回调函数加上query参数

// Header.vue
goSearch () {
    this.$router.push({
        name: 'search',
        params: {
            keyWord: this.keyWord || undefined
        },
        query: this.$route.query
   })
}

在这里插入图片描述

这里本来还有一个if判断,判断query是否为空,但是不起作用,具体原因博主DantinZhang有写过; 参考博客:Vue2电商前台项目(二):完成Home首页模块业务_电商开源项目vue-CSDN博客

六、Home首页的ListContainer和Floor组件

1. 搭建mock

(1)安装mock:npm install mockjs,并在src文件夹下新建mock文件夹,方便进行mock的配置

(2)创建数据文件:

  • 轮播图banner数据文件src/mock/banner.json
  • 楼层数据文件:src/mock/floor.json

(3)把数据文件里用到的图片资源放到src/images文件夹里。

(4) 在mock文件夹下创建mockServe.js,进行配置
在这里插入图片描述
(5) 在main.js文件里引入 mockServe.js,让假数据一上来就先执行一下

import './mock/mockServer'

2. 搭建ListContainer组件

(1)、 mock虚拟数据的ajax请求

  • 创建api/mockRequest.js
    之前二次封装的axios的用来给后台服务器发送请求的。对于向mock虚拟数据发送请求,同样先对axios进行二次封装。不同的是baseURL的值改为在mockServe.js里设置的请求路径
    在这里插入图片描述
  • 放入api/index.js中,统一进行api管理
import mockRequests from './mockRequest'
// 获取轮播图数据的api
export const reqBannerList = () => {
  return mockRequests({ url: '/banner', method: 'get' })

(2)、 获取轮播图数据

Listcontainer组件发送请求,获取数据,存到Vuex里,组件获取Vuex的数据

(3)、 搭建轮播图

  • 安装Swiper:npm install swiper@5

    • Swiper基本使用:Swiper中文网-轮播图幻灯片js插件,H5页面前端开发
  • 引包: import Swiper from 'swiper'

  • 引样式:import 'swiper/css/swiper.css'; 由于页面中不只这一处使用轮播图,所以样式可以从主文件(main.js)中引入。

    此时轮播图只是静态样式,原因是还未创建实例

- 创建Swiper实例的讨论

创建实例之后,轮播图才有动态效果。问题是应该在什么时候,在哪里创建Swiper实例?

1、放在mounted函数?

mounted () {
    console.log('listContainer--Mounted加载');
    // 发送请求并将数据存储在vuex里
    console.log('发送ajax请求');
    this.$store.dispatch('home/getBannerList')
    // 创建实例
    console.log('new Swiper实例');
    new Swiper('.swiper-container',{...})
}

轮播图仍未静态的。new Swiper实例之前,页面中的结构应该要完整。mounted里有一个异步操作,会导致创建实例先执行,当new Swiper实例时,该组件还未获取到数据,v-for渲染结构并不完全,也就是此时的结构是不完整的。所以此时仍是静态效果

3、采用setTimeout异步函数
在mounted函数里,存在的问题是先创建了实例,后有的数据,所以才不起作用。那考虑如何现有数据,再创建实例------采用异步函数

mounted () {
    console.log('listContainer--Mounted加载');
    // 发送请求并将数据存储在vuex里
    this.$store.dispatch('home/getBannerList')
    // 设置定时器,等组件获取到请求的数据之后,再实例化Swpier
    setTimeout(() => {
        console.log('new Swiper实例');
        new Swiper('.swiper-container', {
            ...
        }, 1000)
}

这种方式可以,但不是最优,因为发送ajax请求的时间不确定,所以定时器时间不好把握

4、watch+$nextTick(最优)

  • 数据监听watch:监听已有数据变化
  • $nextTick: 在DOM更新结束后,立即调用这个$nextTick的回调函数。也就是执行这个回调的时候,能够保证服务器的数据回来了,v-for执行完毕了(即轮播图的结构已经完成了)。$nextTick可以保证页面中的结构一定是有的,经常和很多插件一起使用。要是还不明白,回顾博客 Vue(九) nextTick。
watch: {
    // 监听bannerList数据的变化,因为这条数据发生过变化---由空数组变为数组里有4个元素
    bannerList: {
      handler () {
        this.$nextTick(() => {
          new Swiper('.swiper-container', {
            loop: true, // 循环模式
            // 如果需要分页器
            pagination: {
              el: '.swiper-pagination'
            },
            // 如果需要前进后退按钮
            navigation: {
              nextEl: '.swiper-button-next',
              prevEl: '.swiper-button-prev',
            }
          })
        })
      }
    }
  }

watch监听bannerList属性的属性值的变化,当handler函数执行时,只能保证bannerList的数据已经有了,不再是空数组,但是没办法保证v-for已经将这些数据渲染完成。当v-for渲染完成后,结构才完整。因此采用nextTick

3. 搭建Floor组件

经典流程:封装api => 组件挂载完毕时发送请求、获取数据 => 数据存到Vuex中(vuex三件套state、actions、mutations) =>渲染页面

(1)、封装api、发送请求

api/index.js里封装api

// Floor数据
export const reqFloorList = () => {
  return mockRequests({ url: '/floor', method: 'get' })
}

Vuex保存数据及Home组件获取数据
(回顾Home页面,Home页面中有两个<Floor/>标签,需要通过v-for来遍历生成floor组件,所以需要在Home组件中进行dispatch。)
在这里插入图片描述

(2)、 动态数据渲染页面

Home组件将数据传递给子组件Floor

(高频面试题,父组件给子组件传值的方式/组件通信的方式有哪些?
props、自定义事件:Vue(八) props 自定义事件
全局事件总线、消息订阅与发布:Vue(九)全局事件总线、消息订阅与发布
插槽:Vue(十一) 插槽
Vuex: Vue(十二) Vuex

<!-- Home.vue -->
<Floor v-for="f in floorList" :key="f.id" :list="f"></Floor>
<!-- Floor.vue -->
props: ['list']

(3)、 Floor组件里的轮播图

在Floor里,new Swiper实例可以放在mounted里,因为Floor里的数据是父组件Home传递过来的,Floor里没有任何异步操作,所以挂在完毕之后页面结构就会现有,所以创建Swiper实例是可行的。(之前ListContainer组件内发送了异步请求,当创建Swiper实例时,由于数据不全,所以轮播图的结构并不完整)

(4)、 封装轮播图

  由于轮播图在多个组件中用到,所以可将轮播图封装为全局组件。前提是保证目前用到轮播图的地方,轮播图的代码一致。根据上边可知,ListContainer组件和Floor组件的区别是new Swiper实例的地方不一致,ListContainer用的是watch+$nextTick, Floor用的是mounted。

让Floor组件向ListContainer组件看齐,将new Swiper实例放到watch监听里:

list: {
    // 因为Floor中的list数据是父组件传过来的,没有发生过变化,所以需要上来立即执行一次监听,创建Swiper实例。
    immediate: true,
        handler () {
        // 数据已经有了,但是v-for动态渲染结构还是没有办法确定,因此还是需要nextTick
        this.$nextTick(() => {
            new Swiper(this.$refs.mySwiper, {
                loop: true, // 循环模式
                pagination: { // 如果需要分页器
                    el: '.swiper-pagination',
                    clickable: true
                },
                navigation: { // 如果需要前进后退按钮
                    nextEl: '.swiper-button-next',
                    prevEl: '.swiper-button-prev',
                }
            })
        })
    }
}

最终封装为Carousel组件:

<!--src/components/Carousel/index.vue--> 
<template>
  <div class="swiper-container" ref="mySwiper">
    <div class="swiper-wrapper">
      <div class="swiper-slide" v-for="(s, index) in list" :key="index">
        <img :src="s.imgUrl" />
      </div>
    </div>
    <!-- 如果需要分页器 -->
    <div class="swiper-pagination"></div>
    <!-- 如果需要导航按钮 -->
    <div class="swiper-button-prev"></div>
    <div class="swiper-button-next"></div>
  </div>
</template>
<script>
import Swiper from 'swiper'
export default {
  name: 'Carousel',
  props: ['list'],
  // 监听List数据的变化,
  //ListContainer组件中的这条数据发生过变化(由空数组变为数组里有4个元素),所以可用watch监听
  watch: {
    list: {
     // 因为Floor中的list数据是父组件传过来的,没有发生过变化,所以需要上来立即执行一次监听,创建Swiper实例。
      immediate: true,
      handler () {
          // 数据已经有了,但是v-for动态渲染结构还是没有办法确定,因此需要nextTick
        this.$nextTick(() => {
          new Swiper(this.$refs.mySwiper, {
            loop: true,
            pagination: { // 如果需要分页器
              el: '.swiper-pagination',
              clickable: true
            },
            navigation: { // 如果需要前进后退按钮
              nextEl: '.swiper-button-next',
              prevEl: '.swiper-button-prev',
            }
          })
        })
      }
    }
  }
}
</script>

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

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

相关文章

CAS概念、性质、优缺点 | 乐观锁、悲观锁是什么?

前言&#xff1a; 今天在深入了解HashMap时&#xff0c;看到这句话&#xff1a;“concurrentHashMap&#xff0c;在 JDK 1.7 中采用 分段锁的方式&#xff1b;JDK 1.8 中直接采用了CAS&#xff08;无锁算法&#xff09; synchronized。” 哦~~这个CAS好像之前接触过&#xff0c…

VSCode拉取远程项目

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…

2024年测评7款最佳AI论文修改润色平台

在2024年&#xff0c;AI论文修改润色平台的测评和推荐成为学术界和研究者们关注的热点。本文将详细评测并推荐7款最佳AI论文修改润色平台&#xff0c;包括千笔-AIPassPaper&#xff0c;并结合我搜索到的资料进行分析。 一、千笔-AIPassPaper 千笔-AIPassPaper是一款集论文大纲…

芯旺微,车规级32位MCU KF32A芯片简介

文章目录 1. 产品功能特点2. 行业应用3. 开发环境(IDE)4. 开发资源5. KungFu 内核参考1. 产品功能特点 2. 行业应用 汽车照明汽车车窗控制汽车空调面板汽车控制器3. 开发环境(IDE)

营养方案调整执行流程 第十篇

追踪调整方案 疾病诊断≠营养诊断 出健康管理建议应考虑地域习惯等特点&#xff0c;因人而异

HarmonyOS应用开发( Beta5.0)一杯冰美式的时间“拿捏Grid组件”

常见情形 在很多手机商城的页面中会出现类似网格状一样的情况&#xff0c;例如&#xff1a; 京东 ​这里呢是采用Grid组件中的控制滚动,里面的rowsTemplate属性为一行且不对列的行数属性进行操作&#xff0c;这样的话就可以控制水平滑动了。 2.淘宝 ​ 这里就是极其简单的2*…

Google Play结算防掉单方案

我们公司的产品主要是出海产品,使用的是Google Play支付,但是在上线以后,经常有客诉,说支付以后,权益没有到账,于是对整个Google支付体系做了研究了一下。 我们的整个支付流程图大概如下: 其中后端参考的文档地址为: https://developers.google.com/android-publishe…

Springboot中基于X509完成SSL检验的原理与实践

前言 各位对HTTPS不陌生吧&#xff1f;几乎涉及安全的领域&#xff0c;均要求通过HTTPS协议进行数据传输。而在传输过程中&#xff0c;又涉及到了SSL证书的使用。既然提到了SSL证书&#xff0c;那咱们先了解了解什么是SSL证书&#xff1a; SSL证书通过在客户端浏览器和Web服务…

生信代码入门:从零开始掌握生物信息学编程技能

少走弯路,高效分析;了解生信云,访问 【生信圆桌x生信专用云服务器】 : www.tebteb.cc 介绍 生物信息学是一个高度跨学科的领域&#xff0c;结合了生物学、计算机科学和统计学。随着高通量测序技术的发展&#xff0c;海量的生物数据需要通过编程来进行处理和分析。因此&#x…

如何使用云服务器AutoDL进行炼丹

如何使用云服务器进行炼丹 文章目录 如何使用云服务器进行炼丹1、选择平台2、学生认证3、租用新实例1&#xff09;创建实例2&#xff09;选择镜像3&#xff09;注意事项 4、文件传输1&#xff09;下载XFTP&#xff0c;用来传输文件2&#xff09;XFTP连接 5、pycharm远程连接1&a…

【Github项目推荐】DataLoom

项目推荐 - DataLoom 项目背景 在数据驱动的时代&#xff0c;越来越多的企业和个人用户需要从复杂的数据中提取出高价值的信息。然而&#xff0c;传统的数据处理和分析流程复杂且耗时&#xff0c;需要技术人员的深度参与。那么&#xff0c;有没有一种工具能够简化这一过程&am…

Linux:归档及压缩

tar命令 • tar 集成备份工具 – -c&#xff1a;创建归档 – -x&#xff1a;释放归档 – -f&#xff1a;指定归档文件名称,必须在所有选项的最后 – -z、-j、-J&#xff1a;调用 .gz、.bz2、.xz 格式工具进行处理 – -t&#xff1a;显示归档中的文件清单 – -C&#xff1a;指定…

十年多空局

我收到的有关大洋彼岸的推送&#xff1a; 微信和头条上的长者们&#xff0c; 讲着他们小时候没有的GPU和生物技术&#xff0c; 看多 B站上的年轻人&#xff0c; 谈着他们一知半解的制度设计和宏观经济&#xff0c; 看空 十年尺度的看空与看多

githup怎么上传自己的项目

&#xff08;1&#xff09;首先进入自己要上传项目的文件夹中&#xff0c;然后点击Open git Bash here. &#xff08;2&#xff09;然后进入下面界面&#xff0c;输入git init &#xff08;3&#xff09;然后就会生成一个.git的文件夹 &#xff08;4&#xff09;输入git add *…

如何处理软件卸载不干净的情况?

如何处理软件卸载不干净的情况&#xff1f; 一、清理注册表 下载CCleaner&#xff0c;下载之后&#xff0c;点击settings&#xff0c;将语言改为中文。 点击注册表&#xff0c;点击扫描问题-修复选定的问题&#xff0c;最好将之前的注册表完整备份。 反复这一过程&#xff0c…

Spring Boot集成Tess4J实现OCR

1.什么是Tess4j&#xff1f; Tesseract是一个开源的光学字符识别&#xff08;OCR&#xff09;引擎&#xff0c;它可以将图像中的文字转换为计算机可读的文本。支持多种语言和书面语言&#xff0c;并且可以在命令行中执行。它是一个流行的开源OCR工具&#xff0c;可以在许多不同…

PHP-FPM 远程代码执行漏洞(CVE-2019-11043)复现

启动容器 docker-compose up -d 查看端口 docker ps 端口为:8080,访问网站&#xff0c;搭建成功 安装漏洞利用工具 攻击 go run . "http://172.16.1.14:8080//index.php" 显示漏洞利用成功&#xff0c;浏览器进行访问&#xff0c;成功复现

微信小程序开发项目详细讲解

​ 大家好&#xff0c;我是程序员小羊&#xff01; 前言&#xff1a; 微信小程序是一种无需下载安装即可使用的应用程序&#xff0c;基于微信平台开发&#xff0c;能够提供类似原生应用的体验。以下是微信小程序开发的详细讲解&#xff0c;涵盖从项目准备、开发环境搭建到关键…

【无标题】符文价值的退化页

我们利用现有的符文体系建立了一个健全的符文扩展空间&#xff0c;可假若符文让我们感到十分困惑&#xff0c;我们不介意毁灭它们&#xff0c;让一切回到没有字迹的蛮荒纪。 如此&#xff0c;眼睛也失去了作用。我们的成GUO也会给后来者提供又是一DUI 令人眼花缭乱的无用符咒。…

DIC技术助力新能源汽车主机厂力学测试研发与整车性能提升

在新能源汽车研发过程中&#xff0c;非接触式全视场应变DIC测量方案&#xff0c;越来越受到汽车主机厂的信赖与认可。传统接触式传感器&#xff0c;在精度、灵活性和数据处理能力上存在局限。DIC技术可提供精确、高效、全视场、便捷的非接触式测量解决方案。 在汽车研发阶段&a…