Vue2电商前台项目(三):完成Search搜索模块业务

news2024/11/28 1:22:26

目录

一、请求数据并展示

1.写Search模块的接口

2.写Vuex中的search仓库(三连环)

3.组件拿到search仓库的数据

用getters简化仓库中的数据

4.渲染商品数据到页面

5.search模块根据不同的参数获取数据展示

(1)把派发actions的操作封装为函数

(2)设置参数默认值

(3)Object.assign合并对象

(4)再次发请求获取数据 

6.渲染子组件数据到页面

三、面包屑部分的开发

1.面包屑处理分类的问题

2.面包屑处理关键字

(1)删除标签

(2)删除表单框里的关键字

(3)删除路径中的params参数

3.面包屑处理品牌信息

(1)子传父:组件自定义事件

(2)添加品牌面包屑

四、平台售卖属性的操作

(1)子传父:组件自定义事件

(2)添加面包屑

五、Search模块的排序操作!!!

1.谁应该有类名

2.谁应该有箭头

3.实现点击切换样式和箭头

六、实现分页器功能!!!

1.分页器所需要的数据(4个条件)

2.先传假数据

(1)计算总页数

(2)计算连续页的开始和结束数字

(3)分页器动态展示

3.首尾页和省略号什么时候显示?

4.把假数据替换为真数据

5.给当前按钮添加样式


一、请求数据并展示

写完静态组件就写api然后写三连环

1.写Search模块的接口

//获取search模块接口,请求需要带参数
//给服务器传递参数的值至少是个空数组
export const reqGetSearchInfo = (params) => {
   return requests({ url: "http://gmall-h5-api.atguigu.cn/api/list", method: 'post', data: params })
}

2.写Vuex中的search仓库(三连环)

import { reqGetSearchInfo } from "@/api"
// import search from "core-js/fn/symbol/search"
//search模块下的小仓库
const state = {
    searchList: {}
}
const mutations = {
    GETSEARCHLIST(state, searchList) {
        state.searchList = searchList
    }
}
const actions = {
    //获取search模块数据
    async getSearchList({ commit }, params = {}) {
        let result = await reqGetSearchInfo(params)
        if (result.code == 200) {
            commit('GETSEARCHLIST', result.data)
        }

    }
}
//getters为了简化仓库当中的数据而生
const getters = {}
export default {
    state,
    mutations,
    actions,
    getters
}

入口文件引入:

import {reqGetSearchInfo} from '@/api'

search组件当中派发action:

mounted() {
    this.$store.dispatch('getSearchList', {});
  },

3.组件拿到search仓库的数据

捞数据,以前的写法:

import {mapState} from 'vuex'
、、、
computed:{
    ...mapState({
      goodsList:state=>state.search.searchList.goodsList
    })
  }

用getters简化仓库中的数据
 

注意仓库当中state是分模块的,getters是不分模块的

const getters = {
    goodsList(state) {
        return state.searchList.goodsList||[]
        //为了防止没网,返回的就是undefined
    },
    trademarkList(state) {
        return state.searchList.trademarkList||[]
    },
    attrsList(state) {
        return state.searchList.attrsList||[]
    },
}
import {mapGetters} from 'vuex'
mounted() {
    this.$store.dispatch('getSearchList', {});
  },
  computed:{
    ...mapGetters(['goodsList'])
    //这样直接写search组件中就有goodsList数组了
    //getters模块不划分模块,直接用数组
  }

4.渲染商品数据到页面

 <li class="yui3-u-1-5" v-for="(good,index) in goodsList" :key="good.id">
                <div class="list-wrap">
                  <div class="p-img">
                    <a href="item.html" target="_blank"
                      ><img :src="good.defaultImg"
                    /></a>
                  </div>
                  <div class="price">
                    <strong>
                      <em>¥&nbsp;</em>
                      <i>{{good.price}}.00</i>

5.search模块根据不同的参数获取数据展示

(1)把派发actions的操作封装为函数

我们目前的dispatch只能在挂载完毕的时候发起一次请求进行捞取数据,正确的应该是我再搜索啥应该再去捞取

可以把它生成一个函数,调用一次就去捞取数据

methods: {
    getData() {
      //根据参数向服务器发请求获取数据
      this.$store.dispatch("getSearchList", {});
    },
  },

mounted负责来调用函数

mounted() {
    this.getData();
  },

(2)设置参数默认值

数据类型是对象,参数:

data() {
    //我们之前返回的参数都是空数组,现在给它带上参数
    return {
      searchParams: {
        category1Id: "",
        category2Id: "",
        category3Id: "",
        categoryName: "",//分类名
        keyword: "",//用户填进去的
        order: "",//排序
        //这些全是空因为不知道用户填的什么
        pageNo: 1,
        //默认打开是第一页
        pageSize: 10,
        //页面显示多少个数据
        props: [],
        trademark: "",//品牌
      },
    };
  },

在mounted之前我们就得把参数值带过去才能捞取数据,mounted生命周期之前的有beforecreat、created、beforemount,而且beforecreat是获取不到数据的,我们选择在beforemount里,发请求之前发参数,复杂写法:

(3)Object.assign合并对象

用Object.assign:ES6新增的语法,合并对象

Object.assign(x,a,b),三个参数都是数组,后两个给空的x数组赋值

beforeMount() {
    Object.assign(this.searchParams,this.$route.query,this.$route.params)
  },

现在的问题是更新的函数在mounted里面, 所以请求只能发一次,点了首页的手机再搜索华为页面不动

(4)再次发请求获取数据 

我们每次筛选之后路由的信息都在发生变化,所以我们不在mounted里写了,监听路由的变化($route的params和query参数),路由变就请求

watch:{
    //这里不用this.$route,$route就直接是vc上的属性
    $route(newValue,oldValue){
      //参数发生变化的时候我们还得重新去整理参数
      Object.assign(this.searchParams,this.$route.query,this.$route.params)
      //再次发起ajax请求
      this.getData();
    }
  },

每一次请求完毕想要下一次请求之前应该先把当前的请求都删了

watch:{
    //这里不用this.$route,$route就直接是vc上的属性
    $route(newValue,oldValue){
      //参数发生变化的时候我们还得重新去整理参数
      Object.assign(this.searchParams,this.$route.query,this.$route.params)
      //再次发起ajax请求
      this.getData();
      //置空上一次的请求
      this.searchParams.category1Id=''
      this.searchParams.category2Id=''
      this.searchParams.category3Id=''
    }
  },

keyword有时候会复用所以不置空

6.渲染子组件数据到页面

现在开始做search组件的小组件SearchSelector

import {mapGetters} from 'vuex'
  export default {
    name: 'SearchSelector',
    computed:{
      ...mapGetters(['trademarkList','attrsList'])
    }
  }

 <li v-for="trademark in trademarkList" :key="trademark.tmId">{{trademark.tmName}})
     、、、
 <div class="type-wrap" v-for="attr in attrsList" :key="attr.attrId">
  <div class="fl key">{{attr.attrName}}</div>
   <div class="fl value">
     <ul class="type-list">
      <li v-for="(attrValue,index) in attr.attrValueList" :key="index">
         <a>{{attrValue}}</a>
         、、、

然后v-for该拆了拆

三、面包屑部分的开发

1.面包屑处理分类的问题

面包屑可能有也可能没有用v-if,而且点击x号就会删除,设置一个点击事件

<li class="with-x" v-if="searchParams.categoryName">{{searchParams.categoryName}}<i @click="removeCategoryName">×</i></li>
//删除分类的名字
    removeCategoryName() {
      this.searchParams.categoryName = ""; //只删一个为啥置空啊
      //删了之后name和id都得置空
      this.searchParams.category1Id = "";
      this.searchParams.category2Id = "";
      this.searchParams.category3Id = "";
      //置空之后还得向服务器发请求
      this.getData();
    },

这里删除置空好像因为目前我们每次都只有一个标签,所以直接置空了

所有Id和name都置空还是会有十个参数返回服务器那边找数据,既然是空的就没必要添加负担,可以赋值为undefined

this.searchParams.categoryName = undefined; //只删一个为啥置空啊
      //删了之后name和id都得置空
      this.searchParams.category1Id = undefined;
      this.searchParams.category2Id = undefined;
      this.searchParams.category3Id = undefined;

还有一个bug就是我们删除标签之后地址栏还是显示那个标签

点击选项之后路由跳转带着参数,页面的路径就会带着标签,我们可以让删除标签之后再进行页面跳转,自己跳自己,再改路径

//地址也需要修改
      this.$router.push({name:"search"})

这么写不严谨,我只是x了标签,但是我可能有keyword呢,这句话连我的params参数一起都删了

if (this.$route.params) {
        this.$router.push({ name: "search" ,params:this.$route.params});
      }

要是有params参数的话,跳转到search而且带着params参数

2.面包屑处理关键字

现在实现搜索关键字,关键字也会有标签,关闭标签路径当中的params没了,搜索框中的文字也没了

(1)删除标签

<!-- 关键字的面包屑 -->
<li class="with-x" v-if="searchParams.keyword">{{ searchParams.keyword}}<i @click="removeKeyword">×</i></li>
//删除关键字
    removeKeyword(){
      //这一步置空的是search路由的关键字,header上的没有
      this.searchParams.keyword = undefined;
      //重新发请求
      this.getData();

(2)删除表单框里的关键字

清除search路由的关键字并且重新发请求,然后就该清除header组件的关键字了,我们现在在search组件中,他俩是兄弟关系,用到组件间通信,配置$bus全局事件总线

main.js:

new Vue({
  render: h => h(App),
  beforeCreate(){
    Vue.prototype.$bus=this
  },

search通知:

 //通知兄弟组件header 清除关键字
      this.$bus.$emit("clear")

header:

mounted() {
    //通过全局事件总线清除关键字
    this.$bus.$on("clear",()=>{
      this.keyword=''
    })
  },

(3)删除路径中的params参数

//路由的跳转
      this.$router.push({ "name": 'search' })

这么写又把人家的query参数给丢了

//路由的跳转
      if (this.$route.params) {
        this.$router.push({ name: "search" ,query:this.$route.query});
      }

3.面包屑处理品牌信息

(1)子传父:组件自定义事件

实现点击品牌也能出现标签,首先给品牌添加点击事件,(trademark)传递参数为品牌的信息,参数类型为对象,子组件:

<ul class="logo-list">
  <li v-for="trademark in trademarkList" :key="trademark.tmId" @click="tradeMarkHandler(trademark)">{{trademark.tmName}})</li>
</ul>

点击之后就得带着品牌信息向服务器捞数据

注意:我们是让父组件发信息给服务器的,因为之前整理的参数都在父组件里,所以我们的子组件需要给父组件传过去品牌信息

子给父通信:自定义事件,父组件给子组件绑定一个自定义事件:

<!--selector-->
        <SearchSelector @trademarkInfo="trademarkInfo"/>

儿子触发回调函数:

methods: {
      tradeMarkHandler(trademark){
        //点击品牌之后整理参数,向服务器发请求
        //trademark是个对象 有相应的name和id
        this.$emit('trademarkInfo',trademark)
        //trademark为品牌名
      }
    },

父亲整理参数再重新发送:

trademarkInfo(trademark){
      //自定义事件的回调,触发在子组件触发
      //整理参数,格式要求是id:name
      this.searchParams.trademark=`${trademark.tmId}:${trademark.tmName}`
      //发请求
      this.getData();
    }

(2)添加品牌面包屑

 <!-- 品牌的面包屑 -->
<li class="with-x" v-if="searchParams.trademark">{{ searchParams.trademark.split(":")[1] }}<i @click="removeTrademark">×</i></li>

trademark现在的格式是id:name,但是我们展示标签的时候只想展示name,所以用split分割开,要数组【1】

removeTrademark(){
      this.searchParams.trademark=undefined
      this.getData();
    }

四、平台售卖属性的操作

(1)子传父:组件自定义事件

给系统、内存啥的添加面包屑

我们点击的是每个小li,给li加点击事件;props参数格式——id:name

<div class="type-wrap" v-for="attr in attrsList" :key="attr.attrId">
      <div class="fl key">{{attr.attrName}}</div>
      <div class="fl value">
        <ul class="type-list">
          <li v-for="(attrValue,index) in attr.attrValueList" :key="index" @click="attrInfo(attr,attrValue)">
            <!-- 这个attr是上面的v-for的参数,attrValue是这个v-for的参数 -->
            <a>{{attrValue}}</a>
          </li>
        </ul>
      </div>
//平台售卖属性
      attrInfo(attr,attrValue){
        this.$emit('attrInfo',attr,attrValue)
      }

然后我们得把attr和attrValue往父组件送

绑定自定义事件:

 <!--selector-->
        <SearchSelector @trademarkInfo="trademarkInfo" @attrInfo="attrInfo"/>
attrInfo(attr,attrValue){
      let props=`${attr.attrId}:${attrValue}:${attr.attrName}`
      this.searchParams.props.push(props)
      this.getData();
    }

(2)添加面包屑

我们这次就不能再用v-if了,因为以前那些要么显示要么不显示,这次是遍历props数组,有几个就得展示几个,用v-for

<li class="with-x" v-for="(attrValue,index) in searchParams.props" :key="index">
              {{ attrValue.split(":")[1] }}

但是有个bug,就是如果点两次16G它就给你弄两个16G的标签,所以往数组里push的时候就得先判断

if (this.searchParams.props.indexOf(props) == -1) {
        this.searchParams.props.push(props);
      }

数组去重:???.indexOf(xxx)==-1数组索引号为-1说明还没有

删除:先确定需不需要传参,我们删除的时候需要获得数组的索引值

<!-- 平台售卖的面包屑 -->
            <li
              class="with-x"
              v-for="(attrValue, index) in searchParams.props"
              :key="index"
            >
              {{ attrValue.split(":")[1] }}<i @click="removeAttr(index)">×</i>
            </li>
//移出平台售卖
    removeAttr(index){
      this.searchParams.props.splice(index,1)
      this.getData();
    }

五、Search模块的排序操作!!!

1.谁应该有类名

看数据里的order写的是1还是2,是1就是综合,2就是价格

<li :class="{active:searchParams.order.indexOf('1')!=-1}">
     <a>综合</a>
 </li>
<li :class="{active:searchParams.order.indexOf('2')!=-1}">
     <a>价格</a>
 </li>

order是几,哪个就是红色的

将上面这段代码封装成函数:

<li :class="{active:isOne}">
    <a>综合</a>
</li>
<li :class="{active:isTwo}">
    <a>价格</a>
</li>

computed: {
   、、、
    isOne(){
      return this.searchParams.order.indexOf('1')!=-1
    },
    isTwo(){
      return this.searchParams.order.indexOf('2')!=-1
    }
  },

2.谁应该有箭头

谁有类名谁就应该有箭头,箭头用iconfont,这次来使用一下在线的

在线链接没有协议名,往index.html link引入的时候要加上这个网站的协议名https

<link rel="stylesheet" href="https://at.alicdn.com/t/c/font_4501496_w5xz3uenvcs.css">

箭头向上还是向下取决于order数据里的desc还是asc

<ul class="sui-nav">
   <li :class="{active:isOne}"><a>综合<span v-show="isOne" class="iconfont" :class="{'icon-down':isDown,'icon-up':isUp}"></span></a>
   </li>
   <li :class="{active:isTwo}"><a>价格<span v-show="isTwo" class="iconfont" :class="{'icon-down':isDown,'icon-up':isUp}"></span></a>
   </li>

本来我还纳闷那个span里的v-show,后来发现order数字变了之后之前的还留着箭头,箭头应该是有红色样式的才有,也就是目前是它的数字span才能显示

isDown(){
      return this.searchParams.order.indexOf('desc')!=-1
    },
    isUp(){
      return this.searchParams.order.indexOf('asc')!=-1
    }

3.实现点击切换样式和箭头

我们点了一个红色的,它的箭头方向就应该切换;我们点一个白色的,它的背景色就应该变红,箭头默认为降序,所以我们得传参进去,判断点的是1还是2

    <li :class="{active:isOne}" @click="changeOrder('1')">
      、、、          
    <li :class="{active:isTwo}" @click="changeOrder('2')">          
changeOrder(flag){
      //flag代表用户点击的是1还是2
      let originOrder=this.searchParams.order//起始状态
      let originFlag=this.searchParams.order.split(":")[0]//记录起始是0还是1
      let originSort=this.searchParams.order.split(":")[1]//记录起始的顺序
      let newOrder=''//准备一个新的order属性值
      //点击综合
      if(flag==originFlag){
        newOrder=`${originFlag}:${originSort=="desc"?"asc":"desc"}`
        //这样写就不用一种一种的分情况写了
      }else{
        //点击的是价格,默认就降序
        newOrder=`${flag}:${'desc'}`
      }
      //将新的order给旧的
      this.searchParams.order=newOrder
      this.getData()
    }

这个三元表达式太妙了,我自己想肯定得一个一个情况分着写,最后别忘记把新的order给旧的

六、实现分页器功能!!!

1.分页器所需要的数据(4个条件)

分页是一个全局组件:pagitation,全局组件都得到main.js注册

Vue.component(Pagination.name,Pagination)
import {reqGetSearchInfo} from '@/api'

需要知道当前是第几页:pageNo字段

需要知道每一个需要展示多少条数据:pageSize字段

需要知道整个分页器一共有多少条数据:total字段

需要知道连续的页面个数:5或7(奇数——对称):continues字段

2.先传假数据

<Pagination :pageNo="1" :pageSize="3" :total="91" :continues="5" />
props:['pageNo','pageSize','total','continues']

真数据在服务器里面,我们先自己设置一些假数据把组件管理一下再传真数据

(1)计算总页数

computed:{
      totalPage(){
          return Math.ceil(this.total/this.pageSize)
          //向上取整
      }
  }

Math.ceil(xxx) 向上取整

<button>{{totalPage}}</button>

(2)计算连续页的开始和结束数字

startNumAndEndNum() {
        const {continues,pageNo,totalPage}=this//解构一下
        //定义两个变量存储起始和结束数字
        let start=0 ,end = 0
        //连续页数可能不到5页
        if(continues>totalPage){
            start=1
            end=totalPage
        }else{
            //正常数据,这块不能写死因为你到时候连续页数不一定是5,没准是7
            // start=pageNo-2
            // end =pageNo+2
            start=pageNo-parseInt(continues/2)
            end=pageNo+parseInt(continues/2)
        }

现在这样写有bug,就是假如你现在页数很多,但是你现在处于第一页,那么start就成负数了

假如当前是第一页,应该是1、2、3、4、5

假如是第二页,也应该是1、2、3、4、5

//不正常的数字纠正
            if(start<=0){
                start=1
                end=continues
            }

end还有bug,假如我现在在28页,end是(continues=5)30,但是我总页数可能就29页呢

 //end判断
            if(end>totalPage){
                end=totalPage
                start=totalPage-continues+1
            }
         }
        return {start,end}
//记得最后return啊,要不然上面用end、start的时候说undefined

(3)分页器动态展示

一个小tips:v-for可以遍历数组、数字、字符串、对象

<!-- 中间部分 -->
    <button v-for="(page, index) in startNumAndEndNum.end" :key="index">
      {{ page }}
    </button>

让它去遍历到最后一个数,如果end是10的话(pageNo=8),continues显示的是从1到10

过滤掉前面的数字:

<button v-for="(page, index) in startNumAndEndNum.end" :key="index" v-if="page>=startNumAndEndNum.start">{{ page }}</button>

3.首尾页和省略号什么时候显示?

但是存在bug,continues的start如果是1的话,跟前面的1重复了,就不再要前面的1了

<button v-if="startNumAndEndNum.start>1">1</button>

而且···得在start为3时才能出现:

<button v-if="startNumAndEndNum.start>2">···</button>

前面start的bug解决了,就该解决end的了

<button v-if="startNumAndEndNum.end<totalPage-1">···</button>
<button v-if="startNumAndEndNum.end<totalPage">{{ totalPage }}</button>

4.把假数据替换为真数据

去仓库中捞一下total,pageNo和pageSize在data中有

import { mapGetters,mapState } from "vuex";
computed:{
...mapState({
      total:state=>state.search.searchList.total
    })
<!-- 分页器 -->
<Pagination :pageNo="searchParams.pageNo" :pageSize="searchParams.pageSize" :total="total" :continues="5" />

儿子点击了哪页就得告诉父亲,当前的pageNo,子给父通信:自定义事件

<!-- 分页器 -->
<Pagination @getPageNo="getPageNo" 、、、 />
<button :disabled="pageNo==1" @click="$emit('getPageNo',getPageNo-1)">上一页</button>
    <!-- 点击传入当前页码-1,页数为1的时候不能点 -->
    <button v-if="startNumAndEndNum.start>1" @click="$emit('getPageNo',1)">1</button>
    <button v-if="startNumAndEndNum.start>2">···</button>
    <!-- 中间部分 -->
    <button v-for="(page, index) in startNumAndEndNum.end" :key="index" v-if="page>=startNumAndEndNum.start" @click="$emit('getPageNo',page)">
      {{ page }}
    </button>

    <button v-if="startNumAndEndNum.end<totalPage-1">···</button>
    <button v-if="startNumAndEndNum.end<totalPage" @click="$emit('getPageNo',totalPage)">{{ totalPage }}</button>
    <button :disabled="pageNo==totalPage" @click="$emit('getPageNo',getPageNo+1)">下一页</button>

分情况处理点击事件,点击的如果是上一页:第一页不能点击上一页,其他的点击传给当前的页数+1;下一页同理

中间部分点击之后就传当前点击的页数

然后父组件就得开始整理参数,然后重新发请求

getPageNo(){
      //整理带给服务器的参数
      this.searchParams.pageNo=pageNo
      this.getData()
    }

5.给当前按钮添加样式

点击哪个按钮它的颜色就变成skyblue

<button v-if="startNumAndEndNum.start>1" @click="$emit('getPageNo',1)" :class="{active:pageNo==1}">1</button>
    <button v-if="startNumAndEndNum.start>2">···</button>
    <!-- 中间部分 -->
    <button v-for="(page, index) in startNumAndEndNum.end" :key="index" v-if="page>=startNumAndEndNum.start" @click="$emit('getPageNo',page)" :class="{active:pageNo==page}">
      {{ page }}
    </button>

    <button v-if="startNumAndEndNum.end<totalPage-1">···</button>
    <button v-if="startNumAndEndNum.end<totalPage" @click="$emit('getPageNo',totalPage)" :class="{active:pageNo==totalPage}">{{ totalPage }}</button>
    <button :disabled="pageNo==totalPage" @click="$emit('getPageNo',getPageNo+1)">下一页</button>

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

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

相关文章

layui中对table表格内容鼠标移入显示 tips内容

要在Layui中的表格中实现鼠标移入显示Tips&#xff0c;你可以使用Layui的事件监听和Tips组件。 有两种实现方式&#xff01; 第一种是&#xff0c;通过自定义鼠标事件显示 tips。在渲染 table 时&#xff0c;对 filed 进行重构&#xff0c;增加相应的选择器标识&#xff0c;一…

冯喜运:4.10晚间黄金原油走势分析

黄金消息技术面分析&#xff1a;美国CPI年率创半年新高&#xff0c;美国3月未季调CPI年率录得3.5%&#xff0c;高于预期的3.4%水平&#xff0c;为2023年9月以来最高水平。美国CPI高于预期&#xff0c;现货黄金短线下挫16美元。日线当前的指标macd依旧属于金叉放量运行&#xff…

unipush+个推实现消息推送

1.注册个推平台的帐号个推&#xff0c;专业的数据智能服务商-为垂直领域提供数据智能解决方案 2.应用列表中选择新增应用/服务 3.填写下应用信息4.创建好应用后在manifest.json中的sdkConfigs配置上写入appid、appkey、appsecret "sdkConfigs" : {"ad" :…

tailwindcss+vue3+vite+preline项目搭建

最近原子化样式比较火&#xff0c;用了一下确实还不错&#xff0c;也确实是用一些标准的样式能够使网页看起来比较统一&#xff0c;而且能够极大的减轻起名字的压力&#xff0c;有利有弊&#xff0c;就不一一细说了。 之前开发都是习惯于使用vitevue3来开发的&#xff0c;此次搭…

ITK 重采样 resample

Itk 重新采样有二多种情况&#xff0c;这里说二种情况 1. 输入参数 &#xff0c;和输出相关数据&#xff0c;输出范围&#xff0c;spacing &#xff1b; typedef itk::Image< float, 3 > itkFloatImageType;typedef itk::ResampleImageFilter < itkFloatImageType, i…

观察者模式与发布-订阅模式的对决

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

基础算法(算法竞赛、蓝桥杯)--堆排序

1、B站视频链接&#xff1a;A15 堆 堆排序_哔哩哔哩_bilibili 题目链接&#xff1a;【模板】堆 - 洛谷 #include <iostream> using namespace std; int a[1000010],cnt; void up(int u){ //上浮if(u/2 && a[u/2]>a[u]) swap(a[u],a[u/2]), up(u/2); } void d…

练习题(2024/4/10)

1. 删除有序数组中的重复项 给你一个 非严格递增排列 的数组 nums &#xff0c;请你 原地 删除重复出现的元素&#xff0c;使每个元素 只出现一次 &#xff0c;返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。 考虑 nums 的唯一元…

Vue3---基础1(认识,创建)

变化 相对于Vue2&#xff0c;Vue3的变化&#xff1a; 性能的提升 打包大小减少 41% 初次渲染快 55%&#xff0c;更新渲染快133% 内存减少54% 源码的升级 使用 proxy 代替 defineProperty 实现响应式 重写虚拟 DOM 的实现和 Tree-shaking TypeScript Vue3就可以更好的支持TypeSc…

Harmony鸿蒙南向驱动开发-MMC

MMC&#xff08;MultiMedia Card&#xff09;即多媒体卡&#xff0c;是一种用于固态非易失性存储的小体积大容量的快闪存储卡。 MMC后续泛指一个接口协定&#xff08;一种卡式&#xff09;&#xff0c;能符合这种接口的内存器都可称作MMC储存体。主要包括几个部分&#xff1a;…

【java工具-灵活拉取数据库表结构和数据】

需求&#xff1a; 假设我们现在有一个需求&#xff0c;需要快速拉取数据库的某些表建表语句&#xff0c;和数据&#xff0c;平时做备份之类&#xff1b; 我这边自己写了个工具&#xff0c;不多废话&#xff0c;也不整虚的&#xff0c; 直接看代码&#xff1a; package com.…

SQL注入sqli_labs靶场第五、六题

第五题 根据报错信息&#xff0c;判断为单引号注入 没有发现回显点 方法&#xff1a;布尔盲注&#xff08;太耗时&#xff0c;不推荐使用&#xff09; 1&#xff09;猜解数据库名字&#xff1a;&#xff08;所有ASCII码值范围&#xff1a;0~127&#xff09; ?id1 and length…

Redis从入门到精通(四)Redis实战(一)短信登录

文章目录 前言第4章 Redis实战4.1 短信登录4.1.1 基于session实现短信登录4.1.1.1 短信登录逻辑梳理4.1.1.2 创建测试项目4.1.1.3 实现发送短信验证码功能4.1.1.4 实现用户登录功能4.1.1.5 实现登录拦截功能4.1.1.6 session共享问题 4.1.2 基于Redis实现短信登录4.1.2.1 Key-Va…

Web3 游戏周报(3.31-4.6)

【3.31-4.6】Web3 游戏行业动态&#xff1a; Xai 基金会宣布与 Reboot 达成合作拟支持 Pixel Vault: BattiePlan 游戏生态迁移 加密游戏 Hytopia 在节点销售获得 800 万美元后将于本月推出测试版 新加坡 Web3 游戏初创公司 Gomble Games 完成 1,000 万融资 NFT 卡牌游戏 Par…

PyCharm+PyQt5配置方法

一、前言 PyQt5PyQt5是一套Python绑定Digia QT5应用的框架。Qt库是最强大的GUI库之一PyQt5-toolsPyQt5中没有提供常用的Qt工具&#xff0c;比如图形界面开发工具Qt Designer&#xff0c;PyQt5-tools中包含了一系列常用工具Qt Designer可以通过Qt Designer来编写UI界面&#xf…

SPI外设简介

SPI外设简介 简介部分 可配置8/16位数据帧、高位先行/低位先行 SPI和I2C都是高位先行&#xff0c;串口是低位先行 PCLK是外设时钟&#xff0c;APB2是72MHz、APB1是36MHz SPI1的时钟频率比SPI2的大一倍 如果需要快速大量传输数据&#xff0c;可以使用DMA数据转运&#xff0…

Chrome谷歌下载入口

​hello&#xff0c;我是小索奇 发现好多人说谷歌浏览器在哪里下载呀&#xff0c;哪里可以找到&#xff1f; 你可能会心想&#xff0c;一个浏览器你还不会下载啊&#xff1f; 还真是&#xff0c;有很多伙伴找不到下载入口&#xff0c;为什么呢&#xff1f; Bing进行搜索&am…

2、java语法之循环、数组与方法(找工作版)

写在前面&#xff1a;整个系列文章是自己学习慕课相关视频&#xff0c;进行的一个总结。文章只是为了记录学习课程的整个过程&#xff0c;方便以后查漏补缺&#xff0c;找到对应章节。 文章目录 一、Java循环结构1、while循环2、do-while循环3、for循环4、嵌套循环5、break语句…

【技术揭秘】爬取网站或APP应用的几种常用方案:RPA、抓包工具、Python爬虫,你了解多少?

本来准备空闲之余尝试用RPA软件抓取数据&#xff0c;【AIRPA系列】1、利用AIRPA提升工作效率 应用场景 &#xff0c; 最近工作项目有点忙&#xff0c; RPA实操系列可能会晚点了&#xff08;自己真正实操后再写&#xff0c;copy别人的没啥意思&#xff09;。这里简单整理下爬取…

Docker快速上手及常用命令速查

Docker快速上手 安装 在ubuntu上安装docker: sudo apt-get install docker docker -v #查看版本在centos7上安装docker&#xff1a;(docker在YUM源的Extras仓库中) yum install docker systemctl start dockerdocker常用命令速查 #查看docker信息 docker info #查看本地镜…