Vue3 实用的开发技巧

news2024/12/29 1:55:19

一、前言

Vue3已经发布很长时候了,官方也将默认版本切换到了vue3,Vue官网也发布了完善的中文文档,不知同志们是否已经开始使用了了呢?下面给大家介绍一些在开发中Vue3实用的开发技巧,让大家开发更加流畅。

二、开发技巧

1. 善用Composition API抽离通用逻辑

众所周知,vue3最大的新特性,当属Composition API 也叫组合api ,用好了它,在开发中可以去掉许多重复的逻辑代码,提高开发效率。

什么是Composition API

Vue2使用的是Options API,即选项api,使用 (datacomputedmethodswatch) 组件选项来组织逻辑通常都很有效。但是当我们的组件开始变得更大时,逻辑关注点的列表也会增长。尤其对于那些一开始没有编写这些组件的人来说,这会导致组件难以阅读和理解。

于是在vue3中为了解决当前痛点,避免在大型项目中出现代码逻辑分散,散落在当前组件的各个角落,从而变得难以维护,Composition API横空出世。

所谓Composition API就是在组件配置对象中声明 setup函数,我们可以将所有的逻辑封装在setup函数中,然后在配合vue3中提供的响应式API钩子函数、计算属性API等,我们就能达到和常规的选项式同样的效果,但是却拥有更清晰的代码以及逻辑层面的复用。

基础使用

<template>
    <div ref="composition">测试compositionApi</div>
</template>
<script>
import { inject, ref, onMounted, computed, watch } from "vue";
export default {
    // setup起手
    setup(props, { attrs, emit, slots, expose }) {
 
        // 获取页面元素
        const composition = ref(null)
        // 依赖注入
        const count = inject('foo', '1')
        // 响应式结合
        const num = ref(0)
        //钩子函数
        onMounted(() => {
            console.log('这是个钩子')
        })
        // 计算属性
        computed(() => num.value + 1)
        // 监听值的变化
        watch(count, (count, prevCount) => {
            console.log('这个值变了')
        })
        return {
            num,
            count
        }
 
    }
}
</script>

通过以上代码我们可以看出,一个setup函数我们干出了在传统选项式中的所有事情。通过这些api的组合可以实现逻辑复用,这样我们就能封装很多通用逻辑,实现复用,大大提高开发效率。

举个例子:大家都用过复制剪贴板的功能,在通常情况下,利用navigator.clipboard.writeText 方法就能将复制内容写入剪切板。然而,细心的你会发现,其实赋值剪切板他是一个通用功能,比如:你做b端业务的,管理系统中到处充满了复制id、复制文案等功能。

于是我们就可以使用Composition API的将剪贴板功能的逻辑提取封装一个功能函数,实现复用。

import { watch, getCurrentScope, onScopeDispose, unref, ref } from "vue"
export const isString = (val) => typeof val === 'string'
export const noop = () => { }
export function unrefElement(elRef) {
    const plain = unref(elRef)// 拿到本来的值
    return (plain).$el ?? plain //前面的值为null、undefined,则取后面的值,否则都取前面的值
}
export function tryOnScopeDispose(fn) {
    // 如果有活跃的effect
    if (getCurrentScope()) {
        //在当前活跃的 effect 作用域上注册一个处理回调。该回调会在相关的 effect 作用域结束之后被调用
        //能代替onUmounted
        onScopeDispose(fn)
        return true
    }
    return false
}
//带有控件的setTimeout包装器。
export function useTimeoutFn(
    cb,// 回调
    interval,// 时间
    options = {},
) {
    const {
        immediate = true,
    } = options
 
    const isPending = ref(false)
 
    let timer
 
    function clear() {
        if (timer) {
            clearTimeout(timer)
            timer = null
        }
    }
 
    function stop() {
        isPending.value = false
        clear()
    }
 
    function start(...args) {
        // 清除上一次定时器
        clear()
        // 是否在pending 状态
        isPending.value = true
        // 重新启动定时器
        timer = setTimeout(() => {
            // 当定时器执行的时候结束pending状态
            isPending.value = false
            // 初始化定时器的id
            timer = null
            // 执行回调
            cb(...args)
        }, unref(interval))
    }
    if (immediate) {
        isPending.value = true
 
        start()
    }
 
    tryOnScopeDispose(stop)
 
    return {
        isPending,
        start,
        stop,
    }
}
//轻松使用EventListener。安装时使用addEventListener注册,卸载时自动移除EventListener。
export function useEventListener(...args) {
    let target
    let event
    let listener
    let options
    // 如果第一个参数是否是字符串
    if (isString(args[0])) {
        //结构内容
        [event, listener, options] = args
        target = window
    }
    else {
        [target, event, listener, options] = args
    }
    let cleanup = noop
    const stopWatch = watch(
        () => unrefElement(target),// 监听dom
        (el) => {
            cleanup() // 执行默认函数
            if (!el)
                return
            // 绑定事件el如果没有传入就绑定为window
            el.addEventListener(event, listener, options)
            // 重写函数方便改变的时候卸载
            cleanup = () => {
                el.removeEventListener(event, listener, options)
                cleanup = noop
            }
        },
        //flush: 'post' 模板引用侦听
        { immediate: true, flush: 'post' },
    )
    // 卸载
    const stop = () => {
        stopWatch()
        cleanup()
    }
 
    tryOnScopeDispose(stop)
 
    return stop
}
 
export function useClipboard(options = {}) {
    //获取配置
    const {
        navigator = window.navigator,
        read = false,
        source,
        copiedDuring = 1500,
    } = options
    //事件类型
    const events = ['copy', 'cut']
    // 判断当前浏览器知否支持clipboard
    const isSupported = Boolean(navigator && 'clipboard' in navigator)
    // 导出的text
    const text = ref('')
    //导出的copied
    const copied = ref(false)
    // 使用的的定时器钩子
    const timeout = useTimeoutFn(() => copied.value = false, copiedDuring)
 
    function updateText() {
        //解析系统剪贴板的文本内容返回一个Promise
        navigator.clipboard.readText().then((value) => {
            text.value = value
        })
    }
 
    if (isSupported && read) {
        // 绑定事件
        for (const event of events)
            useEventListener(event, updateText)
    }
    // 复制剪切板方法
    //navigator.clipboard.writeText 方法是异步的返回一个promise
    async function copy(value = unref(source)) {
        if (isSupported && value != null) {
            await navigator.clipboard.writeText(value)
            // 响应式的值,方便外部能动态获取
            text.value = value
            copied.value = true
            timeout.start()// copied.value = false 
        }
    }
 
    return {
        isSupported,
        text,
        copied,
        copy,
    }
}

这时我们就复用了复制的逻辑,如下代码中直接引入在模板中使用即可

<template>
    <div v-if="isSupported">
        <p>
            <code>{{ text || '空' }}</code>
        </p>
        <input v-model="input" type="text" />
        <button @click="copy(input)">
            <span v-if="!copied">复制</span>
            <span v-else>复制中!</span>
        </button>
    </div>
    <p v-else>您的浏览器不支持剪贴板API</p>
</template>
<script setup>
import { ref, getCurrentScope } from 'vue'
import { useClipboard } from './copy.js'
const input = ref('')
const { text, isSupported, copied, copy } = useClipboard()
console.log(text)// 复制内容
console.log(isSupported)// 是否支持复制剪切板api 
console.log(copied)//是否复制完成延迟
console.log(copy) // 复制方法
</script>

以上代码参考vue版本的Composition API库所有完整版请参考

2. 善用<script setup>

<script setup> 是在单文件组件 (SFC) 中使 的编译时语法糖。相比于普通的 <script> 语法,它具有更多优势:

  • 更少的样板内容,更简洁的代码;
  • 能够使用纯 Typescript 声明 props 和抛出事件;
  • 更好的运行时性能 (其模板会被编译成与其同一作用域的渲染函数,没有任何的中间代理);
  • 更好的 IDE 类型推断性能 (减少语言服务器从代码中抽离类型的工作)。

3. 善用h(createVNode)和render 函数

我们知道在vue3中导出了一个 createVNode 函数,它能创建一个vdom,大家不要小看vdom, 我们好好利用它,就能做出意想不到的效果。比如我们要实现一个弹窗组件。

我们通常的思路是写一个组件在项目中引用进来,通过v-model来控制他的显示隐藏,但是这样有个问题,我们复用的时候的成本需要复制粘贴。我们没有办法来提高效率,比如封装成 npm 通过调用js来使用。

然而,有了 createVNode 和 render 之后所有问题就迎刃而解了。

// 我们先写一个弹窗组件
const message = {
      setup() {
        const num = ref(1)
           return {
              num
           }
      },
      template: `<div>
                      <div>{{num}}</div>
                      <div>这是一个弹窗</div>
                 </div>`
}
// 初始化组件生成vdom
const vm = createVNode(message)
// 创建容器,也可以用已经存在的
const container = document.createElement('div')
//render通过patch 变成dom
render(vm, container)
// 弹窗挂到任何你想去的地方  
document.body.appendChild(container.firstElementChild)

我们可以将它封装为一个方法,放到任何想放的地方。

4. 善用JSX/TSX

官方文档上说了,在绝大多数情况下,Vue 推荐使用模板语法来搭建 HTML。然而在某些使用场景下,我们真的需要用到 JavaScript 完全的编程能力。这时渲染函数就派上用场了。

jsx和模板语法的优势对比

jsx和模板语法都是vue 支持的的书写范畴,然后他们确有不同的使用场景和方式,需要我们根据当前组件的实际情况来使用

什么是JSX

JSX 是一种 Javascript 的语法扩展,JSX = Javascript + XML,即在 Javascript 里面写 XML,因为 JSX 的这个特性,所以他即具备了 Javascript 的灵活性,同时又兼具html的语义化和直观性。

模板语法的优势

  • 模板语法书写起来不怎么违和,我们就像在写html一样;

  • 在vue3中由于模板的可遍历性,它能在编译阶段做更多优化,比如静态标记、块block、缓存事件处理程序等;

  • 模板代码逻辑代码严格分开,可读性高;

  • 对JS功底不那么好的人,记几个命令就能快速开发,上手简单;

  • vue官方插件的完美支持,代码格式化,语法高亮等。

JSX的优势

  • 灵活;
  • 一个文件能写好多个组件;
  • 只要JS功底好,就不用记忆那么多命令;
  • JS和JSX混用,方法即声明即用,逻辑清晰。

对比

我们知道组件类型,分为容器型组件和展示展示型组件在一般情况下,容器型组件,他由于可能要对于当前展示型组件做一个标准化或者包装,那么此时容器型组件中用JSX就再好不过。

举个例子:现在有个需求,我们有两个按钮,现在要做一个通过后台数据来选择展示哪一个按钮,我们通常的做法,是通过在一个模板中通过v-if去控制不同的组件

然而有了JSX与函数式组件之后,我们发现逻辑更清晰了,代码更简洁了,质量更高了。

两个按钮组件

//btn1.vue
<template>
  <div>
      这是btn1{{ num }}
      <slot></slot>
  </div>
</template>
<script>
import { ref, defineComponent } from 'vue'
export default defineComponent({
  name: 'btn1',
  setup() {
      const num = ref(1)
      return { num }
  }
})
</script>
//btn2.vue
<template>
  <div>
      这是btn2{{ num }}
      <slot></slot>
  </div>
</template>
<script>
import { ref, defineComponent } from 'vue'
export default defineComponent({
  name: 'btn2',
  setup() {
      const num = ref(2)
      return { num }
  }
})
</script>

用JSX配合函数式组件来做一个容器组件

// 容器组件
import btn1 from './btn1.vue'
import btn2 from './btn2.vue'
export const renderFn = function (props, context) {
  return props.type == 1 ? <btn1>{context.slots.default()}</btn1> : <btn2>{context.slots.default()}</btn2>
}

引入业务组件

//业务组件
<template>
 <renderFn :type="1">1111111</renderFn>
</template>
<script>
import { renderFn } from './components'
console.log(renderFn)
export default {
 components: {
   renderFn
 },
 setup() {
 },
};
</script>

5. 善用依赖注入(Provide / Inject)

什么是依赖注入

依赖注入 用大白话来说:就是将实例变量传入到一个对象中去。

vue中的依赖注入

 基本用法

//parent.vue
<template>
    <child @setColor="setColor"></child>
    <button @click="count++">添加</button>
</template>
 
<script >
import { defineComponent, provide, ref } from "vue";
import Child from "./child.vue";
export default defineComponent({
    components: {
        Child
    },
    setup() {
        const count = ref(0);
        const color = ref('#000')
        provide('count', count)
        provide('color', color)
        function setColor(val) {
            color.value = val
        }
        return {
            count,
            setColor
        }
    }
})
</script>

子组件中注入进来

//child.vue
//使用inject 注入
<template>
    <div>这是注入的内容{{ count }}</div>
    <child1 v-bind="$attrs"></child1>
</template>
 
<script>
import { defineComponent, inject } from "vue";
import child1 from './child1.vue'
export default defineComponent({
    components: {
        child1
    },
    setup(props, { attrs }) {
        const count = inject('count');
        console.log(count)
        console.log(attrs)
        return {
            count
        }
    }
})
</script>

因为依赖注入的特性,我们很大程度上代替了全局状态管理,相信谁都不想动不动就引入那繁琐的vuex吧。

接下来我们来举个例子,现在我么有个页面主题色,他贯穿所有组件,并且可以在某一些组件内更改主题色,那我们常规的解决方案中,就是装个vuex然后通过他的api下发颜色值,这时候如果想改,首先要发起dispatch到Action,然后在Action 中触发Mutation接着在Mutation中再去改state,如此一来,你是不是发现有点杀鸡用牛刀了,我就改个颜色而已。

我们来看有了依赖注入应该怎么处理,首先我们知道vue是单项数据流,也就是子组件不能修改父组件的内容,于是我们就应该想到使用 $attrs 使用它将方法透传给祖先组件,在组件组件中修改即可。

//子孙组件child1.vue
<template>
    <div :style="`color:${color}`" @click="setColor">这是注入的内容的颜色</div>
</template>
 
<script>
import { defineComponent, inject } from "vue";
 
export default defineComponent({
    setup(props, { emit }) {
        const color = inject('color');
        function setColor() {
            console.log(0)
            emit('setColor', 'red')
        }
        return {
            color,
            setColor
        }
    }
})
</script>

将当前子孙组件嵌入到child.vue中去,就能利用简洁的方式来修改颜色了。

6. 善用$attrs

$attrs 现在包含了_所有_传递给组件的 attribute,包括 class 和 style

$attrs在我们开发中到底有什么用呢?

通过他,我们可以做组件的事件以及props透传。

首先有一个标准化的组件,一般是组件库的组件等等。

//child.vue
<template>
    <div>这是一个标准化组件</div>
    <input type="text" :value="num" @input="setInput" />
</template>
 
<script>
import { defineComponent } from "vue";
 
export default defineComponent({
    props: ['num'],
    emits: ['edit'],
    setup(props, { emit }) {
        function setInput(val) {
            emit('edit', val.target.value)
        }
        return {
            setInput
        }
    }
})
</script>

接下来有一个包装组件,他对当前的标准化组件做修饰,从而使结果变成我们符合我们的预期的组件

//parent.vue
 <template>
    <div>这一层要做一个单独的包装</div>
    <child v-bind="$attrs" @edit="edit"></child>
</template>
 
<script>
import { defineComponent } from "vue";
import child from './child.vue'
export default defineComponent({
    components: {
        child
    },
    setup(props, { emit }) {
        function edit(val) {
            // 对返回的值做一个包装
            emit('edit', `${val}time`)
        }
        return {
            edit
        }
    }
})
</script>

我们发现当前包装组件中使用了$attrs,通过他透传给标准化组件,这样一来,我们就能对比如element UI中的组件做增强以及包装处理,并且不用改动原组件的逻辑。

7. 优雅注册全局组件技巧

vue3的组件通常情况下使用vue提供的component 方法来完成全局组件的注册。

const app = Vue.createApp({})
 
app.component('component-a', {
  /* ... */
})
app.component('component-b', {
  /* ... */
})
app.component('component-c', {
  /* ... */
})
 
app.mount('#app')

使用时

<div id="app">
  <component-a></component-a>
  <component-b></component-b>
  <component-c></component-c>
</div>

我们发现可能使用注册vue插件的方式,也能完成组件注册,并且是优雅的!

vue插件注册

插件的格式

//plugins/index.js
export default {
  install: (app, options) => {
      // 这是插件的内容
  }
}

插件的使用

import { createApp } from 'vue'
import Plugin from './plugins/index.js'
const app = createApp(Root)
app.use(Plugin)
app.mount('#app')

其实插件的本质,就是在use的方法中调用插件中的install方法,那么这样一来,我们就能在install方法中注册组件。

index.js中抛出一个组件插件

// index.js
import component from './Cmponent.vue'
const component = {
    install:function(Vue){
        Vue.component('component-name',component)
    }  
//'component-name'这就是后面可以使用的组件的名字,install是默认的一个方法 component-name 是自定义的,我们可以按照具体的需求自己定义名字
}
// 导出该组件
export default component

组件注册

// 引入组件
import install from './index.js'; 
// 全局挂载utils
Vue.use(install);

上述案例中,就是一个简单的优雅的组件注册方式,大家可以发现包括element-plus、vant 等组件都是用如此方式注册组件。

8. v-model的最新用法

我们知道在vue2中想要模拟v-model,必须要子组件要接受一个value props 吐出来一个 叫input的emit

然而在vue3中他升级了

父组件中使用v-model

<template>
    <child v-model:title="pageTitle"></child>
</template>
 
<script>
import { defineComponent, ref } from "vue";
import child from './child.vue'
export default defineComponent({
    components: {
        child
    },
    setup(props, { emit }) {
        const pageTitle = ref('这是v-model')
        return {
            pageTitle
        }
    }
})
</script>
 

子组件中使用 title的props 以及规定吐出update:title的emit

<template>
    <div>{{ title }}</div>
    <input type="text" @input="setInput" />
</template>
 
<script>
import { defineComponent } from "vue";
 
export default defineComponent({
    props: ['title'],
    emits: ['update:title'],
    setup(props, { emit }) {
        function setInput(val) {
            emit('update:title', val.target.value)
        }
        return {
            setInput
        }
    }
})
</script>

有了以上语法糖,我们在封装组件的时候,就可以随心所欲了,比如我自己封装可以控制显示隐藏的组件我们就能使用v-model:visible单独控制组件的显示隐藏。使用正常的v-model 控制组件内部的其他逻辑,从而拥有使用更简洁的逻辑,表达相同的功能。

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

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

相关文章

Vue实现leafletMap自定义绘制线段 并且删除指定的已绘制的点位

效果&#xff1a;点击表格可实现选中地图点位&#xff0c;删除按钮点击可删除对应点位并且重新绘制线段&#xff0c;点击确定按钮 保存已经绘制的点位信息传给父组件 并且该组件已实现回显 完整的组件代码如下 文件名称为&#xff1a; leafletMakePointYt <!--* Descripti…

小程序学习(六):全局配置

1.全局配置文件及常用的配置项 全局配置-window 2.小程序窗口的组成部分 3.了解window节点常用的配置项 4.设置导航栏的标题 设置步骤:app.json->window->navigationBarTitleText 5.设置导航栏的背景色 背景颜色不支持red这种文字 6.设置导航栏的标题颜色 注意:navigat…

山西电力市场日前价格预测【2023-08-03】

日前价格预测 预测明日&#xff08;2023-08-03&#xff09;山西电力市场全天平均日前电价为344.46元/MWh。其中&#xff0c;最高日前电价为395.01元/MWh&#xff0c;预计出现在19: 45。最低日前电价为314.42元/MWh&#xff0c;预计出现在03: 15。 价差方向预测 1&#xff1a;实…

CefInitialize初始化

结合代码以及查看exe生成目录的debug.log [0802/160846.105:ERROR:icu_util.cc(133)] Invalid file descriptor to ICU data received. setlocal mt.exe -nologo -manifest "D:/D-Pro/Test/t_Explore/t_Explore/lib/Resources/cefsimple.exe.manifest" "D:/D-P…

第一章 基本的图像操作和处理

文章目录 第一章 基本的图像操作和处理1.1PIL&#xff1a;Python图像处理类库1.1.1转图像格式1.1.2创建缩略图1.1.3复制和粘贴图像区域 1.2Matplotlib1.2.1绘制图像、点、线1.2.2图像轮廓和直方图 1.3NumPy1.3.1图像数组表示1.3.2灰度变换1.3.4直方图均衡化 1.4SciPy1.4.1图像模…

基于Yolov2深度学习网络的车辆检测算法matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 4.1. 卷积神经网络&#xff08;CNN&#xff09; 4.2. YOLOv2 网络 4.3. 实现过程 4.4. 应用领域 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 MATLAB2022A 3.部分核心…

USB技术浅析

一、USB3.0 USB是史上定义出的最成功的PC外围互连技术&#xff0c;并且已经迅猛地被引入到CE和Mobile领域。仅仅在2006年&#xff0c;就有超过20亿USB设备出产&#xff0c;而现在已经有超过60亿的USB产品被安装。 而随着技术创新的不断前进&#xff0c;新式设备&#xff0c;媒…

在线考试系统springboot学生试卷问答管理java jsp源代码mysql

本项目为前几天收费帮学妹做的一个项目&#xff0c;Java EE JSP项目&#xff0c;在工作环境中基本使用不到&#xff0c;但是很多学校把这个当作编程入门的项目来做&#xff0c;故分享出本项目供初学者参考。 一、项目描述 在线考试系统springboot 系统有2权限&#xff1a;管理…

物联网工程开发实施,应该怎么做?

我这里刚好有嵌入式、单片机、plc的资料需要可以私我或在评论区扣个6 物联网工程的概念 物联网工程是研究物联网系统的规划、设计、实施、管理与维护的工程科学&#xff0c;要求物联网工程技术人员根 据既定的目标&#xff0c;依照国家、行业或企业规范&#xff0c;制定物联网…

Linux - 进程地址空间

引入 在学习C语言的时候&#xff0c;内存包括栈区、堆区、静态区 这个布局是内存吗&#xff1f; 不是&#xff01;&#xff01; 这是进程地址空间&#xff01; 下面测试一下&#xff1a; 11540是bash进程 我们修改一下源程序&#xff0c;在观察下结果 发现父进程的g_value的值不…

在terminal里面如何把图片从一个文件夹下面移动到另一个文件夹下面

使用命令行将图片从 /home/meiyi/Downloads/ 文件夹下移动到 Blog/blog/app/assets/images/ 文件夹下&#xff0c;可以按照以下步骤进行&#xff1a; 1. 打开 terminal 并进入 Blog/blog 目录下面 2.将图片移动到 app/assets/images/ 文件夹下面 可以使用mv命令将图片从 /ho…

xlrd与xlwt操作Excel文件详解

Python操作Excel的模块有很多&#xff0c;并且各有优劣&#xff0c;不同模块支持的操作和文件类型也有不同。下面是各个模块的支持情况&#xff1a; .xls.xlsx获取文件内容写入数据修改文件内容保存样式调整插入图片xlrd√√√xlwt√√√√√xlutils√√√√xlwings√√√√√…

虚拟云网络系列 | Antrea 应用于 VMware 方案功能简介(十二)

接续 Antrea 网络系列&#xff0c;接下来我想和大家讨论的是 Antrea 本身的两个网络与定址相关功能&#xff1a;Antrea Egress/Antrea IPAM。但在开始说明这两个机制前&#xff0c;先得讨论在原生 Kubernetes 方案内基础的网络与定址设计&#xff0c;通常在企业环境内会产生什么…

使用docker部署一个jar项目

简介: 通过docker镜像, docker可以在服务器上运行包含项目所需运行环境的docker容器, 在线仓库里有很多各个软件公司官方发布的镜像, 或者第三方的镜像. 如果我们需要使用docker把我们的应用程序打包成镜像, 别的机器上只要安装了docker, 就可以直接运行镜像, 而不需要再安装应…

建网站一般使用Windows还是liunx好?

建网站一般使用Windows还是liunx好&#xff1f; 1&#xff1b;服务器配置比较低时&#xff0c;最好使用linux系统。 对于一个电脑新手&#xff0c;刚开始做网站时&#xff0c;都会选择入门级的服务器&#xff0c;我刚开始做网站时&#xff0c;就是这样的。我购买了一台入门级服…

为什么需要智能工业自动化网络?如何搭建?

在当今快节奏的社会中&#xff0c;工业自动化变得越来越重要。传统的手动操作和生产方式已经不能满足现代工业的需求。因此&#xff0c;建设工业自动化已成为一个必然趋势。通过不断进步的新技术创建更高效、更可靠、更安全的智能工业自动化网络。在本文中&#xff0c;我们将讨…

【转】金融行业JR/T0197-2020《金融数据安全 数据安全分级指南》解读

原文链接&#xff1a;金融行业JR/T0197-2020《金融数据安全 数据安全分级指南》解读 《金融数据安全 数据安全分级指南》 解 读 随着IT技术的发展&#xff0c;银行的基础业务、核心流程等众多事务和活动都运营在信息化基础之上&#xff0c;金融机构运行过程中产生了大量的数字…

SE-Net注意力机制详解

📌本次任务:了解SE-Net原理 SE-Net 是 ImageNet 2017(ImageNet 收官赛)的冠军模型,是由WMW团队发布。具有复杂度低,参数少和计算量小的优点。且SENet 思路很简单,很容易扩展到已有网络结构如 Inception 和 ResNet 中。(这篇论文是2019年的,应该是后续做了更新) 一…

(Acwing)完全背包问题

有 N 种物品和一个容量是 V 的背包&#xff0c;每种物品都有无限件可用。 第 ii 种物品的体积是 vi&#xff0c;价值是 wi。 求解将哪些物品装入背包&#xff0c;可使这些物品的总体积不超过背包容量&#xff0c;且总价值最大。 输出最大价值。 输入格式 第一行两个整数&am…

远程连接身份验证错误,又找不到加密Oracle修正

一、问题描述 远程连接服务器出现了错误&#xff0c;错误信息为&#xff1a;远程连接身份验证错误&#xff0c;又找不到加密Oracle修正。 二、原因分析 出错原因&#xff1a;Windows的CVE-2018-0886 的 CredSSP 更新将CredSSP 身份验证协议默认设置成了“缓解”&#xff0c;…