简历考察点2_《CiCi-基于Vue3.0的智能音乐分享平台》

news2024/10/2 20:28:26

(1)项目初始化和推荐页面开发:

重点:轮播图、Scroll、下拉加载方法实现、

问题一:轮播图实现

① 获取轮播图数据:虽然找到接口了,但是由于XHR请求在浏览器端会有跨域的限制,不能直接请求QQ官网的接口地址,需要做一层Proxy代理:

 获取响应数据:

 获取轮播图数据,使用BetterScroll的基本配置项,监听slideWillChange事件

onMounted(() => {
    const sliderVal = slider.value = new BScroll(wrapperRef.value, {
      click: true,
      scrollX: true,
      scrollY: false,
      momentum: false,
      bounce: false,
      probeType: 2,
      slide: true
    })

    sliderVal.on('slideWillChange', (page) => {
      currentPageIndex.value = page.pageX
    })
  })

 问题二: 歌单列表 超过 recommend 页面时 不能滚动,如何解决?

添加 overflow: scroll;属性就可以滚动了

 支持slot 插槽的方式,滚动内容放入插槽中,外层可以和better-scroll做一些初始化联动

// 构造钩子 函数
import BScroll from '@better-scroll/core'
import ObserveDOM from '@better-scroll/observe-dom'
import { onMounted, onUnmounted, ref } from 'vue'

BScroll.use(ObserveDOM)

export default function useScroll(wrapperRef, options, emit) {
  const scroll = ref(null)

  onMounted(() => {
      const scrollVal = scroll.value = new BScroll(wrapperRef.value, {
      observeDOM: true,
      ...options
    })
    
    if (options.probeType > 0) { 
      scrollVal.on('scroll', (pos) => { 
        // useScroll(rootRef, props, emit) 通过 emit 把位置信息派发出去
        emit('scroll', pos)
      })
    }
  })

  onUnmounted(() => {
    scroll.value.destroy()
  })

  return scroll
}

 Better-Scroll debugger发现容器高度和内容高度不一致时,采用observe-dom开启对content以及content子元素DOM改变的探测。当插件被使用后,当这些DOM元素发生变化时,将会触发scroll的refresh方法:

1. 针对改变频繁的CSS属性,增加debounce;

2. 如果改变发生在scroll动画过程中,则不会触发refresh

问题三:图片懒加载的实现> assets-js-create-loading-like-directive

vue2.0 vue-lazyload会实现图片懒加载的效果,默认先加载chicken图片,再去加载新的图片

/** 实现loading 加载的处理 */
import { createApp } from 'vue'
import { addClass, removeClass } from '@/assets/js/dom'

/** 
 * base.scss 定义的属性 ---  处理歌手详情页 边界效果的处理
 * .g-relative { position: relative; }
 */

const relativeCls = 'g-relative'

export default function createLoadingLikeDirective(Comp) {
  return {
    mounted(el, binding) {
      const app = createApp(Comp)
      const instance = app.mount(document.createElement('div'))
      const name = Comp.name
      if (!el[name]) {
        el[name] = {}
      }
      el[name].instance = instance
      const title = binding.arg
      if (typeof title !== 'undefined') {
        instance.setTitle(title)
      }

      if (binding.value) {
        append(el)
      }
    },
    updated(el, binding) {
      const title = binding.arg
      const name = Comp.name
      if (typeof title !== 'undefined') {
        el[name].instance.setTitle(title)
      }
      if (binding.value !== binding.oldValue) {
        binding.value ? append(el) : remove(el)
      }
    }
  }

  function append(el) {
    const name = Comp.name
    const style = getComputedStyle(el)
    if (['absolute', 'fixed', 'relative'].indexOf(style.position) === -1) {
      addClass(el, relativeCls)
    }
    el.appendChild(el[name].instance.$el)
  }

  function remove(el) {
    const name = Comp.name
    removeClass(el, relativeCls)
    el.removeChild(el[name].instance.$el)
  }
}

在组件中引入: 

(2)歌手页面开发:

问题:IndexList组件功能实现、use-fix歌手列表固定标题实现、use-shortcut歌手列表快速导航入口实现

问题一:IndexList组件功能 界面实现

歌手列表导航实现: 调用接口,获取封装后的数据,如何根据序列化找到对应歌手 

界面实现: 上方有固定标题栏,左侧  右侧是序列分成了不同组设置快速导航入口A-Z排序

<!-- 歌手列表 将数据呈现-->
<template>
  <scroll 
    class="index-list"
    :probe-type="3"
    @scroll="onScroll"
    ref="scrollRef"
    >
    <!-- 采用 groupRef 来获取DOM -->
    <ul ref="groupRef">
      <li 
        v-for="group in data"
        :key="group.title"
        class="group"
      >
        <h2 class="title">{{group.title}}</h2>
        <ul>
          <li
            v-for="item in group.list"
            :key="item.id"
            class="item"
            @click="onItemClick(item)"
          >
            <img class="avatar" v-lazy="item.pic">
            <span class="name">{{item.name}}</span>
          </li>
        </ul>
      </li>
    </ul>
    <!-- 歌手列表固定标题 -->
    <div 
      class="fixed"
      v-show="fixedTitle"
      :style="fixedStyle"
    >
      <div class="fixed-title">{{fixedTitle}}</div>
    </div>

    <!-- 快速导航入口 设置 A-Z 排序 -->
    <div 
      class="shortcut"
      @touchstart.stop.prevent="onShortcutTouchStart"    
      @touchmove.stop.prevent="onShortcutTouchMove"
      @touchend.stop.prevent
    >
      <ul>
        <li
          v-for="(item, index) in shortcutList"
          :key="item"
          :data-index="index"         
          class="item"
          :class="{'current': currentIndex === index}">
          {{ item }}
        </li>
      </ul>
    </div>
  </scroll>
</template>

 问题二:use-shortcut 设置快速导航入口:

  function onShortcutTouchStart(e) { 
    console.log(e.target)
    const anchorIndex = parseInt(e.target.dataset.index)
    touch.y1 = e.touches[0].pageY
    touch.anchorIndex = anchorIndex
    // 滑动到目标锚点
    scrollTo(anchorIndex)
  }

  // 根据鼠标move 快速移动
  function onShortcutTouchMove(e) { 
    touch.y2 = e.touches[0].pageY
    // 接近栏 距离 上一栏 距离 判断
    const delta = (touch.y2 - touch.y1) / ANCHOR_HEIGHT | 0
    const anchorIndex = touch.anchorIndex + delta
    // 滑动到目标锚点
    scrollTo(anchorIndex)
  }

  function scrollTo(index) { 
    if (isNaN(index)) { 
      return
    }
    // 设置index 的值
    index = Math.max(0, Math.min(shortcutList.value.length - 1, index))
    const targetEl = groupRef.value.children[index]
    const scroll = scrollRef.value.scroll
    scroll.scrollToElement(targetEl, 0)
  }

问题三:标题固定 

当calculate() 完成之后 设置nextTick 执行延迟回调

probeType

  • 类型:Number
  • 默认值:0
  • 可选值:1、2、3
  • 作用:有时候我们需要知道滚动的位置。
  • 当 probeType 为 1 的时候,会非实时(屏幕滑动超过一定时间后)派发scroll 事件;
  • 当 probeType 为 2 的时候,会在屏幕滑动的过程中实时的派发 scroll 事件;
  • 当 probeType 为 3 的时候,不仅在屏幕滑动的过程中,而且在 momentum 滚动动画运行过程中实时派发 scroll 事件。
  • 如果没有设置该值,其默认值为 0,即不派发 scroll 事件。

存储singer关键字

(3) 歌手页面开发 singer-detail

歌手的唯一标识  singerMid: req.requery.mid

异步获取关键歌手信息:

上推的时候 图层变模糊 列表往上滑动 overflow-hidden: false

需要设置图片层级 上面的标题 在上推的时候,标题不会被掩盖

下拉的时候 图片整体放大 有回弹效果

<scroll
    class="list"
    :style="scrollStyle"
    v-loading="loading"
    v-no-result:[noResultText]="noResult"
    :probe-type="3"
    @scroll="onScroll"  //设置scroll 来监听事件
    >

 

核心代码:具体的含义是什么

为什么设置maxTranslateY

const RESERVED_HEIGHT = 40 作用是什么

Z-Index 折叠层 较大的元素会覆盖较小的元素在上层进行显示

const RESERVED_HEIGHT = 40 // 设置默认标签头高度

  export default {
    name: 'music-list',
    components: {
      SongList,
      Scroll
    },
    props: {
      songs: {
        type: Array,
        default() {
          return []
        }
      },
      title: String,
      pic: String,
      loading: Boolean,
      noResultText: {
        type: String,
        default: '抱歉,没有找到可播放的歌曲'
      },
      // rank  榜单标签 默认 boolean
      rank: Boolean  
    },
    data() {
      return {
        imageHeight: 0,
        scrollY: 0,
        maxTranslateY: 0
      }
    },
    computed: {
      noResult() {
        return !this.loading && !this.songs.length
      },
      playBtnStyle() {
        let display = ''
        if (this.scrollY >= this.maxTranslateY) {
          display = 'none'
        }
        return {
          display
        }
      },
      bgImageStyle() {
        const scrollY = this.scrollY
        let zIndex = 0
        let paddingTop = '70%'
        let height = 0
        // 兼容 iPhone 设备
        let translateZ = 0
        // 可以滚动到的最大高度
        if (scrollY > this.maxTranslateY) {
          zIndex = 10
          paddingTop = 0
          height = `${RESERVED_HEIGHT}px`
          translateZ = 1
        }
        // 实现向上推的效果 默认值为1
        let scale = 1
        // 向下推 Y坐标为负数
        if (scrollY < 0) {
          scale = 1 + Math.abs(scrollY / this.imageHeight)
        }

        return {
          zIndex,
          paddingTop,
          height,
          backgroundImage: `url(${this.pic})`,
          transform: `scale(${scale})translateZ(${translateZ}px)`
        }
      },
      scrollStyle() {
        const bottom = this.playlist.length ? '60px' : '0'
        return {
          top: `${this.imageHeight}px`,
          bottom
        }
      },
      // 设置遮罩层
      filterStyle() {
        let blur = 0
        const scrollY = this.scrollY
        const imageHeight = this.imageHeight
        if (scrollY >= 0) {
          blur = Math.min(this.maxTranslateY / imageHeight, scrollY / imageHeight) * 20  // 设置blur缩放比
        }
        return {
          backdropFilter: `blur(${blur}px)`
        }
      },
      ...mapState([
        'playlist'
      ])
    },
    mounted() {
      this.imageHeight = this.$refs.bgImage.clientHeight
      this.maxTranslateY = this.imageHeight - RESERVED_HEIGHT  // 可以移动的最大高度
    },
    methods: {
      goBack() {
        this.$router.back()
      },
      onScroll(pos) {
        this.scrollY = -pos.y
      },
      //  学到这里的时候对其他部分进行处理
      selectItem({ index }) {
        this.selectPlay({
          list: this.songs,
          index
        })
      },
      random() {
        this.randomPlay(this.songs)
      },
      ...mapActions([
        'selectPlay',
        'randomPlay'
      ])
    }
  }

(4)歌手详情页组件开发

问题一: 歌手详情页 详情页刷新 -- 刷新依然可以访问(有问题)-1:20

mid 总是加载不出来 依赖于传递的prop:singer 对象

分析 之前页面渲染会报错:现在的页面渲染依赖于prop singer这个数据,之前为什么可以 因为会通过歌手列表sing-list一级路由,点击某个歌手的时候 可以拿到这个歌手对应的singer对象,渲染二级路由的时候将singer对象进行传递,所以页面可以正常渲染,但是一旦页面进行刷新之后 内存中的数据都丢失了,因为刷新之后 没有经过一级路由 不知道点击了对应的哪个歌手,这样就拿不到对应的歌手对象 拿不到歌手对象 页面自然不能正常渲染 要保证可以正常渲染 借助浏览器的本地存储能力 使用存储一个使用localstorage和sessionstorage(关掉页面就没有了 但是刷新还是在的),当然 这里页面刷新使用sessionstorage 就足够实现

借助浏览器的本地存储能力 来解决这个问题:

使用 good-storage的方式

import storage from 'good-storage'

// localStorage

Storage.set(key, val)

Storage.get(key, def)

// sessionStorage

storage.session.set(key, val)

storage.session.get(key, val)

通过 constance.js 来存储项目中的共享常量

// 定义当前的singer_key 对象
export const SINGER_KEY = '__singer__'
export const FAVORITE_KEY = '__favorite__'
export const ALBUM_KEY = '__album__'
export const TOP_KEY = '__top__'
export const SEARCH_KEY = '__search__'
export const PLAY_KEY = '__play__'

/**
 * 歌手详情页_音乐播放器PLAY_MODE
 * sequence 顺序播放
 * loop 循环播放
 * random 随机播放
*/
export const PLAY_MODE = {
  sequence: 0,
  loop: 1,
  random: 2
}

(2)问题二:transitions 实现歌手详情页路由的过渡效果 transform: translate3d(0, 0, 0);

<template>
  <!-- 当singers数组为空的时候 加载loading -->
  <div class="singer" v-loading="!singers.length">
    <index-list
      :data="singers"
      @select="selectSinger"
    ></index-list>
    <router-view v-slot="{ Component }">
      <transition appear name="slide">
        <!-- 传递 对应的singer数据 -->
        <component :is="Component" 
        :data="selectedSinger" />  
      </transition>
    </router-view>
  </div>
</template>

(3)歌手详情页歌曲列表随机播放 shuffle 函数引入 实现随机播放

// 实现shuffle 洗牌功能
export function shuffle(source) {
  const arr = source.slice()
  for (let i = 0; i < arr.length; i++) {
    const j = getRandomInt(i)
    swap(arr, i, j)
  }
  return arr
}

function getRandomInt(max) {
  return Math.floor(Math.random() * (max + 1))
}

function swap(arr, i, j) {
  const t = arr[i]
  arr[i] = arr[j]
  arr[j] = t
}

(5)播放器内核组件开发

 

 (6)歌单详情页与排行榜页面开发

 

歌单详情页: 歌手详情获取 sessionstorage

在渲染歌手详情页面 要获取到对应 歌曲的cached.id来拿到数据,对singer拿到数据是singer.mid

computedSinger() {
        let ret = null
        const data = this.data
        if (data) {
          ret = data
        } else {
          const cached = storage.session.get(key)
          // 歌手详情获取的getSingerDetail.mid  但对于 歌曲详情 是数字id 这里需要转换成字符串 所以是catche.id
          if (cached && (cached.mid || cached.id + '') === this.$route.params.id) {
            ret = cached
          }
        }
        return ret
      }

歌单排行榜 top-list.vue 根据Key 值来获取到 排行榜列表 

排行榜 的编号:获取TopDetail 具体信息

export function getTopDetail(top) {
  return get('/api/getTopDetail', {
    id: top.id,
    period: top.period
  })
}

 歌手排行榜和 图标

<template>
  <ul class="song-list">
    <li
      class="item"
      v-for="(song, index) in songs"
      :key="song.id"
      @click="selectItem(song, index)"
    >
      <div class="rank" v-if="rank">
        <span :class="getRankCls(index)">{{ getRankText(index) }}</span>
      </div>
      <div class="content">
        <h2 class="name">{{song.name}}</h2>
        <p class="desc">{{getDesc(song)}}</p>
      </div>
    </li>
  </ul>
</template>

<script>
  export default {
    name: 'song-list',
    props: {
      songs: {
        type: Array,
        default() {
          return []
        }
      },
      rank: Boolean
    },
    emits: ['select'],
    methods: {
      getDesc(song) {
        return `${song.singer}·${song.album}`
      },
      selectItem(song, index) {
        this.$emit('select', { song, index })
      },
      getRankCls(index) {
        if (index <= 2) {
          return `icon icon${index}` // 在css中设置了对应的样式
        } else {
          return 'text'
        }
      },
      getRankText(index) {
        if (index > 2) {
          return index + 1
        }
      }
    }
  }
</script>

<style lang="scss" scoped>  省略一部分
    .icon {
          display: inline-block;
          width: 25px;
          height: 24px;
          background-size: 25px 24px;
          &.icon0 {
            @include bg-image('first');
          }
          &.icon1 {
            @include bg-image('second');
          }
          &.icon2 {
            @include bg-image('third');
          }
        }
<style>

 (7)搜索页面开发:

具备搜索框(在搜索框中输入文字 就会显示出歌曲或者歌手,向上滑动的时候就会进行歌单的加载-上拉加载)、热门搜索 点击表单会在输入框进行回显、搜索历史呈现

 v-model 监听事件 监听input框中数据的变化

v-model是双向绑定,当值进行传递的时候,会根据传输的值进行渲染,子组件是不能修改值的,子组件的值是从父组件而来。但是data中定义的变量是可以进行修改的,再设置watch进行监听

所以不能写成: v-model: modelValue

当输入框中频繁输入进行内容提交时

采用 throttle-debounce 实现节流效果 输入内容较多时候(JS高级 之 防抖 debounce - throttle 节流_js防抖debounce_玄鱼殇的博客-CSDN博客)

防抖 debounce

1. 概念

  • 当事件触发时,相应的函数并不会立即触发,而是会等待一定的时间
  • 当事件密集触发时,函数的触发会被频繁的推迟,并把上一次的给取消掉
  • 只有等待了一段时间也没有事件触发,才会真正的执行响应函数

2. 应用场景

  • 输入框中频繁的输入内容,搜索或者提交信息
  • 频繁的点击按钮,触发某个事件
  • 监听浏览器滚动事件,完成某些特定操作
  • 用户缩放浏览器的resize事件

节流 throttle 
1. 概念

  • 当事件触发时,会执行这个事件的响应函数
  • 如果这个事件会被频繁触发,那么节流函数会按照一定的频率来执行函数
  • 不管在这个中间有多少次触发这个事件,执行函数的频繁总是固定的


2. 应用场景

  • 监听页面的滚动事件
  • 鼠标移动事件
  • 用户频繁点击按钮操作
  • 轮播图的按钮滚动
this.$watch('query', debounce(300, (newQuery) => {
        this.$emit('update:modelValue', newQuery.trim())
      }))
<template>
  <div class="search-input">
    <i class="icon-search"></i>
    <input
      class="input-inner"
      v-model="query"
      :placeholder="placeholder"
    />
    <i
      v-show="query"
      class="icon-dismiss"
      @click="clear"
    ></i>
  </div>
</template>

<script>
  import { debounce } from 'throttle-debounce'

  export default {
    name: 'search-input',
    props: {
      modelValue: String,
      placeholder: {
        type: String,
        default: '搜索歌曲、歌手'
      }
    },
    data() {
      return {
        query: this.modelValue
      }
    },
    created() {
      this.$watch('query', debounce(300, (newQuery) => {
        this.$emit('update:modelValue', newQuery.trim())
      }))

      this.$watch('modelValue', (newVal) => {
        this.query = newVal
      })
    },
    methods: {
      clear() {
        this.query = ''
      }
    }
  }
</script>

 ① 实现数据绑定:

1.实现一个监听器Observer,用来劫持并监听所有属性,如果有变动的,就通知订阅者。

2.实现一个订阅者Watcher,每一个Watcher都绑定一个更新函数,watcher可以收到属性的变化通知并执行相应的函数,从而更新视图。

3.实现一个解析器Compile,可以扫描和解析每个节点的相关指令(v-model,v-on等指令),如果节点存在v-model,v-on等指令,则解析器Compile初始化这类节点的模板数据,使之可以显示在视图上,然后初始化相应的订阅者(Watcher)。

搜索suggest完成组件化开发 (写完)

设置use-pull-up-load 进行下拉框加载


  onMounted(() => {
    const scrollVal = scroll.value = new BScroll(rootRef.value, {
      pullUpLoad: true,
      observeDOM: true,
      click: true
    })

    scrollVal.on('pullingUp', pullingUpHandler)

    async function pullingUpHandler() {
      if (preventPullUpLoad.value) {
        scrollVal.finishPullUp()
        return
      }
      isPullUpLoad.value = true
      await requestData()
      scrollVal.finishPullUp()
      scrollVal.refresh()
      isPullUpLoad.value = false
    }
  })

设置use-search-history 获取搜索历史记录

export default function useSearchHistory() {
  const maxLen = 200

  const store = useStore()

  function saveSearch(query) {
    const searches = save(query, SEARCH_KEY, (item) => {
      return item === query
    }, maxLen)
    store.commit('setSearchHistory', searches)
  }

  function deleteSearch(query) {
    const searches = remove(SEARCH_KEY, (item) => {
      return item === query
    })
    store.commit('setSearchHistory', searches)
  }

  function clearSearch() {
    const searches = clear(SEARCH_KEY)
    store.commit('setSearchHistory', searches)
  }

  return {
    saveSearch,
    deleteSearch,
    clearSearch
  }
}

 (8)添加歌曲到用户中心

(9)性能优化

利用keep-alive实现组件应用:每次切换Tab的时候 都会重新渲染组件并发送异步请求,即使这个组件被访问过还是会重复这个逻辑。但这个项目要求没有这么高,所以下次重复访问的时候,存储的数据还是可以再次使用的

 Dom 随着Tab切换缓存依然存在,需要设置 重置onActivated和清理onDeactivated的工作-Scroll Slide use-mini-slide use-pull-up-load

<router-view :style="viewStyle" v-slot="{ Component }">
    <keep-alive>
      <component :is="Component"/>
    </keep-alive>
  </router-view>

 (2)路由组件异步加载:实现非首屏代码异步加载,减缓首屏代码加载执行速率(路由懒加载)

依靠webpack+ES6的的方式

 在设置路由后 进行模式注释

configureWebpack: (config) => {
    if (process.env.npm_config_report) {
      const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
      config.plugins.push(new BundleAnalyzerPlugin())
    }
  },

路由懒加载 

webpack提供的require.ensure()
vue-router配置路由,使用webpack的require.ensure技术,也可以实现按需加载。
这种情况下,多个路由指定相同的chunkName,会合并打包成一个js文件。

// 下面2行代码,没有指定webpackChunkName,每个组件打包成一个js文件。
/* const Home = () => import('@/components/home')
const Index = () => import('@/components/index')
const About = () => import('@/components/about') */
// 下面2行代码,指定了相同的webpackChunkName,会合并打包成一个js文件。 把组件按组分块
const Home =  () => import(/* webpackChunkName: 'ImportFuncDemo' */ '@/components/home')
const Index = () => import(/* webpackChunkName: 'ImportFuncDemo' */ '@/components/index')
const About = () => import(/* webpackChunkName: 'ImportFuncDemo' */ '@/components/about')

(3)通过webpack组件化管理进行项目部署

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

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

相关文章

8_分类算法-k近邻算法(KNN)

文章目录 1 KNN算法1.1 KNN算法原理1.2 KNN过程1.3 KNN三要素1.4 KNN分类预测规则1.5 KNN回归预测规则1.6 KNN算法实现方式&#xff08;重点&#xff09;1.7 k近邻算法优缺点 2 KD-Tree2.1 KD Tree构建方式2.2 KD Tree查找最近邻2.3 KNN参数说明 1 KNN算法 定义&#xff1a;如…

fineReport10问题笔记

1. word导出相关问题 1.1 导出文字为图片 fineReport技术文档 1&#xff09;文本控制 选中单元格&#xff0c;点击「单元格属性>样式>对齐」&#xff0c;文本控制设置有四种&#xff0c;分别为「自动换行、单行显示、单行显示&#xff08;调整字体&#xff09;、多行显…

AA实验是什么?

AA实验是什么&#xff1a;AA实验是在AB实验正式上线前做的分流均匀性检验&#xff0c;这个时候还没有正式上实验策略&#xff0c;只是为了检验两组的分流是否均匀先空跑一段时间。 AA实验的准备工作&#xff1a;这个时候要进行的工作是检查 两组分流是否均匀 、埋点是否正常 。…

精益求精:通付盾安卓应用加固升级,为移动安全保驾护航!

在如今竞争激烈的移动应用领域&#xff0c;保障应用资源的安全性成为刻不容缓的任务。最近&#xff0c;通付盾针对资源加密方案进行了全面升级&#xff0c;大幅增强了其兼容性&#xff0c;实现了更全面的资源文件类型保护。这次升级为移动应用的安全性和稳定性迈出了坚实的一步…

driver‘s license exam 2

机动车科目二内容 driver‘s license exam 1_spencer_tseng的博客-CSDN博客 driver‘s license exam 2_spencer_tseng的博客-CSDN博客 driver‘s license exam 3_spencer_tseng的博客-CSDN博客 driver‘s license exam 4_spencer_tseng的博客-CSDN博客 car indicator light…

跨平台图表:ChartDirector for .NET 7.1 Crack

什么是新的 ChartDirector for .NET 7.0 支持跨平台使用&#xff0c;但仅限于 .NET 6。这是因为在 .NET 7 中&#xff0c;Microsoft 停止了用于非 Windows 使用的 .NET 图形库 System.Drawing.Common。由于 ChartDirector for .NET 7.0 依赖于该库&#xff0c;因此它不再支持 .…

物通博联嵌入式数据采集网关采集传感器的数据上传到云端

在当今的物联网&#xff08;IoT&#xff09;时代&#xff0c;各种传感器广泛应用于各种工业领域。传感器数据采集是实现自动化生产的基础&#xff0c;可以为企业决策提供科学的数据支持&#xff0c;通过各类智能传感器采集传输终端&#xff0c;将采集的传感器数据实时传输到设备…

2048. 下一个更大的数值平衡数;1292. 元素和小于等于阈值的正方形的最大边长;2707. 字符串中的额外字符

2048. 下一个更大的数值平衡数 核心思想&#xff1a;枚举直接从n1开始枚举它是不是平衡数即可。 1292. 元素和小于等于阈值的正方形的最大边长 核心思想:枚举正方形的左上角优化。优化部分有两部分&#xff0c;第一部分是计算面积的优化&#xff0c;预先处理好g&#xff0c;让…

LVS集群 (NET模式搭建)

目录 一、集群概述 一、负载均衡技术类型 二、负载均衡实现方式 二、LVS集群结构 一、三层结构 二、架构对象 三、LVS工作模式 四、LVS负载均衡算法 一、静态负载均衡 二、动态负载均衡 五、ipvsadm命令详解 六、搭建实验流程 一、首先打开三台虚拟机 二、…

SpreadsheetGear 2017 2023 for .NET Crack

SpreadsheetGear 2017 & 2023 for .NET Crack Spreadsheet Gear for.NET被描述为允许用户和开发人员使用iOS、Android、Mac OS、Linux&#xff0c;最后是UWP&#xff0c;以利用可扩展的Excel报告以及与图表API兼容的全面Excel&#xff0c;以及为用户和开发人员提供的最快、…

Rancher证书更新

一、环境 主机名 IP地址 操作系统 rancher版本 K8s-Master 192.168.10.236 Centos 7 2.5.9 二、更新证书 1、查看当前证书到期时间 2、进行证书轮换 [rootK8s-Master ~]# docker ps |grep rancher/rancher d581da2b7c4e rancher/rancher:v2.5.9 …

appium2.0+ 单点触控和多点触控新的解决方案

在 appium2.0 之前&#xff0c;在移动端设备上的触屏操作&#xff0c;单手指触屏和多手指触屏分别是由 TouchAction 类&#xff0c;Multiaction 类实现的。 在 appium2.0 之后&#xff0c;这 2 个方法将会被舍弃。 "[Deprecated] TouchAction action is deprecated. Ple…

【25考研】- 整体规划及高数一起步

【25考研】- 整体规划及高数一起步 一、整体规划二、专业课870计算机应用基础参考网上考研学长学姐&#xff1a; 三、高数一典型题目、易错点及常用结论&#xff08;一&#xff09;典型题目&#xff08;二&#xff09;易错点&#xff08;三&#xff09;常用结论1.arcsinxarccos…

Python爬虫实战案例——第二例

某某美剧剧集下载(从搜索片名开始) 本篇文章主要是为大家提供某些电影网站的较常规的下载电影的分析思路与代码思路(通过爬虫下载电影)&#xff0c;我们会从搜索某部影片的关键字开始直到成功下载某一部电影。 地址&#xff1a;aHR0cHM6Ly93d3cuOTltZWlqdXR0LmNvbS9pbmRleC5od…

为什么选择网络安全?为什么说网络安全是IT行业最后的红利?

一、为什么选择网络安全&#xff1f; 这几年随着我国《国家网络空间安全战略》《网络安全法》《网络安全等级保护2.0》等一系列政策/法规/标准的持续落地&#xff0c;网络安全行业地位、薪资随之水涨船高。 未来3-5年&#xff0c;是安全行业的黄金发展期&#xff0c;提前踏入…

60.每日一练:回文数(力扣)

目录 问题描述 代码解决以及思想 解法&#xff08;一&#xff09; 知识点 解法&#xff08;二&#xff09; 问题描述 代码解决以及思想 解法&#xff08;一&#xff09; class Solution { public:bool isPalindrome(int x) {string arr to_string(x); // 将整数转换为…

IDEA常用插件之代码扫描SonarLint

文章目录 SonarLint 查找隐藏的bug下载安装插件扫描代码查看结果 SonarLint 查找隐藏的bug 下载安装插件 扫描代码 项目右键 -> Analyze -> Analyze with SonarLint 查看结果 扫描完成结果在下面可以直接查看到报告

第2篇:ESP32 helloword第一个程序示范点亮板载LED

1.选择ESP32开发板 2.寻找串口号&#xff0c;win10自动安装驱动 手动安装驱动参考&#xff1a; 百度网盘 请输入提取码百度网盘为您提供文件的网络备份、同步和分享服务。空间大、速度快、安全稳固&#xff0c;支持教育网加速&#xff0c;支持手机端。注册使用百度网盘即可…

typora

图像 偏好设置 图床 picgosmms图床 YAML typora-copy-images-to: upload 在将文件复制到本地文件夹后&#xff0c;再上传 Typora_PicGo_SMMS图床配置 第一步 在偏好设置-图像中 1.设置为上传图片 2.下载picogo并设置路径 第二步 获取https://sm.ms/home/apitoken的a…

Django会话技术

文章目录 Cookie实践运行结果 CSRF防止CSRF Session实践 Cookie 理论上&#xff0c;一个用户的所有请求燥作都应该属于同一个会话&#xff0c;而另一个用户的所有请求操作则应该属于另一个会话&#xff0c;二者不能混淆&#xff0c;而web应用程序是使用HTTP协议传输数据的。HTT…