【前端】Vue项目:旅游App-(17)home:页面滚动显示搜索栏、节流、时间同步

news2024/11/15 16:41:17

文章目录

    • 目标
    • 过程与代码
      • 页面滚动到目标位置显示搜索框
      • 优化:节流
      • 搜索栏
      • 显示时间同步
    • 效果
    • 总代码
      • 修改或添加的文件
      • search-bar.vue
      • useScroll.js
      • store的main.js
      • formatDate.js
      • home.vue
    • 参考

本项目博客总结:【前端】Vue项目:旅游App-博客总结

目标

窗口滚动到固定位置时显示搜索栏:

在这里插入图片描述
且搜索栏左侧显示的时间与入住离开的时间相匹配。

在这里插入图片描述

过程与代码

页面滚动到目标位置显示搜索框

我们可以用v-if控制搜索框的显示与否,用上篇写的useScroll得知页面的滚动情况。

为了useScroll的扩展性,我们可以把scrollHeightscrollTopclientHeightreturn出来:

// 关于滚动到底部的代码逻辑
import { onMounted, onUnmounted } from "@vue/runtime-core";
import { ref } from 'vue'

export default function useScroll() {
    // 初始默认为没有到底
    const isReachBottom = ref(false)
    const scrollTop = ref(0)
    const clientHeight = ref(0)
    const scrollHeight = ref(0)

    const scrollBottomListener = () => {
        // 当前位置到顶部的距离
        scrollTop.value = document.documentElement.scrollTop
        // 屏幕的长度
        clientHeight.value = document.documentElement.clientHeight
        // 页面总体长度
        scrollHeight.value = document.documentElement.scrollHeight

        // 滚动到底部:提前一点刷新
        if (scrollHeight.value <= scrollTop.value + clientHeight.value + 1) {
            console.log('滚动到底部')
            isReachBottom.value = true
        }
    }

    onMounted(() => {
        window.addEventListener('scroll', scrollBottomListener)
    })

    onUnmounted(() => {
        window.removeEventListener('scroll', scrollBottomListener)
    })

    return { isReachBottom, scrollHeight, clientHeight, scrollTop }
}

在需要知道当前页面滚动到哪里的时候把scrollTop 解构出来即可。

需求:在页面滚动到开始搜索按钮时显示搜索栏(严谨地说,是此按钮刚好被上滑的页面遮盖住时显示)。因此我们可以:

在这里插入图片描述

scrollBottomListener是窗口滚动时会启动的事件,我们这样就可以实时监听到scrollTop 的变化。

浏览器控制台输出“开始搜索按钮刚好被遮盖一点”时页面距离窗口顶部的距离为:484

在这里插入图片描述
watch监听scrollTop ,当它>=484时令搜索框显示。

html:

<div class="search-bar" v-if="isShowSearchBar">
   我是搜索框
</div>

js:

// 是否显示搜索栏的控制
const isShowSearchBar = ref(false)
const { scrollTop } = useScroll()
watch(scrollTop, (newValue) => {
    if (scrollTop.value >= 484) {
        isShowSearchBar.value = true
    }
    else {
        isShowSearchBar.value = false
    }
})

用计算属性优化:

定义的可响应数据依赖于另一个可响应数据,可以使用计算属性

const isShowSearchBar = computed(() => {
    return scrollTop.value >= 484
})

效果:

有了一点遮挡时,显示:

在这里插入图片描述
反之没有:

在这里插入图片描述

优化:节流

相关资料:
面试官:什么是防抖和节流?有什么区别?如何实现? | web前端面试 - 面试官系列 (vue3js.cn)
Underscore.js 简介 | Underscore.js 中文文档 | Underscore.js 中文网 (underscorejs.cn)

我们观察useScroll函数,每当窗口滚动时,都会调用回调函数scrollBottomListener
它调用函数十分频繁,会降低前端的性能。因此,我们要对它进行优化。

优化有两种主要方式:防抖和节流。

定义:

节流: n 秒内只运行一次,若在 n 秒内重复触发,只有一次生效
防抖: n 秒后在执行该事件,若在 n 秒内被重复触发,则重新计时

应用场景:

防抖在连续的事件,只需触发一次回调的场景有:

搜索框搜索输入。只需用户最后一次输入完,再发送请求
手机号、邮箱验证输入检测
窗口大小resize。只需窗口调整完成后,计算窗口大小。防止重复渲染。

节流在间隔一段时间执行一次回调的场景有:
滚动加载,加载更多或滚到底部
监听搜索框,搜索联想功能

这里很明显要使用节流

我们可以使用已经封装好的库来调用节流的函数。

npm i underscore

在这里插入图片描述
第一个参数是要进行节流的函数,这里是scrollBottomListener
第二个参数是再次执行函数要间隔的时间。

时间设为100ms刚好,若设置为1000ms会明显感觉到延迟。注意,wait不要设置太大。

const scrollBottomListener = throttle(() => {
        // 当前位置到顶部的距离
        scrollTop.value = document.documentElement.scrollTop
        // 屏幕的长度
        clientHeight.value = document.documentElement.clientHeight
        // 页面总体长度
        scrollHeight.value = document.documentElement.scrollHeight

        // 滚动到底部:提前一点刷新
        if (scrollHeight.value <= scrollTop.value + clientHeight.value + 1) {
            console.log('滚动到底部')
            isReachBottom.value = true
        }

        // console.log(scrollTop.value)
    }, 100)

搜索栏

想要在固定位置有个搜索栏,要position:fixed

html:

<div class="search-bar" v-if="isShowSearchBar">
    <searchBar/>
</div>

css:

.search-bar{
   // 定位在屏幕某位置,不随页面滚动而改变
   position: fixed;
   top: 0;
   left: 0;
   right: 0;

   height: 45px;

   background-color: #fff;
   // 防止被house-item组件中有绝对定位的覆盖掉
   z-index: 9;
}

对应searchBar组件:

<template>
    <div class="search">
        <div class="left">
            <div class="item start">
                <div class="name"></div>
                <div class="time">02.01</div>
            </div>
            <div class="item end">
                <div class="name"></div>
                <div class="time">02.02</div>
            </div>
        </div>
        <div class="content">
            <div class="keyword">关键字/位置/民宿</div>
        </div>
        <div class="right">
            <van-icon size="20px" color="#3f4954" name="search" />
        </div>
    </div>
</template>

<script setup>


</script>

<style lang="less" scoped>
.search {
    display: flex;
    justify-content: start;
    align-items: center;
    border-radius: 10px;
    background-color: #F5F5F5;
    margin: 5px 15px 10px;
    // padding: 5px;

    .left {
        display: flex;
        flex-direction: column;
        margin-left: 10px;

        .item {
            display: flex;
            flex-direction: row;
            font-size: 12px;
            margin: 3px;
        }

        .name {
            color: #999;
        }

        .time {
            margin: 0 3px;
            color: #000;
        }

    }

    .content {
        width: 80%;
        margin: 0 10px;

        .keyword {
            color: #999;
            font-size: 13px;
        }
    }

    .right {
        margin-right: 15px;
    }
}
</style>

效果:

在这里插入图片描述

显示时间同步

想让显示时间同步,显然我们要把时间放在store中统一管理。在日历中修改时间即在store中修改时间。任何需要读取时间的地方都在store中读取。

import { defineStore } from "pinia"

const startDay = new Date()
const endDay = new Date()
endDay.setDate(startDay.getDate() + 1)

const useMainStore = defineStore('main', {
    state: () => ({
        token:'',

        startDay:startDay,
        endDay:endDay
    }),
    actions: {

    }
})

export default useMainStore

在search-box中将时间同步:

// 日期
const { startDay, endDay } = storeToRefs(mainStore)
const startDayStr=ref(formatMonthDay(startDay.value))
const endDayStr=ref(formatMonthDay(endDay.value))

watch(startDay,(newValue)=>{
    startDayStr.value=formatMonthDay(startDay.value)
})
watch(endDay,(newValue)=>{
    endDayStr.value=formatMonthDay(endDay.value)
})

// 日历
const date = ref('1');
const showCalendar = ref(false);

const formatDate = (date) => `${date.getMonth() + 1}/${date.getDate()}`;
const onConfirm = (values) => {
    const [start, end] = values;
    showCalendar.value = false;

    mainStore.startDay=start
    mainStore.endDay=end
    date.value = getDiffDate(start, end)
};

在search-bar中时间同步的操作相似,不赘述。

效果

在这里插入图片描述
在这里插入图片描述

总代码

修改或添加的文件

在这里插入图片描述
在这里插入图片描述

search-bar.vue

组件:搜索栏。

<template>
    <div class="search">
        <div class="left">
            <div class="item start">
                <div class="name"></div>
                <div class="time">{{ startDayStr }}</div>
            </div>
            <div class="item end">
                <div class="name"></div>
                <div class="time">{{ endDayStr }}</div>
            </div>
        </div>
        <div class="content">
            <div class="keyword">关键字/位置/民宿</div>
        </div>
        <div class="right">
            <van-icon size="20px" color="#3f4954" name="search" />
        </div>
    </div>
</template>

<script setup>
import { ref } from 'vue';
import { storeToRefs } from 'pinia';

import useMainStore from '@/store/modules/main';
import { formatMonthDay2 } from '@/utils/formatDate'

const mainStore = useMainStore()
const { startDay, endDay } = storeToRefs(mainStore)
const startDayStr = ref(formatMonthDay2(startDay.value))
const endDayStr = ref(formatMonthDay2(endDay.value))

</script>

<style lang="less" scoped>
.search {
    display: flex;
    justify-content: start;
    align-items: center;
    border-radius: 10px;
    background-color: #F5F5F5;
    margin: 5px 15px 10px;
    // padding: 5px;

    .left {
        display: flex;
        flex-direction: column;
        margin-left: 10px;

        .item {
            display: flex;
            flex-direction: row;
            font-size: 12px;
            margin: 3px;
        }

        .name {
            color: #999;
        }

        .time {
            margin: 0 3px;
            color: #000;
        }

    }

    .content {
        width: 80%;
        margin: 0 10px;

        .keyword {
            color: #999;
            font-size: 13px;
        }
    }

    .right {
        margin-right: 15px;
    }
}
</style>

useScroll.js

增加了拓展性和节流。

// 关于滚动到底部的代码逻辑
import { onMounted, onUnmounted } from "@vue/runtime-core";
import { ref } from 'vue'
import { throttle } from "underscore";

export default function useScroll() {
    // 初始默认为没有到底
    const isReachBottom = ref(false)
    const scrollTop = ref(0)
    const clientHeight = ref(0)
    const scrollHeight = ref(0)

    const scrollBottomListener = throttle(() => {
        // 当前位置到顶部的距离
        scrollTop.value = document.documentElement.scrollTop
        // 屏幕的长度
        clientHeight.value = document.documentElement.clientHeight
        // 页面总体长度
        scrollHeight.value = document.documentElement.scrollHeight

        // 滚动到底部:提前一点刷新
        if (scrollHeight.value <= scrollTop.value + clientHeight.value + 1) {
            console.log('滚动到底部')
            isReachBottom.value = true
        }

        // console.log(scrollTop.value)
    }, 100)

    onMounted(() => {
        window.addEventListener('scroll', scrollBottomListener)
    })

    onUnmounted(() => {
        window.removeEventListener('scroll', scrollBottomListener)
    })

    return { isReachBottom, scrollHeight, clientHeight, scrollTop }
}

store的main.js

整个项目的时间显示保存在这里。

import { defineStore } from "pinia"

const startDay = new Date()
const endDay = new Date()
endDay.setDate(startDay.getDate() + 1)

const useMainStore = defineStore('main', {
    state: () => ({
        token:'',

        startDay:startDay,
        endDay:endDay
    }),
    actions: {

    }
})

export default useMainStore

formatDate.js

新增了"x.x"日期的格式化方法。

import dayjs from 'dayjs'

// 格式化“x月x日”
export function formatMonthDay(date) {
    return dayjs(date).format('MM月DD日')
}

// 格式化“x.x”
export function formatMonthDay2(date) {
    return dayjs(date).format('MM.DD')
}

// end-start
export function getDiffDate(start, end) {
    return dayjs(end).diff(start, 'day')
}

home.vue

新增页面滚动到目标位置显示搜索框,以及对应的css。
更新了时间同步。

<template>
    <div class="home">
        <div class="nav-bar">
            <div class="title">旅游App</div>
            <div class="banner">
                <img src="@/assets/img/home/banner.webp" alt="">
            </div>
        </div>
        <div class="search-box">
            <div class="section location">
                <div class="city">
                    <router-link to="/city">{{ cityStore.currentCity.cityName }}</router-link>
                </div>
                <div class="position">
                    <div class="text">我的位置</div>
                    <img src="@/assets/img/home/icon_location.png" alt="">
                </div>
            </div>

            <div class="section time-range" :value="date" @click="showCalendar = true">
                <div class="start">
                    <span>入住</span>
                    <div class="time">
                        {{ startDayStr }}
                    </div>
                </div>
                <div class="stay">共{{ date }}晚</div>
                <div class="end">
                    <span>离店</span>
                    <div class="time">
                        {{ endDayStr }}
                    </div>
                </div>
            </div>

            <!-- 日历 -->
            <van-calendar :round="false" v-model:show="showCalendar" type="range" @confirm="onConfirm"
                :show-confirm="false" />

            <!-- 价格人数 -->
            <div class="price-counter section">
                <div class="left">价格不限</div>
                <div class="right">人数不限</div>
            </div>

            <!-- 关键字 -->
            <div class="keyword section">
                <span>关键字/位置/民宿名</span>
            </div>

            <!-- 热门推荐 -->
            <div class="hotSuggest section">
                <template v-for="(item, index) in hotSuggestData" :key="index">
                    <div class="hotSuggestItem">
                        {{ item.tagText.text }}
                    </div>
                </template>
            </div>

            <div class="searchBtn" @click="searchBtnClick()">
                开始搜索
            </div>

            <div class="search-bar" v-if="isShowSearchBar">
                <searchBar />
            </div>

            <homeCategories />

            <homeContent />
        </div>
    </div>
</template>

<script setup>
import useCityStore from '../../store/modules/city';
import useHomeStore from '../../store/modules/home';
import useMainStore from '../../store/modules/main'
import { formatMonthDay, getDiffDate } from '@/utils/formatDate'
import homeCategories from './cpns/home-categories.vue'
import homeContent from './cpns/home-content.vue';
import useScroll from '../../hooks/useScroll';
import searchBar from '../../components/search-bar/search-bar.vue';

import { computed, ref, watch } from 'vue';
import { storeToRefs } from 'pinia';
import { useRouter } from 'vue-router'



const cityStore = useCityStore()
const homeStore = useHomeStore()
const mainStore = useMainStore()
const router = useRouter()


homeStore.fetchCategories()
const { categories } = storeToRefs(homeStore)
console.log(categories)

function moreList() {
    homeStore.fetchHouseList()
}

// 日期
const { startDay, endDay } = storeToRefs(mainStore)
const startDayStr=ref(formatMonthDay(startDay.value))
const endDayStr=ref(formatMonthDay(endDay.value))

watch(startDay,(newValue)=>{
    startDayStr.value=formatMonthDay(startDay.value)
})
watch(endDay,(newValue)=>{
    endDayStr.value=formatMonthDay(endDay.value)
})

// 日历
const date = ref('1');
const showCalendar = ref(false);

const formatDate = (date) => `${date.getMonth() + 1}/${date.getDate()}`;
const onConfirm = (values) => {
    const [start, end] = values;
    showCalendar.value = false;

    mainStore.startDay=start
    mainStore.endDay=end
    date.value = getDiffDate(start, end)
};

// 热门数据
homeStore.fetchHotSuggest()
const { hotSuggest } = storeToRefs(homeStore)
const hotSuggestData = hotSuggest

// 搜索按钮跳转
function searchBtnClick() {
    router.push({
        path: '/search',
        query: {
            // 因为是响应式
            startDay: startDay.value,
            endDay: endDay.value
        }
    })
}

// 是否显示搜索栏的控制

const { scrollTop } = useScroll()
const isShowSearchBar = computed(() => {
    return scrollTop.value >= 484
})

</script>

<style lang="less" scoped>
.home {
    .nav-bar {
        .title {
            height: 46px;

            // flex居中,以后左右有东西可以直接加
            display: flex;
            align-items: center;
            justify-content: center;

            color: var(--primary-color);
            font-size: 16px;
            font-weight: 700;
        }

        .banner {

            // 图片本身大很多,让它大小刚好
            img {
                width: 100%;
            }
        }
    }

    .search-box {

        --van-calendar-popup-height: 100%;

        // search-box里的每个部分都加上section
        // 都有类似的样式
        .section {
            display: flex;
            flex-wrap: wrap;
            align-items: center;
            padding: 0 20px;
            color: #999;
            margin-top: 10px;
        }

        .location {
            height: 44px;

            display: flex;
            align-items: center;
            padding: 0 20px;
            color: #53565c;

            .city {
                // flex:1 === flex:1 1 auto 除了position之外的剩余部分都属于city
                flex: 1;
            }

            .position {
                width: 74px;

                display: flex;
                align-items: center;

                .text {
                    font-size: 12px;
                }

                img {
                    width: 20px;
                    margin-left: 5px;
                }
            }
        }

        .time-range {
            display: flex;
            justify-content: space-between;
            height: 45px;

            span {
                font-size: 16px;
            }

            .time {
                color: #53565c;
            }
        }

        .price-counter {
            justify-content: space-between;
            height: 35px;
        }

        .keyword {
            height: 35px;
        }

        .hotSuggest {

            .hotSuggestItem {

                margin: 3px;
                padding: 4px 8px;
                font-size: 12px;
                background-color: #f1f3f5;
                color: #3f4954;
                border-radius: 20px;
            }
        }

        .searchBtn {
            display: flex;
            justify-content: center;
            align-items: center;

            height: 38px;
            font-size: 18px;
            // 渐变色要用image
            background-image: var(--theme-linear-gradient);
            color: #fff;

            border-radius: 20px;
            margin: 20px 20px;
        }

        .search-bar {
            // 定位在屏幕某位置,不随页面滚动而改变
            position: fixed;
            top: 0;
            left: 0;
            right: 0;

            height: 45px;

            background-color: #fff;
            // 防止被house-item组件中有绝对定位的覆盖掉
            z-index: 9;
        }
    }
}
</style>

参考

面试官:什么是防抖和节流?有什么区别?如何实现? | web前端面试 - 面试官系列 (vue3js.cn)

Underscore.js 简介 | Underscore.js 中文文档 | Underscore.js 中文网 (underscorejs.cn)

Vue 警告 Write operation failed: computed value is readonly_PKQ1023的博客-CSDN博客

【Js】检查Date对象是否为Invalid Date_smart_dream的博客-CSDN博客_invalid date

vue父组件通过ref获取子组件data数据出现undefined(问题篇)_skyblue_afan的博客-CSDN博客

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

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

相关文章

HDFS文件浏览器功能OOM排查

现象描述 涉及HDFS文件浏览器的某个功能运行一段时间后会出现OOM的情况 错误日志如下&#xff1a; service.log.2023-02-01-0.log:java.lang.OutOfMemoryError: Java heap space排查过程 需要查看dump文件排查一下造成OOM的原因 查看jvm参数如下&#xff1a; java -Duser.t…

一文讲明Docker的基本使用,常见Docker命令使用 、Docker的安装使用等【详细说明+图解+概念+实践】

一个混迹于Github、Stack Overflow、开源中国、CSDN、博客园、稀土掘金、51CTO等 的野生程序员。 目标&#xff1a;分享更多的知识&#xff0c;充实自己&#xff0c;帮助他人 GitHub公共仓库&#xff1a;https://github.com/zhengyuzh 以github为主&#xff1a; 1、分享前端后端…

【Python合集系列】2023兔年吉祥,新的一年希望放烟花的人跟看烟花的人都能平平安安哦~(附多种源码)

前言 希望放烟花的人跟看烟花的人都能平平安安。 &#x1f440; NICE TO MEET YOU :)&#x1f319; 所有文章完整的素材源码都在&#x1f447;&#x1f447; 粉丝白嫖源码福利&#xff0c;请移步至CSDN社区或文末公众hao即可免费。 ​哈喽&#xff01;我是木子&#xff0c;新…

设计模式之适配器模式,以C++为例。

今天来盘一盘适配器模式。适配器&#xff1a;顾名思义&#xff0c;就是让原本不合适的变为合适的&#xff0c;好似一对男女&#xff0c;没有中间的媒婆是不会互相了解的&#xff0c;好像不太恰当&#xff0c;就这么解释吧&#xff0c;只有有了这个中间人他们才会产生联系&#…

智能驾驶开启高精定位新赛道,这家供应商正加码布局海外市场

高工智能汽车研究院监测数据显示&#xff0c;2022年1-11月中国市场乘用车前装标配搭载NOA交付达到18.38万辆&#xff0c;同比增长91.86%&#xff1b;同时&#xff0c;NOA搭载的车型配置价格还在不断下滑&#xff0c;正在把NOA的配置拉至15万元价格区间。 而作为高精定位&#x…

面向对象——static(静态)Math类自定义工具类代码块

目录 static&#xff08;静态&#xff09;关键字 static的注意事项 static的优点和缺点 应用场景 自定义工具类 代码块 static&#xff08;静态&#xff09;关键字 static是一个修饰符&#xff0c;用于修饰成员&#xff08;成员变量 、成员方法&#xff09;static的特点…

Redis处理client连接数过多,大量空闲链接无法释放问题

打开redis命令终端&#xff0c;输入&#xff1a; client list 查看连接数&#xff0c;用于返回所有连接到服务器的客户端信息和统计数据 参数解析&#xff1a; id: 唯一的64位的客户端ID(Redis 2.8.12加入)。 addr: 客户端的地址和端口 fd: 套接字所使用的文件描述符 age…

python真的很骚可惜你不会

python基本语法 &#x1f4d2;博客主页&#xff1a; 微笑的段嘉许博客主页 &#x1f389;欢迎关注&#x1f50e;点赞&#x1f44d;收藏⭐留言&#x1f4dd; &#x1f4cc;本文由微笑的段嘉许原创&#xff01; &#x1f4c6;51CTO首发时间&#xff1a;&#x1f334;2023年1月日3…

redis分布式缓存

文章目录一、redis持久化1.1.RDB持久化1.1.1.执行时机1.1.2.RDB原理1.1.3.小结1.2.AOF持久化1.2.1.AOF原理1.2.2.AOF配置1.2.3.AOF文件重写1.2.4.小结1.3.RDB与AOF对比二、Redis主从集群2.1.集群结构2.2.准备实例和配置2.3.启动2.4.开启主从关系2.5.测试2.6.主从数据同步原理2.…

Codeforces Round #848 (Div. 2) A-E 赛时思路+正解

青大蒟蒻第一次在正式的div2div2div2中AcAcAc了五道题&#xff0c;也是小蒟蒻有史以来发挥最好的一场&#xff0c;这场过后我的cf也许可能也要变成黄了。 A. Flip Flop Sum 题意&#xff1a;给定一个a——ia——ia——i数组&#xff0c;权值仅为1或-1&#xff0c;我们选择相邻…

《死亡空间》重制回归!无法启动怎么办?

作为科幻生存恐怖系列的经典之作&#xff0c;《死亡空间》在推出15年后再次回归&#xff0c;果然引发热潮。精美震撼的科幻场景&#xff0c;强烈的视觉画面&#xff0c;加上阴森的3D 音效&#xff0c;重制版提升了身临其境之感&#xff0c;完全是沉浸式恐怖体验&#xff0c;只能…

红外遥控数码管显示

红外遥控器实物图红外遥控器接口电路数码管接口电路红外遥控数码管显示程序源代码/**************************红外遥控数码管显示************************** * 单片机&#xff1a;51单片机* 开发环境&#xff1a;keil * 名称:红外遥控数码管显示 * 功能&#xff1a;遥控器红外…

C语言常量

常量是固定值&#xff0c;在程序执行期间不会改变。这些固定的值&#xff0c;又叫做字面量。常量可以是任何的基本数据类型&#xff0c;比如整数常量、浮点常量、字符常量&#xff0c;或字符串字面值&#xff0c;也有枚举常量。常量就像是常规的变量&#xff0c;只不过常量的值…

OpenMMLAB AI实战营第一课笔记

计算机视觉的发展 计算机视觉是什么 计算机视觉是一门让计算机学会"看"的学科&#xff0c;研究如何自动理解图像和视频中的内容 计算机视觉的发展 早期萌芽&#xff08;1960-1980&#xff09; 统计机器学习与模式识别(1990-2000) ImageNet 大型数据库(2006) 斯坦…

ocelot+consul治理服务

consulConsul 是HashiCorp公司推出的开源工具&#xff0c;用于实现分布式系统的服务发现与配置。与其它分布式服务注册与发现的方案相比&#xff0c;Consul的方案更“一站式”&#xff0c;内置了服务注册与发现框架、分布一致性协议实现、健康检查、Key/Value存储、多数据中心方…

程序员副业接单做私活避坑指南

这篇文章系统的分享了对接单做私活这件事情的思考&#xff0c;也给出一些干货建议。希望让大家少走一些弯路&#xff0c;不要被坑。 先说结论 不建议大家在接单这个事情上投入太大精力&#xff0c;如果你“贼心不改”&#xff0c;建议大家以比较随缘的方式对待这件事情。 再说…

Linux云主机配置

Linux云主机配置 推荐环境&#xff1a; Mac 阿里云主机Linux 阿里云主机Windows Xshell 阿里云主机&#xff08;选择使用&#xff09;Windows 虚拟机 阿里云主机 1.云主机配置 选择配置的过程中&#xff0c;请注意选择操作系统版本为Ubuntu 16.04 64位 或 Ubuntu 18.04 6…

多位大厂专家鼎力推荐,44个微服务架构设计模式pdf,程序员福利

前言 本文的目标是让架构师和程序员学会使用微服务架构成功开发应用程序。 本文不仅讨论了微服务架构的好处&#xff0c;还描述了它们的弊端。读者将掌握如何在使用单体架构和使用微服务架构之间做出正确的权衡。 谁应该阅读本文&#xff1f; 本文的重点是架构和开发&#…

前端vue2实现头部组件(自定义背景icon+抽屉式使用指南展示)

一、文章引导 #mermaid-svg-Sqlx5Ih7pUPfo8rw {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-Sqlx5Ih7pUPfo8rw .error-icon{fill:#552222;}#mermaid-svg-Sqlx5Ih7pUPfo8rw .error-text{fill:#552222;stroke:#55222…

Python多态及用法详解

Python 是弱类型语言&#xff0c;其最明显的特征是在使用变量时&#xff0c;无需为其指定具体的数据类型。这会导致一种情况&#xff0c;即同一变量可能会被先后赋值不同的类对象&#xff0c;例如&#xff1a;class CLanguage: defsay(self): print("赋值的是 CLanguage 类…