vue3 videojs实现播放器,动态更改src

news2024/9/26 3:23:07

一、背景

vue3下载第三方插件videojs,达到播放器的效果,并且点击事件能够动态更改播放器的src。实现思路:

  1. 场景一:只有一个播放器,当点击事件,直接赋值,动态更改封装好的组件的src参数,能够实现切换播放器的效果。
  2. 场景二:不止有一个窗口,而是多窗口,要选中多个窗口中的一个窗口,然后点击,达到动态切换选中播放器的src。

二、实现总结

1.vue框架更改对应数据data,对应的视图view变化。

2.在封装的组件监听传参src的变化,如果点击的 src和之前的不同,进行切换资源,播放器重新加载播放;

3.播放器的资源source的参数有src+type,注意type可以不设置。

推荐用法:不设置type,如果要设置一定要更传过来的视频流的数据格式保持一致,否则会爆红

三、效果展示

四、完整代码 

(一)、封装组件 

 组件封装,videojs封装成一个组件:

完整代码:

<script setup lang="ts">
import { computed, CSSProperties, onMounted, ref, watch } from 'vue'
import videojs from 'video.js'
import type { VideoJsPlayerOptions } from 'video.js'
import 'video.js/dist/video-js.min.css'
type MyVideoProps = {
  /** 视频地址 */
  src: string
  width?: string
  height?: string
}
const props = withDefaults(defineProps<MyVideoProps>(), {})
// video标签
const videoRef = ref<HTMLElement | null>(null)
// video实例对象
let videoPlayer: videojs.Player | null = null
const videoWrapStyles = computed<CSSProperties>(() => {
  return {
    width: props.width || '100%',
    height: props.height || '100%'
  }
})
// 初始化videojs
const initVideo = () => {
  // https://gitcode.gitcode.host/docs-cn/video.js-docs-cn/docs/guides/options.html
  const options: VideoJsPlayerOptions = {
    language: 'zh-CN', // 设置语言
    controls: true, // 是否显示控制条
    preload: 'auto', // 预加载
    autoplay: true, // 是否自动播放
    fluid: false, // 自适应宽高
    src: props.src, // 要嵌入的视频源的源 URL
    objectFit: 'cover', // 同css object-fit,作用于video标签
    notSupportedMessage: 'Ajiang此视频暂无法播放,请稍后再试' //允许覆盖Video.js无法播放媒体源时显示的默认信息。
  }
  if (videoRef.value) {
    // 创建 video 实例
    videoPlayer = videojs(videoRef.value, options, onPlayerReady)
  }
}
// video初始化完成的回调函数
const onPlayerReady = () => { }
onMounted(() => {
  initVideo()
})
watch(() => props.src, (now) => {
  if (now) {
    videoPlayer.pause()
    // videoPlayer.dispose()
    videoPlayer.reset()
    setTimeout(() => {
      videoPlayer.src([
        {
          src: props.src,
          // type: "application/x-mpegURL"  //type可以不写,一旦写了一定要符合否则报错
        }
      ])
      videoPlayer.load()
      videoPlayer.play()
    }, 10)
  }
})
</script>
<template>
  <div :style="videoWrapStyles">
    <video id="my-player" ref="videoRef" class="video-js w-full h-full">
      <source :src="src" />
    </video>
  </div>
</template>
<style lang="less" scoped>
.w-full {
  width: 100%;
}

.h-full {
  height: 100%;
}
</style>

(二)、局部引入 

 页面引入,引入封装的组件:

完整代码:

<template>
    <div class="home_box">
        <div class="leftBox">
            <div class="top_nav">
                <div v-for="(item, index) in topnav" :key="index" :class="item.class_name" @click="toOtherModel(item.path)">
                    {{ item.name }}
                </div>
            </div>
            <div class="videoBox">
                <div :class="data.cruentIndex == 0 ? 'playerBox1' :
                    data.cruentIndex == 1 ? 'playerBox2' :
                        data.cruentIndex == 2 ? 'playerBox3' : ''
                    ">
                    <template v-if="data.cruentIndex == 0 && data.videoUrlData">
                        <div class="myVedioBox">
                            <Vediojs :src="data.videoUrlData[0].url" width="100%" height="78vh" />
                        </div>
                    </template>
                    <template v-if="data.cruentIndex == 1">
                        <div class="myVedioBox" v-for="(item, index) in fourBoxData[1].controlTypy" :id="'player_' + index"
                            :key="index" @click="changePlayer(index)">
                            <Vediojs :src="data.videoUrlData[index]?.url" />
                        </div>
                    </template>
                    <template v-if="data.cruentIndex == 2">
                        <div class="myVedioBox" v-for="(item, index) in fourBoxData[2].controlTypy" :id="'player_' + index"
                            :key="index" @click="changePlayer(index)">
                            <Vediojs :src="data.videoUrlData[index]?.url" />
                        </div>
                    </template>
                </div>
                <div :class="data.cruentIndex == 3 ? 'playerBox4' : ''" v-show="data.isCloseed == true">
                    <template v-if="data.cruentIndex == 3">
                        <div class="myVedioBox" v-for="(item, index) in fourBoxData[3].controlTypy" :key="index">
                            <Vediojs :src="data.videoUrlData[index].url" width="100%" height="88vh" />
                            <div class="closeBox" @click="handleCloseBtn">关闭</div>
                        </div>
                    </template>
                </div>
            </div>
        </div>
        <div class="rightBox">
            <div class="rightTitleBox">
                <img :src="getAssetsFile('pmsHome/title_icon.png')" alt="一张图" />
                <span>选择窗口</span>
            </div>
            <div class="fourBox">
                <div class="fourInnerBox" v-for="(item, index) in fourBoxData" @click="handleImageIcon(index)">
                    <img :src="getAssetsFile(data.cruentIndex == index ? item.activeImgUrl : item.imgUrl)" alt="一张图">
                </div>
            </div>
            <div class="rightTitleBox">
                <img :src="getAssetsFile('pmsHome/title_icon.png')" alt="一张图" />
                <span>监控列表</span>
            </div>
            <div class="rightTreeBox">
                <div class="treeInnerBox">
                    <el-tree ref="treeRef" node-key="myTreeKey" :data="treeData" :props="treeDefaultProps"
                        @node-click="handleNodeClick" :current-node-key='4' default-expand-all :highlight-current="true" />
                </div>
            </div>
        </div>
    </div>
</template>
<script setup>
import { nextTick, onMounted, reactive, ref, watch } from "vue";
import { useRouter } from "vue-router";
import { getAssetsFile } from '@/utils'
import Vediojs from "./common/Vediojs.vue";
import 'video.js/dist/video-js.min.css'
const router = useRouter();
const treeRef = ref()
const treeDefaultProps = {
    children: 'children',
    label: 'label',
    id: 'myTreeKey',
    url: 'url'
}
onMounted(() => {

})
const topnav = reactive([
    {
        name: "360゜全景影像",
        class_name: "panoramicImage_title",
        path: "panoramicImage"
    },
    {
        name: "综合感知",
        class_name: "comprehensivePerception_title",
        path: "comprehensivePerception"
    },
]);
const data = reactive({
    cruentIndex: 0,
    videoUrlData: [
        {
            id: '1',
            label: '常规监控',
            url: 'https://media.w3.org/2010/05/sintel/trailer.mp4',
        },
        {
            id: '2',
            label: '常规监控2',
            url: 'http://vjs.zencdn.net/v/oceans.mp4',
        },
        {
            id: '3',
            label: '常规监控',
            url: 'https://media.w3.org/2010/05/sintel/trailer.mp4',
        },
        {
            id: '4',
            label: '常规监控',
            url: 'https://media.w3.org/2010/05/sintel/trailer.mp4',
        },
        {
            id: '5',
            label: '常规监控',
            url: 'https://media.w3.org/2010/05/sintel/trailer.mp4',
        },
        {
            id: '6',
            label: '常规监控2',
            url: 'http://vjs.zencdn.net/v/oceans.mp4',
        },
        {
            id: '7',
            label: '常规监控',
            url: 'https://media.w3.org/2010/05/sintel/trailer.mp4',
        },
        {
            id: '8',
            label: '常规监控',
            url: 'https://media.w3.org/2010/05/sintel/trailer.mp4',
        },
        {
            id: '9',
            label: '常规监控',
            url: 'https://media.w3.org/2010/05/sintel/trailer.mp4',
        },
    ],
    isCloseed: false,
})
const fourBoxData = reactive([
    {
        imgUrl: 'intelligentNavigation/rightIcon/icon1.png',
        activeImgUrl: 'intelligentNavigation/rightIcon/icon1_isChecked.png',
        controlTypy: 1,
    },
    {
        imgUrl: 'intelligentNavigation/rightIcon/icon2.png',
        activeImgUrl: 'intelligentNavigation/rightIcon/icon2_isChecked.png',
        controlTypy: 4,
    },
    {
        imgUrl: 'intelligentNavigation/rightIcon/icon3.png',
        activeImgUrl: 'intelligentNavigation/rightIcon/icon3_isChecked.png',
        controlTypy: 9,
    },
    {
        imgUrl: 'intelligentNavigation/rightIcon/icon4.png',
        activeImgUrl: 'intelligentNavigation/rightIcon/icon3_isChecked.png',
        controlTypy: 1,
    },
])
const treeData = [
    {
        id: '1',
        label: '常规监控',
        url: '#',
        children: [
            {
                id: '2',
                label: '监控器1',
                url: 'https://media.w3.org/2010/05/sintel/trailer.mp4',
            },
            {
                id: '3',
                label: '监控器2',
                url: 'http://vjs.zencdn.net/v/oceans.mp4',
            },
            {
                id: '4',
                label: '监控器3',
                url: 'https://media.w3.org/2010/05/sintel/trailer.mp4',
            },
            {
                id: '5',
                label: '监控器4',
                url: 'http://vjs.zencdn.net/v/oceans.mp4',
            },
            {
                id: '6',
                label: '监控器集群',
                children: [
                    {
                        id: '8',
                        label: '监控器5',
                        url: 'https://media.w3.org/2010/05/sintel/trailer.mp4',
                    },
                    {
                        id: '9',
                        label: '监控器6',
                        url: 'http://vjs.zencdn.net/v/oceans.mp4',
                    },
                    {
                        id: '10',
                        label: '监控器7',
                        url: 'https://media.w3.org/2010/05/sintel/trailer.mp4',
                    },
                ],
            },
            {
                id: '7',
                label: '监控器集群二',
                url: '#',
                children: [
                    {
                        id: '11',
                        label: '监控器1',
                        url: 'http://vjs.zencdn.net/v/oceans.mp4',
                    },
                    {
                        id: '12',
                        label: '监控器2',
                        url: 'https://media.w3.org/2010/05/sintel/trailer.mp4',
                    },
                    {
                        id: '13',
                        label: '监控器3',
                        url: 'http://vjs.zencdn.net/v/oceans.mp4',
                    },
                ],
            },
        ],
    },
]
const changePlayer = (id) => {
    console.log('ddd>>>', id, typeof id);
    //2.如何获取到多个播放器中的一个?
    data.currentPlayerId = id
}

const toOtherModel = (path) => {
    router.push({ name: path });
}

const handleNodeClick = (treeNode, node) => {
    if (node.level !== 1) {
        defaultHighlight(treeNode.myTreeKey)
        if (data.cruentIndex !== 0) {
            data.videoUrlData[data.currentPlayerId].url = treeNode.url
        } else {
            data.videoUrlData[0].url = treeNode.url
        }
    } else {
        console.log('高亮在根元素>>>');
    }
}
const handleImageIcon = (value) => {
    data.cruentIndex = value
    if (value == 3) {
        data.isCloseed = !data.isCloseed
    }
}
const defaultHighlight = (param) => {
    nextTick(() => {
        treeRef.value.setCurrentKey(param)  //树状图选中效果
    })
}
const handleCloseBtn = () => {
    data.isCloseed = !data.isCloseed
    data.cruentIndex = 0
}
</script>
<style scoped lang='less'>
.home_box {
    width: 100%;
    height: 88vh;
    display: flex;
    position: relative;

    .leftBox {
        width: 80%;
        height: 100%;
        margin-right: 1%;
        display: flex;
        flex-direction: column;

        .top_nav {
            width: 100%;
            height: 6%;
            margin-bottom: 12px;
            color: rgba(106, 151, 218, 1);
            font-weight: bold;
            font-size: calc(100vw * 22 / 1920);
            display: flex;

            >div {
                height: 46px;
                margin-right: 30px;
                text-align: center;
                line-height: 43px;
            }

            .panoramicImage_title {
                width: 235px;
                background: url("@/assets/images/intelligentNavigation/panoramicImage_title.png");
                background-size: 100% 100%;
                background-position: center;
            }

            .comprehensivePerception_title {
                width: 185px;
                background: url("@/assets/images/intelligentNavigation/comprehensivePerception_title.png");
                background-size: 100% 100%;
                background-position: center;
            }
        }

        .videoBox {
            width: 100%;
            flex: 1;
            background-color: #EBF1F6;
            border: 1px solid #95DEF7;
            border-radius: 8px;
            display: flex;
            justify-content: center;
            align-items: center;

            .video-player-wrapper {
                width: 100%;
                height: 100%;
                background-color: pink;
                display: flex;
                flex-wrap: wrap;
                justify-content: space-between;

                .video-player-item {
                    width: 500px;
                    height: 300px;
                    background-color: skyblue;
                }
            }


            .playerBox1 {
                width: 98%;
                height: 96%;

                .myvideoBox {
                    width: 100%;
                    height: 100%;
                    display: flex;
                    justify-content: center;
                    align-items: center;

                    img {
                        width: 1400px;
                        height: 700px;
                        object-fit: cover;
                    }
                }
            }

            .playerBox2 {
                width: 98%;
                height: 96%;
                display: flex;
                flex-wrap: wrap;

                .myVedioBox {
                    width: 49%;
                    margin: 0px auto 8px auto;

                    img {
                        width: 100%;
                        height: 100%;
                        object-fit: cover;
                    }
                }
            }

            .playerBox3 {
                width: 98%;
                height: 96%;
                display: flex;
                flex-wrap: wrap;

                .myVedioBox {
                    width: 33%;
                    margin: 0px auto 7px auto;

                    img {
                        width: 100%;
                        height: 100%;
                        object-fit: cover;
                    }
                }
            }

            .playerBox4 {
                width: 100%;
                height: 100%;
                position: absolute;
                top: 0px;
                left: 0px;
                z-index: 2;

                .myVedioBox {
                    .closeBox {
                        width: 40px;
                        height: 40px;
                        line-height: 40px;
                        border: 1px solid #fff;
                        border-radius: 50%;
                        color: #4279CA;
                        font-weight: 600;
                        background-color: #fff;
                        position: absolute;
                        top: 10px;
                        right: 20px;
                        z-index: 3;

                        &:hover {
                            border: 1px solid #4279CA;
                            color: #fff;
                            background-color: #4279CA;
                            cursor: pointer;
                        }
                    }
                }
            }
        }
    }

    .rightBox {
        flex: 1;
        display: flex;
        flex-direction: column;

        .rightTitleBox {
            width: 100%;
            height: 46px;
            background: url('@/assets/images/intelligentNavigation/rightTitle_bg_long.png');
            background-size: 100% 100%;
            margin-bottom: 12px;
            font-size: calc(100vw * 24 / 1920);
            color: #4279CA;
            font-weight: bold;
            display: flex;
            justify-content: flex-start;
            align-items: center;

            img {
                width: 27px;
                height: 27px;
                margin: 8px 11px 8px 18px;
            }
        }

        .fourBox {
            width: 100%;
            height: 64px;
            background-color: #EBF0F5;
            border: 3px solid #fff;
            border-radius: 4px;
            margin-bottom: 16px;
            display: flex;
            justify-content: space-around;
            align-items: center;
            box-sizing: border-box;

            .fourInnerBox {
                width: 40px;
                height: 40px;
                display: flex;
                justify-content: center;
                align-items: center;

                img {
                    width: 40px;
                    height: 40px;
                    object-fit: cover;
                }
            }
        }

        .rightTreeBox {
            width: 100%;
            flex: 1;
            padding-left: 16px;
            background-color: #EBF1F6;
            border: 3px solid #fff;
            border-radius: 4px;
            box-sizing: border-box;

            .treeInnerBox {
                width: 100%;
                height: 100%;

                :deep(.el-tree) {
                    background-color: #EBF0F5;
                }
            }
        }

    }
}
</style>
<style lang='less'>
@import "@/assets/css/reset.less";
</style>

五、核心代码

 封装组件的监听watch:

watch(() => props.src, (now) => {
  if (now) {
    videoPlayer.pause()
    // videoPlayer.dispose()
    videoPlayer.reset()
    setTimeout(() => {
      videoPlayer.src([
        {
          src: props.src,
          // type: "application/x-mpegURL"  //type可以不写,一旦写了一定要符合否则报错
        }
      ])
      videoPlayer.load()
      videoPlayer.play()
    }, 10)
  }
})

局部引入的点击事件:

const changePlayer = (id) => {
    console.log('ddd>>>', id, typeof id);
    //2.如何获取到多个播放器中的一个?
    data.currentPlayerId = id
}


const handleNodeClick = (treeNode, node) => {
    if (node.level !== 1) {
        if (data.cruentIndex !== 0) {
            data.videoUrlData[data.currentPlayerId].url = treeNode.url   //变data,变视频
        } else {
            data.videoUrlData[0].url = treeNode.url
        }
    } else {
        console.log('高亮在根元素>>>');
    }
}

 

 

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

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

相关文章

【AI】如何用AI生成XMind思维导图

哈喽&#xff0c;大家好&#xff0c;我是木头左&#xff0c;物联网搬砖工一名&#xff0c;致力于为大家淘出更多好用的AI工具&#xff01; 背景 随着人工智能技术的不断发展&#xff0c;越来越多的应用场景开始涉及到AI技术。在办公软件领域&#xff0c;XMind是一款非常受欢迎…

阿里云服务区ECS,申请免费的服务器之后,如何使用xshell 登陆,找不到匹配的host key 算法

目录 1 问题2 解决 1 问题 当在阿里云免费领取服务器之后&#xff0c;使用xshell 登陆不上&#xff0c;提示 找不到匹配的host key 算法 或者 找不到匹配的keyexchange算法 咋解决 2 解决 在在服务器端配置文件&#xff1a;/etc/ssh/sshd_config # 在行尾增加",ecdh…

Linux系统编程:通过System V共享内存实现进程间通信

目录 一. 共享内存实现进程间通信的原理 二. 共享内存相关函数 2.1 共享内存的获取 shmget / ftok 2.2 共享内存与进程地址空间相关联 shmat 2.3 取消共享内存与进程地址空间的关联 shmdt 2.4 删除共享内存 shmctl 2.5 通信双方创建共享内存代码 三. 共享内存实现进程间…

基于java/springboot的考研学习平台

摘 要 本毕业设计的内容是设计并且实现一个考研学习平台。它是在Windows下&#xff0c;以MYSQL为数据库开发平台&#xff0c;Tomcat网络信息服务作为应用服务器。考研学习平台的功能已基本实现&#xff0c;主要包括学生、教师、课程信息、学习资源、课程购买、课程发货、课程…

【Spring Boot】构建RESTful服务 — 实战:实现Web API版本控制

实战&#xff1a;实现Web API版本控制 前面介绍了Spring Boot如何构建RESTful风格的Web应用接口以及使用Swagger生成API的接口文档。如果业务需求变更&#xff0c;Web API功能发生变化时应该如何处理呢&#xff1f;可以通过Web API的版本控制来处理。 1.为什么进行版本控制 …

「天锐绿盾」——企业电脑文件加密防泄密软件

随着信息技术的快速发展&#xff0c;公司的日常运营和商业机密都依赖于电脑文件。然而&#xff0c;黑客攻击、员工疏忽或物理丢失等原因都可能导致公司电脑文件泄露&#xff0c;给公司带来巨大的经济损失和声誉损失。因此&#xff0c;公司需要采取有效的措施来保护电脑文件的安…

因数据泄露被罚80万!高校数据安全合规建设如何开展?

8月16日&#xff0c;“南昌网警巡查执法”官方公号披露了一起高校数据泄露事件。 根据通报&#xff0c;南昌某高校3万余条师生个人信息数据在境外互联网上被公开售卖。南昌公安网安部门即刻开展一案双查&#xff0c;抓获犯罪嫌疑人3名&#xff0c;并对涉案高校不履行数据安全保…

游戏IP如何变身数字人?数字人绑定技术了解下

随着数字人的概念大火&#xff0c;各行各业纷纷推出专属的数字人&#xff0c;游戏《王者荣耀》作为国内最大的手游IP&#xff0c;凭借其自有资源角色IP的优势&#xff0c;推出了数字人“上官婉儿”&#xff0c;在晚会上携手真人跨次元演绎歌曲&#xff0c;在动作和舞蹈过程中由…

打造专属照片分享平台:快速上手Piwigo网页搭建

文章目录 通过cpolar分享本地电脑上有趣的照片&#xff1a;部署piwigo网页前言1.Piwigo2. 使用phpstudy网页运行3. 创建网站4. 开始安装Piwogo 总结 &#x1f340;小结&#x1f340; &#x1f389;博客主页&#xff1a;小智_x0___0x_ &#x1f389;欢迎关注&#xff1a;&#x…

性能分析之MySQL慢查询日志分析

一、背景 MySQL的慢查询日志是MySQL提供的一种日志记录,他用来记录在MySQL中响应的时间超过阈值的语句,具体指运行时间超过long_query_time(默认是10秒)值的SQL,会被记录到慢查询日志中。 慢查询日志一般用于性能分析时开启,收集慢SQL然后通过explain进行全面分析,一…

视频集中存储/云存储/安防监控/视频汇聚平台EasyCVR新增角色权限功能分配

视频集中存储/云存储/安防视频监控/视频汇聚平台EasyCVR可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及支持厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等。 EasyCVR视频集中…

解构软件开发中的破窗效应

目录 一、前言 二、解构破窗效应 三、如何解构&#xff1f; 一、前言 “一个房子如果窗户破了&#xff0c;没有人去修补&#xff0c;隔不久&#xff0c;其它的窗户也会莫名其妙地被人打破&#xff1b;一面墙&#xff0c;如果出现一些涂鸦没有被清洗掉&#xff0c;很快的&#x…

dll调用nodejs的回调函数

nodejs使用ffi调用dll。dll中有回调函数调用js中的方法。 c语言中cdll.h文件 extern "C" {typedef void(*JsCall)(int index); //这个就是要传入的类型结构extern __declspec(dllimport) int Add(int a, int b);extern __declspec(dllexport) void CallBackTest(Js…

【内网穿透】如何实现在外web浏览器远程访问jupyter notebook服务器

文章目录 前言1. Python环境安装2. Jupyter 安装3. 启动Jupyter Notebook4. 远程访问4.1 安装配置cpolar内网穿透4.2 创建隧道映射本地端口 5. 固定公网地址 前言 Jupyter Notebook&#xff0c;它是一个交互式的数据科学和计算环境&#xff0c;支持多种编程语言&#xff0c;如…

Python系统学习1-9-类一之类语法

一、类之初印象 1、类就是空表格&#xff0c;将变量&#xff08;列名&#xff09;和函数&#xff08;行为&#xff09;结合起来 2、创建对象&#xff0c;表达具体行 3、创建类就是创建数据的模板 --操作数据时有提示 --还能再组合数据的行为 --结构更加清晰 4、类的内存分配…

为什么我建议机械专业的同学转行嵌入式

最近&#xff0c;我身边有不少机械专业找我&#xff0c;他们对未来的就业形势相当苦恼&#xff0c;觉得自己之后只能进厂打螺丝了。但是我跟他们说&#xff0c;在这个选择比努力重要的时代&#xff0c;只要入对行&#xff0c;谁都可以一飞冲天。 对于学机械的同学&#xff0c;…

mysql 8.0安装

操作系统&#xff1a;22.04.1-Ubuntu apt 安装命令 sudo apt install mysql-client-core-8.0 sudo apt install mysql-server-8.0终端输入 mysql 可以直接免密登录 如果此时提示需要密码&#xff0c;则可以进入配置文件&#xff0c;设置免密登录 sudo vim /etc/mysql/mysq…

Python爬虫性能优化:多进程协程提速实践指南

目录 1. 多进程爬虫的实现&#xff1a; 1.1 将爬虫任务划分成多个子任务&#xff1a; 1.2 创建进程池&#xff1a; 1.3 执行任务&#xff1a; 1.4 处理结果&#xff1a; 代码示例 2. 协程爬虫的实现&#xff1a; 2.1 定义异步爬虫函数&#xff1a; 2.2 创建事件循环&a…

小程序分包流程

目录 问题&#xff1a;小程序为什么要分包&#xff1f; 一、常见的分包形式 二、常规分包 概念&#xff1a; 1.操作位置 2.特点 3.分包使用 1.主包结构不变&#xff0c;但是要把分包过的页面移除 2.分几个包就声明几个 3.主结构展示 注意&#xff1a;分包之后当进行页…

GD32F207 位带操作 GPIO

下面的程序用在GD32F207上测试成功&#xff0c; 如果要在新的单片机上进行位带操作需要查看新的单片机的寄存器偏移量。 #define BITBAND(addr, bitnum) ((addr & 0xF0000000)0x2000000((addr &0xFFFFF)<<5)(bitnum<<2)) #define MEM_ADDR(addr) *((vol…