购物车功能实现(小兔鲜儿)【Vue3】

news2024/11/13 23:21:26

购物车

流程梳理和本地加入购物车实现

购物车业务逻辑梳理拆解
在这里插入图片描述

  1. 整个购物车的实现分为两个大分支, 本地购物车操作和接口购物车操作
  2. 由于购物车数据的特殊性,采取Pinia管理购物车列表数据并添加持久化缓存

本地购物车 - 加入购物车实现

在这里插入图片描述

  1. 添加购物车
    基础思想:如果已经添加过相同的商品,就在其数量count上加一,如果没有添加过,就直接push到购物车列表中
// 封装购物车模块

import { defineStore } from 'pinia'
import { ref } from 'vue'


export const useCartStore = defineStore('cart', () => {
  // 1. 定义state - cartList
  const cartList = ref([])
  // 2. 定义action - addCart
  const addCart = (goods) => {
    console.log('添加', goods)
    // 添加购物车操作
    // 已添加过 - count + 1
    // 没有添加过 - 直接push
    // 思路:通过匹配传递过来的商品对象中的skuId能不能在cartList中找到,找到了就是添加过
    const item = cartList.value.find((item) => goods.skuId === item.skuId)
    if (item) {
      // 找到了
      item.count++
    } else {
      // 没找到
      cartList.value.push(goods)
    }
  }
  return {
    cartList,
    addCart
  }
}, {
  persist: true,
})

本地购物车 - 头部购物车列表渲染

在这里插入图片描述
2. 头部购物车
2.1. 头部购物车组件模版

<script setup>

</script>

<template>
  <div class="cart">
    <a class="curr" href="javascript:;">
      <i class="iconfont icon-cart"></i><em>2</em>
    </a>
    <div class="layer">
      <div class="list">
        <!--
        <div class="item" v-for="i in cartList" :key="i">
          <RouterLink to="">
            <img :src="i.picture" alt="" />
            <div class="center">
              <p class="name ellipsis-2">
                {{ i.name }}
              </p>
              <p class="attr ellipsis">{{ i.attrsText }}</p>
            </div>
            <div class="right">
              <p class="price">&yen;{{ i.price }}</p>
              <p class="count">x{{ i.count }}</p>
            </div>
          </RouterLink>
          <i class="iconfont icon-close-new" @click="store.delCart(i.skuId)"></i>
        </div>
        -->
      </div>
      <div class="foot">
        <div class="total">
          <p>10 件商品</p>
          <p>&yen; 100.00 </p>
        </div>
        <el-button size="large" type="primary" >去购物车结算</el-button>
      </div>
    </div>
</div>
</template>

<style scoped lang="scss">
.cart {
  width: 50px;
  position: relative;
  z-index: 600;

  .curr {
    height: 32px;
    line-height: 32px;
    text-align: center;
    position: relative;
    display: block;

    .icon-cart {
      font-size: 22px;
    }

    em {
      font-style: normal;
      position: absolute;
      right: 0;
      top: 0;
      padding: 1px 6px;
      line-height: 1;
      background: $helpColor;
      color: #fff;
      font-size: 12px;
      border-radius: 10px;
      font-family: Arial;
    }
  }

  &:hover {
    .layer {
      opacity: 1;
      transform: none;
    }
  }

  .layer {
    opacity: 0;
    transition: all 0.4s 0.2s;
    transform: translateY(-200px) scale(1, 0);
    width: 400px;
    height: 400px;
    position: absolute;
    top: 50px;
    right: 0;
    box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
    background: #fff;
    border-radius: 4px;
    padding-top: 10px;

    &::before {
      content: "";
      position: absolute;
      right: 14px;
      top: -10px;
      width: 20px;
      height: 20px;
      background: #fff;
      transform: scale(0.6, 1) rotate(45deg);
      box-shadow: -3px -3px 5px rgba(0, 0, 0, 0.1);
    }

    .foot {
      position: absolute;
      left: 0;
      bottom: 0;
      height: 70px;
      width: 100%;
      padding: 10px;
      display: flex;
      justify-content: space-between;
      background: #f8f8f8;
      align-items: center;

      .total {
        padding-left: 10px;
        color: #999;

        p {
          &:last-child {
            font-size: 18px;
            color: $priceColor;
          }
        }
      }
    }
  }

  .list {
    height: 310px;
    overflow: auto;
    padding: 0 10px;

    &::-webkit-scrollbar {
      width: 10px;
      height: 10px;
    }

    &::-webkit-scrollbar-track {
      background: #f8f8f8;
      border-radius: 2px;
    }

    &::-webkit-scrollbar-thumb {
      background: #eee;
      border-radius: 10px;
    }

    &::-webkit-scrollbar-thumb:hover {
      background: #ccc;
    }

    .item {
      border-bottom: 1px solid #f5f5f5;
      padding: 10px 0;
      position: relative;

      i {
        position: absolute;
        bottom: 38px;
        right: 0;
        opacity: 0;
        color: #666;
        transition: all 0.5s;
      }

      &:hover {
        i {
          opacity: 1;
          cursor: pointer;
        }
      }

      a {
        display: flex;
        align-items: center;

        img {
          height: 80px;
          width: 80px;
        }

        .center {
          padding: 0 10px;
          width: 200px;

          .name {
            font-size: 16px;
          }

          .attr {
            color: #999;
            padding-top: 5px;
          }
        }

        .right {
          width: 100px;
          padding-right: 20px;
          text-align: center;

          .price {
            font-size: 16px;
            color: $priceColor;
          }

          .count {
            color: #999;
            margin-top: 5px;
            font-size: 16px;
          }
        }
      }
    }
  }
}
</style>

2.2 渲染头部购物车数据

<script setup>
import { useCartStore } from '@/stores/cartStore'
const cartStore = useCartStore()

</script>

<template>
  <div class="cart">
    <a class="curr" href="javascript:;">
      <i class="iconfont icon-cart"></i><em>{{ cartStore.cartList.length }}</em>
    </a>
    <div class="layer">
      <div class="list">

        <div class="item" v-for="i in cartStore.cartList" :key="i">
          <RouterLink to="">
            <img :src="i.picture" alt="" />
            <div class="center">
              <p class="name ellipsis-2">
                {{ i.name }}
              </p>
              <p class="attr ellipsis">{{ i.attrsText }}</p>
            </div>
            <div class="right">
              <p class="price">&yen;{{ i.price }}</p>
              <p class="count">x{{ i.count }}</p>
            </div>
          </RouterLink>
          <i class="iconfont icon-close-new" @click="cartStore.delCart(i.skuId)"></i>
        </div>

      </div>
      <div class="foot">
        <div class="total">
          <p>{{ cartStore.allCount }} 件商品</p>
          <p>&yen; {{ cartStore.allPrice.toFixed(2) }} </p>
        </div>
        <el-button size="large" type="primary" @click="$router.push('/cartlist')">去购物车结算</el-button>
      </div>
    </div>
</div>
</template>

本地购物车 - 头部购物车删除实现

在这里插入图片描述

2.3 删除功能实现

1- 添加删除action函数

  // 删除购物车
  const delCart = async (skuId) => {
      // 思路:
      // 1. 找到要删除项的下标值 - splice
      // 2. 使用数组的过滤方法 - filter
      const idx = cartList.value.findIndex((item) => skuId === item.skuId)
      cartList.value.splice(idx, 1)
  }

2- 组件触发action函数并传递参数

 <i class="iconfont icon-close-new" @click="cartStore.delCart(i.skuId)"></i>

本地购物车 - 头部购物车统计计算

用什么来实现: 计算属性
计算逻辑是什么?

  1. 商品总数计算逻辑: 商品列表中的所有商品count累加之和
  2. 商品总价钱计算逻辑:商品列表中的所有商品的 count * price 累加之和

列表购物车基础数据渲染

本地购物车 - 列表购物车

在这里插入图片描述

  1. 准备模板
<script setup>
const cartList = []
</script>

<template>
  <div class="xtx-cart-page">
    <div class="container m-top-20">
      <div class="cart">
        <table>
          <thead>
            <tr>
              <th width="120">
                <el-checkbox/>
              </th>
              <th width="400">商品信息</th>
              <th width="220">单价</th>
              <th width="180">数量</th>
              <th width="180">小计</th>
              <th width="140">操作</th>
            </tr>
          </thead>
          <!-- 商品列表 -->
          <tbody>
            <tr v-for="i in cartList" :key="i.id">
              <td>
                <el-checkbox />
              </td>
              <td>
                <div class="goods">
                  <RouterLink to="/"><img :src="i.picture" alt="" /></RouterLink>
                  <div>
                    <p class="name ellipsis">
                      {{ i.name }}
                    </p>
                  </div>
                </div>
              </td>
              <td class="tc">
                <p>&yen;{{ i.price }}</p>
              </td>
              <td class="tc">
                <el-input-number v-model="i.count" />
              </td>
              <td class="tc">
                <p class="f16 red">&yen;{{ (i.price * i.count).toFixed(2) }}</p>
              </td>
              <td class="tc">
                <p>
                  <el-popconfirm title="确认删除吗?" confirm-button-text="确认" cancel-button-text="取消" @confirm="delCart(i)">
                    <template #reference>
                      <a href="javascript:;">删除</a>
                    </template>
                  </el-popconfirm>
                </p>
              </td>
            </tr>
            <tr v-if="cartList.length === 0">
              <td colspan="6">
                <div class="cart-none">
                  <el-empty description="购物车列表为空">
                    <el-button type="primary">随便逛逛</el-button>
                  </el-empty>
                </div>
              </td>
            </tr>
          </tbody>

        </table>
      </div>
      <!-- 操作栏 -->
      <div class="action">
        <div class="batch">10 件商品,已选择 2 件,商品合计:
          <span class="red">¥ 200.00 </span>
        </div>
        <div class="total">
          <el-button size="large" type="primary" >下单结算</el-button>
        </div>
      </div>
    </div>
  </div>
</template>

<style scoped lang="scss">
.xtx-cart-page {
  margin-top: 20px;

  .cart {
    background: #fff;
    color: #666;

    table {
      border-spacing: 0;
      border-collapse: collapse;
      line-height: 24px;

      th,
      td {
        padding: 10px;
        border-bottom: 1px solid #f5f5f5;

        &:first-child {
          text-align: left;
          padding-left: 30px;
          color: #999;
        }
      }

      th {
        font-size: 16px;
        font-weight: normal;
        line-height: 50px;
      }
    }
  }

  .cart-none {
    text-align: center;
    padding: 120px 0;
    background: #fff;

    p {
      color: #999;
      padding: 20px 0;
    }
  }

  .tc {
    text-align: center;

    a {
      color: $xtxColor;
    }

    .xtx-numbox {
      margin: 0 auto;
      width: 120px;
    }
  }

  .red {
    color: $priceColor;
  }

  .green {
    color: $xtxColor;
  }

  .f16 {
    font-size: 16px;
  }

  .goods {
    display: flex;
    align-items: center;

    img {
      width: 100px;
      height: 100px;
    }

    >div {
      width: 280px;
      font-size: 16px;
      padding-left: 10px;

      .attr {
        font-size: 14px;
        color: #999;
      }
    }
  }

  .action {
    display: flex;
    background: #fff;
    margin-top: 20px;
    height: 80px;
    align-items: center;
    font-size: 16px;
    justify-content: space-between;
    padding: 0 30px;

    .xtx-checkbox {
      color: #999;
    }

    .batch {
      a {
        margin-left: 20px;
      }
    }

    .red {
      font-size: 18px;
      margin-right: 20px;
      font-weight: bold;
    }
  }

  .tit {
    color: #666;
    font-size: 16px;
    font-weight: normal;
    line-height: 50px;
  }

}
</style>
  1. 绑定路由
import CartList from '@/views/CartList/index.vue'

{
  path: 'cartlist',
  component: CartList
}
  1. 渲染列表
<script setup>
import { useCartStore } from '@/stores/cartStore'
const cartStore = useCartStore()
</script>

<template>
  <div class="xtx-cart-page">
    <div class="container m-top-20">
      <div class="cart">
        <table>
          <thead>
            <tr>
              <th width="120">
                <el-checkbox />
              </th>
              <th width="400">商品信息</th>
              <th width="220">单价</th>
              <th width="180">数量</th>
              <th width="180">小计</th>
              <th width="140">操作</th>
            </tr>
          </thead>
          <!-- 商品列表 -->
          <tbody>
            <tr v-for="i in cartStore.cartList" :key="i.id">
              <td>
                <!-- 单选框 -->
                <el-checkbox/>
              </td>
              <td>
                <div class="goods">
                  <RouterLink to="/"><img :src="i.picture" alt="" /></RouterLink>
                  <div>
                    <p class="name ellipsis">
                      {{ i.name }}
                    </p>
                  </div>
                </div>
              </td>
              <td class="tc">
                <p>&yen;{{ i.price }}</p>
              </td>
              <td class="tc">
                <el-input-number v-model="i.count" />
              </td>
              <td class="tc">
                <p class="f16 red">&yen;{{ (i.price * i.count).toFixed(2) }}</p>
              </td>
              <td class="tc">
                <p>
                  <el-popconfirm title="确认删除吗?" confirm-button-text="确认" cancel-button-text="取消" @confirm="delCart(i)">
                    <template #reference>
                      <a href="javascript:;">删除</a>
                    </template>
                  </el-popconfirm>
                </p>
              </td>
            </tr>
            <tr v-if="cartStore.cartList.length === 0">
              <td colspan="6">
                <div class="cart-none">
                  <el-empty description="购物车列表为空">
                    <el-button type="primary">随便逛逛</el-button>
                  </el-empty>
                </div>
              </td>
            </tr>
          </tbody>

        </table>
      </div>
      <!-- 操作栏 -->
      <div class="action">
        <div class="batch">10 件商品,已选择 2 件,商品合计:
          <span class="red">¥ 200.00 </span>
        </div>
        <div class="total">
          <el-button size="large" type="primary" >下单结算</el-button>
        </div>
      </div>
    </div>
  </div>
</template>

列表购物车 - 单选功能

核心思路: 单选的核心思路就是始终把单选框的状态和Pinia中store对应的状态保持同步
注意事项: v-model双向绑定指令不方便进行命令式的操作(因为后续还需要调用接口), 所以把v-model回退到一般模式,也就是:model-value和@change的配合实现
在这里插入图片描述
基本思想:通过skuId找到要进行单选操作的商品,把控制是否选中的selected字段修改为当前单选框的状态

1- 添加单选action

// 单选功能
const singleCheck = (skuId, selected) => {
  // 通过skuId找到要修改的那一项 然后把它的selected修改为传过来的selected
  const item = cartList.value.find((item) => item.skuId === skuId)
  item.selected = selected
}

2- 触发action函数

<script setup>
// 单选回调
const singleCheck = (i, selected) => {
  console.log(i, selected)
  // store cartList 数组 无法知道要修改谁的选中状态?
  // 除了selected补充一个用来筛选的参数 - skuId
  cartStore.singleCheck(i.skuId, selected)
}
</script>

  
<template>
  <td>
    <!-- 单选框 -->
    <el-checkbox :model-value="i.selected" @change="(selected) => singleCheck(i, selected)" />
  </td>
</template>

列表购物车 - 全选

核心思路:

  1. 操作单选决定全选: 只有当cartList中的所有项都为true时,全选状态才为true
  2. 操作全选决定单选: cartList中的所有项的selected都要跟着一起变
    在这里插入图片描述

1- store中定义action和计算属性

// 全选功能action
const allCheck = (selected) => {
  // 把cartList中的每一项的selected都设置为当前的全选框状态
  cartList.value.forEach(item => item.selected = selected)
}


// 是否全选计算属性
const isAll = computed(() => cartList.value.every((item) => item.selected))

2- 组件中触发aciton和使用计算属性

<script setup>
const allCheck = (selected) => {
  cartStore.allCheck(selected)
}

</script>

  
<template>
  <!-- 全选框 -->
  <el-checkbox :model-value="cartStore.isAll" @change="allCheck" />
</template>

列表购物车 - 统计数据实现

在这里插入图片描述
计算逻辑:

  1. 已选择数量 = cartList中所有selected字段为true项的count之和
  2. 商品合计 = cartList中所有selected字段为true项的count * price之和
// 3. 已选择数量
const selectedCount = computed(() => cartList.value.filter(item => item.selected).reduce((a, c) => a + c.count, 0))
// 4. 已选择商品价钱合计
const selectedPrice = computed(() => cartList.value.filter(item => item.selected).reduce((a, c) => a + c.count * c.price, 0))

接口购物车

整体业务流程回顾
在这里插入图片描述
结论
到目前为止,购物车在非登录状态下的各种操作都已经ok了,包括action的封装,触发,参数传递,剩下的事情就是在action中做登录状态的分支判断,补充登录状态下的接口操作逻辑即可.

接口购物车 - 加入购物车

在这里插入图片描述
1 - 接口封装

// 加入购物车
export const insertCartAPI = ({ skuId, count }) => {
  return request({
    url: '/member/cart',
    method: 'POST',
    data: {
      skuId,
      count
    }
  })
}
// 获取最新的购物车列表
export const findNewCartListAPI = () => {
    return request({
        url: '/member/cart',
    })
}

2- action中适配登录和非登录

import { defineStore } from 'pinia'
import { useUserStore } from './userStore'
import { insertCartAPI } from '@/apis/cart'
export const useCartStore = defineStore('cart', () => {
  const userStore = useUserStore()
  const isLogin = computed(() => userStore.userInfo.token)

  const addCart = async (goods) => {
    const { skuId, count } = goods
    // 登录
    if (isLogin.value) {
      // 登录之后的加入购车逻辑
      await insertCartAPI({ skuId, count })
      updateNewList()
    } else {
      // 未登录
      const item = cartList.value.find((item) => goods.skuId === item.skuId)
      if (item) {
        // 找到了
        item.count++
      } else {
        // 没找到
        cartList.value.push(goods)
      }
    }
  }
}, {
  persist: true,
})

接口购物车 - 删除购物车

在这里插入图片描述
1- 封装接口

// 删除购物车
export const delCartAPI = (ids) => {
  return request({
    url: '/member/cart',
    method: 'DELETE',
    data: {
      ids
    }
  })
}

2- action中适配登录和非登录

 // 删除购物车
  const delCart = async (skuId) => {
    if (isLogin.value) {
      // 调用接口实现接口购物车中的删除功能
      await delCartAPI([skuId])
      updateNewList()
    } else {
      // 思路:
      // 1. 找到要删除项的下标值 - splice
      // 2. 使用数组的过滤方法 - filter
      const idx = cartList.value.findIndex((item) => skuId === item.skuId)
      cartList.value.splice(idx, 1)
    }
  }

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

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

相关文章

力扣每日一题--2050. 并行课程 III(拓补排序例题)

题目描述&#xff1a; 给你一个整数 n &#xff0c;表示有 n 节课&#xff0c;课程编号从 1 到 n 。同时给你一个二维整数数组 relations &#xff0c;其中 r e l a t i o n s [ j ] [ p r e v C o u r s e j , n e x t C o u r s e j ] relations[j] [prevCoursej, nextCou…

【云原生】Docker容器命令监控+Prometheus监控平台

目录 1.常用命令监控 docker ps docker top docker stats 2.weave scope 1.下载 2.安装 3.访问查询即可 3.Prometheus监控平台 1.部署数据收集器cadvisor 2.部署Prometheus 3.部署可视化平台Gragana 4.进入后台控制台 1.常用命令监控 docker ps [rootlocalhost ~…

手把手教你怎么写顺序表

目录 一、顺序表有什么功能&#xff1f; 二、实现顺序表的各个功能 1.前置准备 2.初始化顺序表 3.顺序表扩容 4.打印顺序表 5.增加顺序表成员 5.1尾增 5.2头增 6.删除顺序表中成员的内容 6.1尾删 6.2头删 7.查找成员 8.修改(替换) 9.插入(在目标位置插入成员) 10.定…

Kong Ming Qi hdu7321

Problem - 7321 题目大意&#xff1a;在(n2)*(m2)的棋盘上&#xff0c;中间摆满了n*m个棋子&#xff0c;每个棋子可以向上下左右四个方向移动&#xff0c;对于相邻的三格&#xff0c;移动前后分别为 有 有 无->无 无 有&#xff0c;问最后棋盘上最少能剩下几个棋子 1<n…

论文解读|PF-Net:用于 3D 点云补全的点分形网络

原创 | 文 BFT机器人 01 背景 从激光雷达等设备中获取的点云往往有所缺失&#xff08;反光、遮挡等&#xff09;&#xff0c;这给点云的后续处理带来了一定的困难&#xff0c;也凸显出点云补全作为点云预处理方法的重要性。 点云补全&#xff08;Point Cloud Completion&#x…

Drools用户手册翻译——第四章 Drools规则引擎(七)规则执行模式和线程安全

甩锅声明&#xff1a;本人英语一般&#xff0c;翻译只是为了做个笔记&#xff0c;所以有翻译错误的地方&#xff0c;错就错了&#xff0c;如果你想给我纠正&#xff0c;就给我留言&#xff0c;我会改过来&#xff0c;如果懒得理我&#xff0c;就直接划过即可。 drools的规则执…

HighTec 工程属性介绍2

目录 首先需要创建或导入一个工程&#xff0c;如下图&#xff1a; 有两种方式可以进入工程的属性面板&#xff1a; 选中工程&#xff0c;右键点击 Properies . 选中工程&#xff0c;按键 Alt Enter. 进入工程属性面板之后&#xff0c;左侧是书签标记&#xff0c;右侧是该书…

How to choose WIFI7 IPQ9554- WIFI6 IPQ8072? Who has the better performance?

How to choose WIFI7 IPQ9554- WIFI6 IPQ8072? Who has the better performance? The Wi-Fi standard is Wi-Fi 6, also known as 802.11ax. Wi-Fi 6 brings significant speed, capacity and performance improvements over the previous Wi-Fi 5 (802.11ac) standard. It p…

如何做好项目管理?年薪百万项目大佬一直在用这11张图!

日常工作中&#xff0c;我们会遇到各种大大小小的工作项目&#xff0c;如何能让项目保质保量的完成&#xff0c;就需要项目管理。项目管理是什么&#xff1f;一句话解释&#xff1a;在有限的时间内&#xff0c;在约束的范围中&#xff0c;集合有限资源来完成项目目标。 本周小编…

如何安装mmcv?官网解答

pip install -U openmim mim install mmcv

什么是宏变量和宏替换?

在Java中&#xff0c;宏变量和宏替换通常是与C/C预处理器相关的概念&#xff0c;而不是Java本身的特性。在Java中&#xff0c;我们通常不使用预处理器指令(例如宏定义)来进行代码替换。Java使用的编译器并不支持预处理器指令&#xff0c;因此没有宏替换的概念。 然而&#xff0…

移动硬盘文件或目录损坏且无法读取

早上插上硬盘&#xff0c;拔的时候不太规范&#xff0c;再插进去就显示无法读取了 搜了很多方法&#xff0c;很多让使用什么软件进行恢复 还参考了这个方法&#xff0c;但是我的属性打开跟博主的完全不一样 最后&#xff0c;参考移动硬盘“文件或目录损坏&#xff0c;无法读取…

[NOIP2007 普及组] 守望者的逃离

[NOIP2007 普及组] 守望者的逃离 题目背景 恶魔猎手尤迪安野心勃勃&#xff0c;他背叛了暗夜精灵&#xff0c;率领深藏在海底的娜迦族企图叛变。 题目描述 守望者在与尤迪安的交锋中遭遇了围杀&#xff0c;被困在一个荒芜的大岛上。 为了杀死守望者&#xff0c;尤迪安开始…

把一个列表拆成N个子列表的四种方法

编程的方法往往不止一种&#xff0c;比如怎么把一个Python种的列表拆成N个子列表&#xff0c;我们可以很容易找到N种方法&#xff0c;也许这就是编程的魅力所在。 一、列表表达式法 这种方法最为简洁&#xff0c;不过可读性差一些 这个方法中&#xff0c;即使原始列表的数量无…

途乐证券:美联储第11次加息 年内降息预期下降

7月26日&#xff0c;美国联邦储藏委员会主席鲍威尔在华盛顿到会记者会。新华社发 当地时刻7月26日&#xff0c;美国联邦储藏委员会一如预期加息25个基点。商场对美联储未来是否会持续加息尚未彻底构成共识&#xff0c;但对年内美联储将敞开降息周期的预期下降。 抑通胀 美联储…

24考研数据结构-队列2

目录 数据结构之队列&#xff1a;链式存储结构与循环队列链式存储结构链式队列的结构链式队列的操作 循环队列循环队列的结构循环队列的操作 链式队列与循环队列的比较结论3.2.3 队列的链式存储结构3.2.3.1定义3.2.3.2链式队列的基本操作——带头结点3.2.3.3 不带头结点的相关操…

PLC自学是否可行?

plc编程的关键是模拟原操作流程&#xff0c;通过运行程序完成控制过程。所以核心内容就是程序对流程的描述。因此&#xff0c;掌握PLC编程语言和基本功能实现是很有必要的。 PLC语言分为梯形图、语句和功能图。常用梯形图&#xff0c;适合基本逻辑描述&#xff0c;语句表适合数…

计算机网络(1) --- 网络介绍

目录 1.介绍协议 基础知识 协议 协议分层 OSI七层模型 2.TCP/IP五层模型 3.网络传输的基本流程 1.基本知识 协议报头 2.局域网通信的基本流程 3.网络传输流程 局域网分类 跨路由器传输 数据包封装和分用 4.网络中的地址管理 1.IP地址 2.MAC地址 3.区别 1.介绍…

商品分类子类新建,手机云进销存,扫码入库出库盘点开单打印

商品分类子类新建&#xff0c;手机扫码开单打印进销存&#xff0c;商贸批发生产企业仓库条码管理软件系统&#xff0c;超市便利店五金茶叶烟酒鞋帽门店零售手机收银管理软件APP_哔哩哔哩_bilibili商品分类子类新建的操作步骤。, 视频播放量 1、弹幕量 0、点赞数 0、投硬币枚数 …

Java基础---final 关键字

目录 定义&#xff1a; 用途&#xff1a; 使用注意事项&#xff1a; final 变量 final 方法 final 类 小结 定义&#xff1a; Java中&#xff0c;final 表示最终&#xff0c;也可以称为完结器&#xff0c;表示对象是最终形态的&#xff0c;不可改变的意思 用途&#xff…