黑马程序员前端 Vue3 小兔鲜电商项目——(四)Home 页面布局

news2024/12/23 3:14:01

文章目录

    • Home 页面组件结构
      • 组件结构拆分
      • Home 模块中引入组件
    • 分类实现
      • 模板代码
      • 渲染数据
    • banner 轮播图实现
      • 模板代码
      • 封装接口
      • 渲染数据
    • 面板组件封装
      • 创建公共组件复用
      • 抽取主题和副主题
    • 新鲜好物实现
      • 模版代码
      • 封装接口
      • 渲染数据
    • 人气推荐实现
      • 模板代码
      • 封装接口
      • 渲染数据
    • 懒加载指令实现
      • 封装全局指令
      • 注册全局指令
      • 图片懒加载
    • Product 产品列表实现
      • 模板代码
      • 封装接口
      • 渲染数据
      • 图片懒加载
    • GoodsItem组件封装
      • 封装组件
      • 使用组件

Home 页面组件结构

组件结构拆分

image.png

按照结构新增五个组件:左侧分类、Banner、新鲜好物、人气推荐、产品列表。在 src/views/Home/components 路径下依次创建 HomeCategory.vueHomeBanner.vueHomeNew.vueHomeHot.vueHomeProduct.vue

image-20230621110557287

Home 模块中引入组件

在 Home 的 index.vue 模块入口组件中引入各个组件并渲染:

<script setup>
import HomeCategory from './components/HomeCategory.vue'
import HomeBanner from './components/HomeBanner.vue'
import HomeNew from './components/HomeNew.vue'
import HomeHot from './components/HomeHot.vue'
import homeProduct from './components/HomeProduct.vue'
</script>

<template>
  <div class="container">
    <HomeCategory />
    <HomeBanner />
  </div>
  <HomeNew />
  <HomeHot />
  <homeProduct />
</template>

分类实现

模板代码

HomeCategory.vue 文件中添加以下代码:

<script setup>

</script>

<template>
  <div class="home-category">
    <ul class="menu">
      <li v-for="item in 9" :key="item">
        <RouterLink to="/">居家</RouterLink>
        <RouterLink v-for="i in 2" :key="i" to="/">南北干货</RouterLink>
        <!-- 弹层layer位置 -->
        <div class="layer">
          <h4>分类推荐 <small>根据您的购买或浏览记录推荐</small></h4>
          <ul>
            <li v-for="i in 5" :key="i">
              <RouterLink to="/">
                <img alt="" />
                <div class="info">
                  <p class="name ellipsis-2">
                    男士外套
                  </p>
                  <p class="desc ellipsis">男士外套,冬季必选</p>
                  <p class="price"><i>¥</i>200.00</p>
                </div>
              </RouterLink>
            </li>
          </ul>
        </div>
      </li>
    </ul>
  </div>
</template>


<style scoped lang='scss'>
.home-category {
  width: 250px;
  height: 500px;
  background: rgba(0, 0, 0, 0.8);
  position: relative;
  z-index: 99;

  .menu {
    li {
      padding-left: 40px;
      height: 55px;
      line-height: 55px;

      &:hover {
        background: $xtxColor;
      }

      a {
        margin-right: 4px;
        color: #fff;

        &:first-child {
          font-size: 16px;
        }
      }

      .layer {
        width: 990px;
        height: 500px;
        background: rgba(255, 255, 255, 0.8);
        position: absolute;
        left: 250px;
        top: 0;
        display: none;
        padding: 0 15px;

        h4 {
          font-size: 20px;
          font-weight: normal;
          line-height: 80px;

          small {
            font-size: 16px;
            color: #666;
          }
        }

        ul {
          display: flex;
          flex-wrap: wrap;

          li {
            width: 310px;
            height: 120px;
            margin-right: 15px;
            margin-bottom: 15px;
            border: 1px solid #eee;
            border-radius: 4px;
            background: #fff;

            &:nth-child(3n) {
              margin-right: 0;
            }

            a {
              display: flex;
              width: 100%;
              height: 100%;
              align-items: center;
              padding: 10px;

              &:hover {
                background: #e3f9f4;
              }

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

              .info {
                padding-left: 10px;
                line-height: 24px;
                overflow: hidden;

                .name {
                  font-size: 16px;
                  color: #666;
                }

                .desc {
                  color: #999;
                }

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

                  i {
                    font-size: 16px;
                  }
                }
              }
            }
          }
        }
      }

      // 关键样式  hover状态下的layer盒子变成block
      &:hover {
        .layer {
          display: block;
        }
      }
    }
  }
}
</style>

渲染数据

后端接口返回的 JSON 数据格式如下:

image-20230621114021325

获取数据并进行遍历输出:

<script setup>
  
import { useCategoryStore } from '@/stores/category'
const categoryStore = useCategoryStore()

</script>

<template>
  <div class="home-category">
    <ul class="menu">
      <li v-for="item in categoryStore.categoryList" :key="item.id">
        <RouterLink to="/">{{ item.name }}</RouterLink>
        <RouterLink v-for="i in item.children.slice(0, 2)" :key="i" to="/">{{ i.name }}</RouterLink>
        <!-- 弹层layer位置 -->
        <div class="layer">
          <h4>分类推荐 <small>根据您的购买或浏览记录推荐</small></h4>
          <ul>
            <li v-for="i in item.goods" :key="i.id">
              <RouterLink to="/">
                <img :src="i.picture" alt="" />
                <div class="info">
                  <p class="name ellipsis-2">
                    {{ i.name }}
                  </p>
                  <p class="desc ellipsis">{{ i.desc }}</p>
                  <p class="price"><i>¥</i>{{ i.price }}</p>
                </div>
              </RouterLink>
            </li>
          </ul>
        </div>
      </li>
    </ul>
  </div>
</template>

banner 轮播图实现

模板代码

<script setup>

</script>

<template>
  <div class="home-banner">
    <!--使用 ElementPlus 的轮播图组件-->
    <el-carousel height="500px">
      <el-carousel-item v-for="item in 4" :key="item">
        <img src="http://yjy-xiaotuxian-dev.oss-cn-beijing.aliyuncs.com/picture/2021-04-15/6d202d8e-bb47-4f92-9523-f32ab65754f4.jpg" alt="">
      </el-carousel-item>
    </el-carousel>
  </div>
</template>



<style scoped lang='scss'>
.home-banner {
  width: 1240px;
  height: 500px;
  position: absolute;
  left: 0;
  top: 0;
  z-index: 98;

  img {
    width: 100%;
    height: 500px;
  }
}
</style>

封装接口

创建 src/apis/home.js 文件,编写方法用于获取 Banner 图的 API:

/**
 * @description: 获取banner图
 */
import http from '@/utils/http'
export function getBannerAPI() {
    return http({
        url: 'home/banner'
    })
}

渲染数据

获取数据并进行遍历输出:

<script setup>
import { getBannerAPI } from '@/apis/home'
import { onMounted, ref } from 'vue'

const bannerList = ref([])

const getBanner = async () => {
  const res = await getBannerAPI()
  console.log(res)
  bannerList.value = res.result
}

onMounted(() => getBanner())

</script>

<template>
  <div class="home-banner">
    <el-carousel height="500px">
      <el-carousel-item v-for="item in bannerList" :key="item.id">
        <img :src="item.imgUrl" alt="">
      </el-carousel-item>
    </el-carousel>
  </div>
</template>

面板组件封装

在页面中显示的【新鲜好物】和【人气推荐】两个模块是一样的分布,代码也相同,只是显示的数据不同,因此可以抽取公共部分进行复用。

核心思路:把可复用的结构只写一次,把可能发生变化的部分抽象成组件参数(popS/插槽)。抽象可变的部分:

  • 主标题和副标题是纯文本,可以抽象成 props 传入
  • 主体内容是复杂的模版,抽象成插槽传入

image-20230621144521559

创建公共组件复用

在 src/views/Home/components 路径下创建 HomePanel.vue 文件,代码如下:

<script setup>

</script>


<template>
  <div class="home-panel">
    <div class="container">
      <div class="head">
         <!-- 主标题和副标题 -->
        <h3>
          新鲜好物<small>新鲜出炉 品质靠谱</small>
        </h3>
      </div>
      <!-- 主体内容区域 -->
      <div> 主体内容 </div>
    </div>
  </div>
</template>

<style scoped lang='scss'>
.home-panel {
  background-color: #fff;

  .head {
    padding: 40px 0;
    display: flex;
    align-items: flex-end;

    h3 {
      flex: 1;
      font-size: 32px;
      font-weight: normal;
      margin-left: 6px;
      height: 35px;
      line-height: 35px;

      small {
        font-size: 16px;
        color: #999;
        margin-left: 20px;
      }
    }
  }
}
</style>

抽取主题和副主题

因为主标题和副标题是纯文本,可以抽象成 props 传入,代码如下:

<script setup>
//定义 Props,主标题和副标题
defineProps({
    title: {
        type: String
    },
    subTitle: {
        type: String
    }
})
</script>

在主代码中使用参数:

<div class="container">
  <div class="head">
    <!-- 主标题和副标题 -->
    <h3>
      {{title}}<small>{{ subTitle }}</small>
    </h3>
  </div>
  <!-- 主体内容区域 插槽-->
  <slot/>
</div>

新鲜好物实现

image-20230621142447186

模版代码

在 src/views/Home/components 路径下有之前创建好的 HomeNew.vue 文件,添加以下代码:

<script setup>

</script>

<template>
  <div></div>
  <!-- 下面是插槽主体内容模版
  <ul class="goods-list">
    <li v-for="item in newList" :key="item.id">
      <RouterLink to="/">
        <img :src="item.picture" alt="" />
        <p class="name">{{ item.name }}</p>
        <p class="price">&yen;{{ item.price }}</p>
      </RouterLink>
    </li>
  </ul>
  -->
</template>


<style scoped lang='scss'>
.goods-list {
  display: flex;
  justify-content: space-between;
  height: 406px;

  li {
    width: 306px;
    height: 406px;

    background: #f0f9f4;
    transition: all .5s;

    &:hover {
      transform: translate3d(0, -3px, 0);
      box-shadow: 0 3px 8px rgb(0 0 0 / 20%);
    }

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

    p {
      font-size: 22px;
      padding-top: 12px;
      text-align: center;
      text-overflow: ellipsis;
      overflow: hidden;
      white-space: nowrap;
    }

    .price {
      color: $priceColor;
    }
  }
}
</style>

封装接口

在 src/apis/home.js 文件中,编写方法用于获取 【新鲜好物】 的 API:

/**
 * @description: 获取新鲜好物
 * @param {*}
 * @return {*}
 */
export function findNewAPI(){
    return http({
        url: '/home/new'
    })
}

渲染数据

获取数据并进行遍历输出:

<script setup>
import HomePanel from './HomePanel.vue'
import { findNewAPI } from '@/apis/home'
import { ref, onMounted } from 'vue'

const newList = ref([])
const getNewList = async () => {
    const res = await findNewAPI()
    console.log(res)
    newList.value = res.result
}

onMounted(() => {
    getNewList()
})
</script>

<template>
    <HomePanel title="新鲜好物" sub-title="新鲜出炉 品质好物">
        <!-- 下面是插槽主体内容模版 -->
        <ul class="goods-list">
            <li v-for="item in newList" :key="item.id">
                <RouterLink to="/">
                    <img :src="item.picture" alt="" />
                    <p class="name">{{ item.name }}</p>
                    <p class="price">&yen;{{ item.price }}</p>
                </RouterLink>
            </li>
        </ul>
    </HomePanel>
</template>

人气推荐实现

image-20230621144221266

模板代码

在 src/views/Home/components 路径下有之前创建好的 HomeHot.vue 文件,添加以下代码:

<script setup>

</script>

<template>
  <div></div>
  <!-- 下面是插槽主体内容模版
  <ul class="goods-list">
    <li v-for="item in newList" :key="item.id">
      <RouterLink to="/">
        <img :src="item.picture" :alt="item.alt" />
        <p class="name">{{ item.title }}</p>
      </RouterLink>
    </li>
  </ul>
  -->
</template>

<style scoped lang='scss'>
.goods-list {
  display: flex;
  justify-content: space-between;
  height: 406px;

  li {
    width: 306px;
    height: 406px;

    background: #f0f9f4;
    transition: all .5s;

    &:hover {
      transform: translate3d(0, -3px, 0);
      box-shadow: 0 3px 8px rgb(0 0 0 / 20%);
    }

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

    p {
      font-size: 22px;
      padding-top: 12px;
      text-align: center;
      text-overflow: ellipsis;
      overflow: hidden;
      white-space: nowrap;
    }

    .price {
      color: $priceColor;
    }
  }
}
</style>

封装接口

在 src/apis/home.js 文件中,编写方法用于获取 【人气推荐】 的 API:

/**
 * @description: 获取人气推荐
 * @param {*}
 * @return {*}
 */
export function findHotAPI(){
    return http({
        url:'/home/hot'
    })
}

渲染数据

获取数据并进行遍历输出:

<script setup>
import HomePanel from './HomePanel.vue';
import { ref, onMounted } from 'vue'
import { findHotAPI } from '@/apis/home'

const hotList = ref([])
const getHotList = async() => {
    const res = await findHotAPI()
    console.log(res)
    hotList.value = res.result
}

onMounted(() => {
    getHotList()
})
</script>

<template>
    <HomePanel title="人气推荐" sub-title="人气爆款 不容错过">
        <!-- 下面是插槽主体内容模版 -->
        <ul class="goods-list">
            <li v-for="item in hotList" :key="item.id">
                <RouterLink to="/">
                    <img :src="item.picture" :alt="item.alt" />
                    <p class="name">{{ item.title }}</p>
                </RouterLink>
            </li>
        </ul>
    </HomePanel>
</template>

懒加载指令实现

main.js 入口文件通常只做一些初始化的事情,不应该包含太多的逻辑代码,可以通过插件的方法把懒加载指令封装为插件,main.js 入口文件只需要负责注册插件即可。

封装全局指令

在 src/directives/ 目录下创建 index.js 文件,在其中自定义指令 v-img-lazy,实现当图片进入视口区域时,才对其进行加载:

// 定义懒加载插件
import { useIntersectionObserver } from '@vueuse/core'

export const lazyPlugin = {
  install (app) {
    // 懒加载指令逻辑
    app.directive('img-lazy', {
      mounted (el, binding) {
        // el: 指令绑定的那个元素 img
        // binding: binding.value  指令等于号后面绑定的表达式的值  图片url
        console.log(el, binding.value)
        const { stop } = useIntersectionObserver(
          el,
          ([{ isIntersecting }]) => {
            console.log(isIntersecting)
            if (isIntersecting) {
              // 进入视口区域
              el.src = binding.value
              stop()
            }
          },
        )
      }
    })
  }
}

注册全局指令

在 main.js 中自定义指令注册为全局指令:

// 全局指令注册
import { directivePlugin } from '@/directives'
app.use(directivePlugin)

图片懒加载

在 HomeHot.vue 和 HomeNew.vue 文件的代码上使用自定义的懒加载指令进行修改。修改之后如下:

<img v-img-lazy="item.picture" alt="" />

这样当图片进入视口区域后,才会将图片的地址赋给 img 的 src 属性。

Product 产品列表实现

因为商品列表页面也是有很多模块代码可以复用,只是数据不同,因此我们依然可以继续使用封装好的面板组件。

image-20230621154128794

模板代码

在之前创建好的 HomeProduct.vue 文件中添加如下代码:

<script setup>
import HomePanel from './HomePanel.vue'

</script>

<template>
  <div class="home-product">
    <!-- <HomePanel :title="cate.name" v-for="cate in goodsProduct" :key="cate.id">
      <div class="box">
        <RouterLink class="cover" to="/">
          <img :src="cate.picture" />
          <strong class="label">
            <span>{{ cate.name }}馆</span>
            <span>{{ cate.saleInfo }}</span>
          </strong>
        </RouterLink>
        <ul class="goods-list">
          <li v-for="good in cate.goods" :key="good.id">
            <RouterLink to="/" class="goods-item">
              <img :src="good.picture" alt="" />
              <p class="name ellipsis">{{ good.name }}</p>
              <p class="desc ellipsis">{{ good.desc }}</p>
              <p class="price">&yen;{{ good.price }}</p>
            </RouterLink>
          </li>
        </ul>
      </div>
    </HomePanel> -->
  </div>
</template>

<style scoped lang='scss'>
.home-product {
  background: #fff;
  margin-top: 20px;
  .sub {
    margin-bottom: 2px;

    a {
      padding: 2px 12px;
      font-size: 16px;
      border-radius: 4px;

      &:hover {
        background: $xtxColor;
        color: #fff;
      }

      &:last-child {
        margin-right: 80px;
      }
    }
  }

  .box {
    display: flex;

    .cover {
      width: 240px;
      height: 610px;
      margin-right: 10px;
      position: relative;

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

      .label {
        width: 188px;
        height: 66px;
        display: flex;
        font-size: 18px;
        color: #fff;
        line-height: 66px;
        font-weight: normal;
        position: absolute;
        left: 0;
        top: 50%;
        transform: translate3d(0, -50%, 0);

        span {
          text-align: center;

          &:first-child {
            width: 76px;
            background: rgba(0, 0, 0, 0.9);
          }

          &:last-child {
            flex: 1;
            background: rgba(0, 0, 0, 0.7);
          }
        }
      }
    }

    .goods-list {
      width: 990px;
      display: flex;
      flex-wrap: wrap;

      li {
        width: 240px;
        height: 300px;
        margin-right: 10px;
        margin-bottom: 10px;

        &:nth-last-child(-n + 4) {
          margin-bottom: 0;
        }

        &:nth-child(4n) {
          margin-right: 0;
        }
      }
    }

    .goods-item {
      display: block;
      width: 220px;
      padding: 20px 30px;
      text-align: center;
      transition: all .5s;

      &:hover {
        transform: translate3d(0, -3px, 0);
        box-shadow: 0 3px 8px rgb(0 0 0 / 20%);
      }

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

      p {
        padding-top: 10px;
      }

      .name {
        font-size: 16px;
      }

      .desc {
        color: #999;
        height: 29px;
      }

      .price {
        color: $priceColor;
        font-size: 20px;
      }
    }
  }
}
</style>

封装接口

在 src/apis/home.js 文件中,封装获取商品列表信息的接口:

/**
 * @description: 获取所有商品模块
 * @param {*}
 * @return {*}
 */
export function getGoodsAPI() {
    return http({
        url: '/home/goods'
    })
}

渲染数据

获取数据并进行遍历输出:

<script setup>
import HomePanel from './HomePanel.vue'
import { getGoodsAPI } from '@/apis/home';
import { ref,onMounted } from 'vue';

const goodsProduct = ref([])
const getGoodList = async()=>{
    const res = await getGoodsAPI()
    goodsProduct.value = res.result
}

onMounted(()=>{
    getGoodList()
})

</script>

图片懒加载

使用 v-img-lazy 懒加载指令替换 img 标签的原始 src:

<!-- 指令替换 -->
<img v-img-lazy="cate.picture" />

<!-- 指令替换 -->
<img v-img-lazy="goods.picture" alt="" />

GoodsItem组件封装

image-20230621154957748

在小兔鲜项目的很多个业务模块中都需要用到同样的商品展示模块,没必要重复定义,封装起来,方便复用。

原代码:

<ul class="goods-list">
  <li v-for="good in cate.goods" :key="good.id">
    <RouterLink to="/" class="goods-item">
      <img v-img-lazy="good.picture" alt="" />
      <p class="name ellipsis">{{ good.name }}</p>
      <p class="desc ellipsis">{{ good.desc }}</p>
      <p class="price">&yen;{{ good.price }}</p>
    </RouterLink>
  </li>
</ul>

修改之后的代码:

<ul class="goods-list">
  <li v-for="goods in cate.goods" :key="item.id">
    <GoodsItem :good="good" />
  </li>
</ul>

封装组件

创建 src\views\Home\components\GoodsItem.vue 文件,抽取可复用的代码,并将商品信息抽象成 props 参数传入:

<script setup>
defineProps({
    good:{
        type:Object,
        default:()=>({})
    }
})
</script>
<template>
    <RouterLink to="/" class="goods-item">
        <img v-img-lazy="good.picture" alt="" />
        <p class="name ellipsis">{{ good.name }}</p>
        <p class="desc ellipsis">{{ good.desc }}</p>
        <p class="price">&yen;{{ good.price }}</p>
    </RouterLink>
</template>
<style lang="scss">
.goods-item {
    display: block;
    width: 220px;
    padding: 20px 30px;
    text-align: center;
    transition: all .5s;

    &:hover {
        transform: translate3d(0, -3px, 0);
        box-shadow: 0 3px 8px rgb(0 0 0 / 20%);
    }

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

    p {
        padding-top: 10px;
    }

    .name {
        font-size: 16px;
    }

    .desc {
        color: #999;
        height: 29px;
    }

    .price {
        color: $priceColor;
        font-size: 20px;
    }
}
</style>

使用组件

修改 src\views\Home\components\HomeProduct.vue 中商品信息的代码:

<ul class="goods-list">
  <li v-for="good in cate.goods" :key="good.id">
    <GoodsItem :good="good" />
  </li>
</ul>

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

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

相关文章

Java实现加密(五)Base64编码

目录 一、Base64是怎么诞生的二、Base64定义三、Base64原理1.ASCII码转Base64&#xff08;字节数 % 3 0&#xff09;2.ASCII码转Base64&#xff08;字节数 % 3 2&#xff09;3.ASCII码转Base64&#xff08;字节数 % 3 1&#xff09;4.UTF-8转Base64 四、Java实现Base64编解码…

Android Binder通信原理(一):简介

源码基于&#xff1a;Android R 0. 前言 在Linux 系统中现有的进程间通信&#xff08;IPC&#xff09;方式&#xff1a; 管道(PIPE)&#xff1a;在创建时分配一个page大小的内存&#xff0c;缓存区大小比较有限&#xff1b;命名管道(FIFO)&#xff1a;考虑 PIPE_BUF 和原子操…

华为流程体系:IPD流程之敏捷开发(限制版)

目录 前言 敏捷 逐步采用敏捷原则 专栏列表 CSDN学院课程地址 前言 今天继续来谈谈 IPD 体系中敏捷开发所涉及的一些相关内容。 无论是硬件产品的开发过程&#xff0c;还是在应用或者是学习 IPD 的过程中。 瀑布式流程几乎都是标配。 这其实跟硬件产品或者是传统 IPD …

ROS:配置VScode

目录 前言一、下载二、vscode 安装三、vscode 集成 ROS 插件四、vscode 使用4.1 创建 ROS 工作空间4.2启动 vscode4.3vscode 中编译 ros4.4创建 ROS 功能包4.5C 实现4.6python 实现4.7配置 CMakeLists.txt4.8编译4.9执行 前言 VSCode 全称 Visual Studio Code&#xff0c;是微…

关于华为云服务器安装宝塔面板后,点击终端无响应解决方案

问题再现: 下面是我沟通宝塔客服后&#xff0c;给的解决方案。 我在百般无奈的情况下、卸载了宝塔后&#xff0c;最终躺平&#xff0c;选择了问宝塔官方客服 1、从华为提供的远程登录方式选一种 二、输入服务器密码通过ssh远程登录 服务器 二、执行宝塔官方提供的 命令执…

电影《闪电侠》观后感

上周看了电影《闪电侠》&#xff0c;主要是闪电侠这个人成长过程&#xff0c;与以往英雄题材类还是有些不太一样的&#xff0c;像之前蜘蛛侠和钢铁侠&#xff0c;都是讲主人公怎么成为那个英雄的&#xff0c;而本部电影是一个类似倒叙&#xff0c;他自己本身就已经是闪电侠了&a…

zookeeper安装使用及工作原理分析

1. Zookeeper概念简介 Zookeeper是一个分布式协调服务&#xff1b;就是为用户的分布式应用程序提供协调服务&#xff0c;它是集群的管理者&#xff0c;监视着集群中各个节点的状态&#xff0c;根据节点提交的反馈进行下一步合理操作。 具体介绍&#xff1a; A、zookeeper是为…

Electron详解(二):基本使用与项目打包

一、electron的基本使用 创建一个 electron 项目 在使用Electron进行开发之前&#xff0c;您需要安装 Node.js&#xff0c;最低工作版本为 14.x&#xff0c;低于 14 的版本在后面的打包过程中可能会报错。 &#xff08;注意&#xff0c;因为 Electron 将 Node.js 嵌入到其二…

嵌入式系统与大数据:选择哪个方向更好?

嵌入式系统和大数据是两个不同的领域&#xff0c;各有其独特的优势和发展前景。选择嵌入式系统还是大数据方向&#xff0c;应根据个人兴趣、技能背景以及市场需求进行综合评估。 嵌入式系统方向的优势&#xff1a;我资料有嵌入式、plc、单片机资料需要得可以私我 物联网&#…

在 ZBrush 中雕刻漫画风格的蝙蝠侠半身像

今天瑞云渲染小编给大家带来Rishikesh Nandlaskar分享蝙蝠侠造型背后的制作过程&#xff0c;解释了 ZBrush 和 Substance 3D Painter 中的工作流程&#xff0c;并分享了 Arnold 中的渲染设置。 介绍 我叫 Rishikesh Nandlaskar&#xff0c;是伦敦 Framestore VFX 工作室的高级…

使用数据泵+ogg同步oracle数据

本次迁移背景&#xff1a; 机房要搬迁&#xff0c;新搭建了一套oracle数据库&#xff0c;计划不停机迁移&#xff0c;将源端旧库的数据迁移到目标端新库里。 原本想用RMAN方式迁移&#xff0c;但是由于旧库是AIX系统&#xff0c;新库是linux系统&#xff0c;用RMAN迁移会有问…

SpringBoot2.3集成Spring Security(二) JWT认证

项目背景 紧接上文&#xff0c;我们已经完成了 SpringBoot中集成Spring Security&#xff0c;并且用户名帐号和密码都是从数据库中获取。但是这种方式还是不能满足现在的开发需求。 使用JWT的好处&#xff1a; 无状态认证&#xff1a;JWT本身包含了认证信息和声明&#xff0…

仓库管理软件哪个好?一键解决仓库出入库、管理库存,选这些软件

仓库管理软件哪个好? 仓库管理企业进销存的重要组成部分之一&#xff0c;现代物流中不可缺少的重要环节&#xff0c;对于企业管理的重要性不言而喻。 到底该如何选择仓库管理软件&#xff1f;让进销存老研究员帮你搞定 选择一个好的软件&#xff0c;首先明白他的作用。 向你…

【操作系统】生产者消费者问题实现

目录 实验原理&#xff1a; 实验内容&#xff1a; 实验器材&#xff08;设备、元器件&#xff09;&#xff1a; 实验步骤&#xff1a; 实验数据及结果分析&#xff1a; 实验原理&#xff1a; 考虑n个缓冲区的缓冲池作为一个共享资源&#xff0c;当生产者进程从数据源—文…

高级数据结构——二叉搜索树

目录 1. 二叉搜索树的概念 2. 二叉搜索树的实现 结点类 二叉搜索树的类 2.1 默认成员函数 2.1.1 构造函数 2.1.2 拷贝构造函数 2.1.3 赋值运算符重载函数 2.1.4 析构函数 2.2 中序遍历 2.3 insert插入函数 2.3.1 非递归实现 2.3.2 递归实现 2.4 erase删除函数 2…

App Inventor 2 语音交互机器人Robot,使用讯飞语音识别引擎

应用介绍 App Inventor 2 语音识别及交互App。识别语言指令并控制机器人运动&#xff0c;主要用到语音识别器及文本朗读器组件&#xff0c;语音识别相关开发最佳入门。代码逻辑简单&#xff0c;App交互性及趣味性非常强~ 视频预览 语音Robot教程&#xff08;难度系数&#xf…

中科院、中科大团队精确测量子引力对量子自旋的影响

光子盒研究院 由中国科学院盛东教授、陆征天教授和中国科学技术大学的合作研究小组利用高精度氙气同位素磁力仪研究了中子自旋和引力之间的耦合效应。5月15日&#xff0c;这项题为Search for Spin-Dependent Gravitational Interactions at Earth Range的研究发表在《物理评论快…

three.js常用几何体介绍以及自定义几何体

一、自定义三角形几何体 核心代码&#xff1a; // 添加物体 // 创建几何体 for (let i 0; i < 50; i) {// 每一个三角形&#xff0c;需要3个顶点&#xff0c;每个顶点需要3个值const geometry new THREE.BufferGeometry();const positionArray new Float32Array(9);for …

Java创建多线程的五种写法

目录 一.lambda表达式(强烈推荐,最简单) 基础格式 举例 运行结果 二.继承 Thread, 重写 run 基础格式 举例 运行结果 三.实现 Runnable, 重写 run 基础格式 举例 运行结果 四.使用匿名内部类,继承 Thread, 重写 run 基础格式 举例 运行结果 五.使用匿名内部类,实…