vue中的keep-alive详解与应用场景

🌈个人主页:前端青山
🔥系列专栏:Vue篇
🔖人终将被年少不可得之物困其一生
依旧青山,本期给大家带来vue篇专栏内容:vue-keep-alive
目录
一、Keep-alive 是什么
二、使用场景
三、原理分析
四、案例实现
activated、deactivated钩子
五、缓存后如何获取数据
beforeRouteEnter
actived
一、Keep-alive 是什么
keep-alive是vue中的内置组件,能在组件切换过程中将状态保留在内存中,防止重复渲染DOM
keep-alive 包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们
keep-alive可以设置以下props属性:
-
include- 字符串或正则表达式。只有名称匹配的组件会被缓存 -
exclude- 字符串或正则表达式。任何名称匹配的组件都不会被缓存 -
max- 数字。最多可以缓存多少组件实例
关于keep-alive的基本用法:
<keep-alive><component :is="view"></component>
</keep-alive>
使用includes和exclude:
<keep-alive include="a,b"><component :is="view"></component>
</keep-alive>
<!-- 正则表达式 (使用 `v-bind`) -->
<keep-alive :include="/a|b/"><component :is="view"></component>
</keep-alive>
<!-- 数组 (使用 `v-bind`) -->
<keep-alive :include="['a', 'b']"><component :is="view"></component>
</keep-alive>
匹配首先检查组件自身的 name 选项,如果 name 选项不可用,则匹配它的局部注册名称 (父组件 components 选项的键值),匿名组件不能被匹配
设置了 keep-alive 缓存的组件,会多出两个生命周期钩子(activated与deactivated):
-
首次进入组件时:
beforeRouteEnter>beforeCreate>created>mounted>activated> ... ... >beforeRouteLeave>deactivated -
再次进入组件时:
beforeRouteEnter>activated> ... ... >beforeRouteLeave>deactivated
二、使用场景
使用原则:当我们在某些场景下不需要让页面重新加载时我们可以使用keepalive
举个栗子:
当我们从首页–>列表页–>商详页–>再返回,这时候列表页应该是需要keep-alive
从首页–>列表页–>商详页–>返回到列表页(需要缓存)–>返回到首页(需要缓存)–>再次进入列表页(不需要缓存),这时候可以按需来控制页面的keep-alive
在路由中设置keepAlive属性判断是否需要缓存
{path: 'list',name: 'itemList', // 列表页component (resolve) {require(['@/pages/item/list'], resolve)},meta: {keepAlive: true,title: '列表页'}
}
使用<keep-alive>
<div id="app" class='wrapper'><keep-alive><!-- 需要缓存的视图组件 --> <router-view v-if="$route.meta.keepAlive"></router-view></keep-alive><!-- 不需要缓存的视图组件 --><router-view v-if="!$route.meta.keepAlive"></router-view>
</div>
三、原理分析
keep-alive是vue中内置的一个组件
export default {name: 'keep-alive',abstract: true,
props: {include: [String, RegExp, Array],exclude: [String, RegExp, Array],max: [String, Number]},
created () {this.cache = Object.create(null)this.keys = []},
destroyed () {for (const key in this.cache) {pruneCacheEntry(this.cache, key, this.keys)}},
mounted () {this.$watch('include', val => {pruneCache(this, name => matches(val, name))})this.$watch('exclude', val => {pruneCache(this, name => !matches(val, name))})},
render() {/* 获取默认插槽中的第一个组件节点 */const slot = this.$slots.defaultconst vnode = getFirstComponentChild(slot)/* 获取该组件节点的componentOptions */const componentOptions = vnode && vnode.componentOptions
if (componentOptions) {/* 获取该组件节点的名称,优先获取组件的name字段,如果name不存在则获取组件的tag */const name = getComponentName(componentOptions)
const { include, exclude } = this/* 如果name不在inlcude中或者存在于exlude中则表示不缓存,直接返回vnode */if ((include && (!name || !matches(include, name))) ||// excluded(exclude && name && matches(exclude, name))) {return vnode}
const { cache, keys } = this/* 获取组件的key值 */const key = vnode.key == null// same constructor may get registered as different local components// so cid alone is not enough (#3269)? componentOptions.Ctor.cid + (componentOptions.tag ? `::${componentOptions.tag}` : ''): vnode.key/* 拿到key值后去this.cache对象中去寻找是否有该值,如果有则表示该组件有缓存,即命中缓存 */if (cache[key]) {vnode.componentInstance = cache[key].componentInstance// make current key freshestremove(keys, key)keys.push(key)}/* 如果没有命中缓存,则将其设置进缓存 */else {cache[key] = vnodekeys.push(key)// prune oldest entry/* 如果配置了max并且缓存的长度超过了this.max,则从缓存中删除第一个 */if (this.max && keys.length > parseInt(this.max)) {pruneCacheEntry(cache, keys[0], keys, this._vnode)}}
vnode.data.keepAlive = true}return vnode || (slot && slot[0])}
}
可以看到该组件没有template,而是用了render,在组件渲染的时候会自动执行render函数
this.cache是一个对象,用来存储需要缓存的组件,它将以如下形式存储:
this.cache = {'key1':'组件1','key2':'组件2',// ...
}
在组件销毁的时候执行pruneCacheEntry函数
function pruneCacheEntry (cache: VNodeCache,key: string,keys: Array<string>,current?: VNode
) {const cached = cache[key]/* 判断当前没有处于被渲染状态的组件,将其销毁*/if (cached && (!current || cached.tag !== current.tag)) {cached.componentInstance.$destroy()}cache[key] = nullremove(keys, key)
}
在mounted钩子函数中观测 include 和 exclude 的变化,如下:
mounted () {this.$watch('include', val => {pruneCache(this, name => matches(val, name))})this.$watch('exclude', val => {pruneCache(this, name => !matches(val, name))})
}
如果include 或exclude 发生了变化,即表示定义需要缓存的组件的规则或者不需要缓存的组件的规则发生了变化,那么就执行pruneCache函数,函数如下:
function pruneCache (keepAliveInstance, filter) {const { cache, keys, _vnode } = keepAliveInstancefor (const key in cache) {const cachedNode = cache[key]if (cachedNode) {const name = getComponentName(cachedNode.componentOptions)if (name && !filter(name)) {pruneCacheEntry(cache, key, keys, _vnode)}}}
}
在该函数内对this.cache对象进行遍历,取出每一项的name值,用其与新的缓存规则进行匹配,如果匹配不上,则表示在新的缓存规则下该组件已经不需要被缓存,则调用pruneCacheEntry函数将其从this.cache对象剔除即可
关于keep-alive的最强大缓存功能是在render函数中实现
首先获取组件的key值:
const key = vnode.key == null?
componentOptions.Ctor.cid + (componentOptions.tag ? `::${componentOptions.tag}` : '')
: vnode.key
拿到key值后去this.cache对象中去寻找是否有该值,如果有则表示该组件有缓存,即命中缓存,如下:
/* 如果命中缓存,则直接从缓存中拿 vnode 的组件实例 */
if (cache[key]) {vnode.componentInstance = cache[key].componentInstance/* 调整该组件key的顺序,将其从原来的地方删掉并重新放在最后一个 */remove(keys, key)keys.push(key)
}
直接从缓存中拿 vnode 的组件实例,此时重新调整该组件key的顺序,将其从原来的地方删掉并重新放在this.keys中最后一个
this.cache对象中没有该key值的情况,如下:
/* 如果没有命中缓存,则将其设置进缓存 */
else {cache[key] = vnodekeys.push(key)/* 如果配置了max并且缓存的长度超过了this.max,则从缓存中删除第一个 */if (this.max && keys.length > parseInt(this.max)) {pruneCacheEntry(cache, keys[0], keys, this._vnode)}
}
表明该组件还没有被缓存过,则以该组件的key为键,组件vnode为值,将其存入this.cache中,并且把key存入this.keys中
此时再判断this.keys中缓存组件的数量是否超过了设置的最大缓存数量值this.max,如果超过了,则把第一个缓存组件删掉
四、案例实现
缓存包裹在其中的动态切换组件
<KeepAlive> 包裹动态组件时,会缓存不活跃的组件实例,而不是销毁它们。
任何时候都只能有一个活跃组件实例作为 <KeepAlive> 的直接子节点。
完整案例:08_dynamic/52_keep-alive.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>动态组件</title>
</head>
<body><div id="app"><ul><li @click="currentTab='Home'">首页</li><li @click="currentTab='Kind'">分类</li><li @click="currentTab='Cart'">购物车</li><li @click="currentTab='User'">我的</li></ul><!-- 动态组件默认切换时 执行的是组件的 销毁 和 重新创建 --><!-- 可以使用 KeepAlive 保留组件的状态,避免组件的重新渲染 --><keep-alive><component :is="currentTab"></component></keep-alive></div>
</body>
<script src="../lib/vue.global.js"></script>
<script>const Home = {template: `<div>首页 <input placeholder="首页"/></div>`,created () { console.log('Home created') },mounted () { console.log('Home mounted') },unmounted () { console.log('Home unmounted') }}const Kind = {template: `<div>分类 <input placeholder="分类"/></div>`,created () { console.log('Kind created') },mounted () { console.log('Kind mounted') },unmounted () { console.log('Kind unmounted') }}const Cart = {template: `<div>购物车 <input placeholder="购物车"/></div>`,created () { console.log('Cart created') },mounted () { console.log('Cart mounted') },unmounted () { console.log('Cart unmounted') }}const User = {template: `<div>我的 <input placeholder="我的"/></div>`,created () { console.log('User created') },mounted () { console.log('User mounted') },unmounted () { console.log('User unmounted') }}
Vue.createApp({data () {return {currentTab: 'Home'}},components: {Home,Kind,Cart,User}}).mount('#app')
</script>
</html>
当一个组件在
<KeepAlive>中被切换时,它的activated和deactivated生命周期钩子将被调用,用来替代mounted和unmounted。这适用于<KeepAlive>的直接子节点及其所有子孙节点。
activated、deactivated钩子
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>动态组件</title>
</head>
<body><div id="app"><ul><li @click="currentTab='Home'">首页</li><li @click="currentTab='Kind'">分类</li><li @click="currentTab='Cart'">购物车</li><li @click="currentTab='User'">我的</li></ul><!-- 动态组件默认切换时 执行的是组件的 销毁 和 重新创建 --><!-- 可以使用 KeepAlive 保留组件的状态,避免组件的重新渲染 --><keep-alive><component :is="currentTab"></component></keep-alive></div>
</body>
<script src="../lib/vue.global.js"></script>
<script>const Home = {template: `<div>首页 <input placeholder="首页"/></div>`,created () { console.log('Home created') },mounted () { console.log('Home mounted') },unmounted () { console.log('Home unmounted') },activated () { console.log('Home 显示')},deactivated () { console.log('Home 隐藏')}}const Kind = {template: `<div>分类 <input placeholder="分类"/></div>`,created () { console.log('Kind created') },mounted () { console.log('Kind mounted') },unmounted () { console.log('Kind unmounted') },activated () { console.log('Kind 显示')},deactivated () { console.log('Kind 隐藏')}}const Cart = {template: `<div>购物车 <input placeholder="购物车"/></div>`,created () { console.log('Cart created') },mounted () { console.log('Cart mounted') },unmounted () { console.log('Cart unmounted') },activated () { console.log('Cart 显示')},deactivated () { console.log('Cart 隐藏')}}const User = {template: `<div>我的 <input placeholder="我的"/></div>`,created () { console.log('User created') },mounted () { console.log('User mounted') },unmounted () { console.log('User unmounted') },activated () { console.log('User 显示')},deactivated () { console.log('User 隐藏')}}
Vue.createApp({data () {return {currentTab: 'Home'}},components: {Home,Kind,Cart,User}}).mount('#app')
</script>
</html>
要不不缓存,要缓存都缓存了,这样不好
使用
include/exclude可以设置哪些组件被缓存,使用max可以设定最多缓存多少个<!-- 用逗号分隔的字符串,中间不要家空格 --> <KeepAlive include="a,b"><component :is="view"></component> </KeepAlive> <!-- 正则表达式 (使用 `v-bind`) --> <KeepAlive :include="/a|b/"><component :is="view"></component> </KeepAlive> <!-- 数组 (使用 `v-bind`) --> <KeepAlive :include="['a', 'b']"><component :is="view"></component> </KeepAlive>组件如果想要条件性地被
KeepAlive缓存,就必须显式声明一个name选项。<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>动态组件</title> </head> <body><div id="app"><ul><li @click="currentTab='Home'">首页</li><li @click="currentTab='Kind'">分类</li><li @click="currentTab='Cart'">购物车</li><li @click="currentTab='User'">我的</li></ul><!-- 动态组件默认切换时 执行的是组件的 销毁 和 重新创建 --><!-- 可以使用 KeepAlive 保留组件的状态,避免组件的重新渲染 --><!-- 字符串逗号分隔,千万不要加空格 --><!-- <keep-alive include="home,user"><component :is="currentTab"></component></keep-alive> --><!-- 正则 --><!-- <keep-alive :include="/home|user/"><component :is="currentTab"></component></keep-alive> --><!-- 数组 --><keep-alive :include="['home', 'user']"><component :is="currentTab"></component></keep-alive></div> </body> <script src="../lib/vue.global.js"></script> <script> const Home = {name: 'home',template: `<div>首页 <input placeholder="首页"/></div>`,created () { console.log('Home created') },mounted () { console.log('Home mounted') },unmounted () { console.log('Home unmounted') },activated () { console.log('Home 显示')},deactivated () { console.log('Home 隐藏')}}const Kind = {name: 'kind',template: `<div>分类 <input placeholder="分类"/></div>`,created () { console.log('Kind created') },mounted () { console.log('Kind mounted') },unmounted () { console.log('Kind unmounted') },activated () { console.log('Kind 显示')},deactivated () { console.log('Kind 隐藏')}}const Cart = {name: 'cart',template: `<div>购物车 <input placeholder="购物车"/></div>`,created () { console.log('Cart created') },mounted () { console.log('Cart mounted') },unmounted () { console.log('Cart unmounted') },activated () { console.log('Cart 显示')},deactivated () { console.log('Cart 隐藏')}}const User = {name: 'user',template: `<div>我的 <input placeholder="我的"/></div>`,created () { console.log('User created') },mounted () { console.log('User mounted') },unmounted () { console.log('User unmounted') },activated () { console.log('User 显示')},deactivated () { console.log('User 隐藏')}} Vue.createApp({data () {return {currentTab: 'Home'}},components: {Home,Kind,Cart,User}}).mount('#app') </script> </html>
五、缓存后如何获取数据
解决方案可以有以下两种:
-
beforeRouteEnter
-
actived
beforeRouteEnter
每次组件渲染的时候,都会执行beforeRouteEnter
beforeRouteEnter(to, from, next){next(vm=>{console.log(vm)// 每次进入路由执行vm.getData() // 获取数据})
},
actived
在keep-alive缓存的组件被激活的时候,都会执行actived钩子
activated(){this.getData() // 获取数据
},
注意:服务器端渲染期间avtived不被调用
相关文章:
vue中的keep-alive详解与应用场景
🌈个人主页:前端青山 🔥系列专栏:Vue篇 🔖人终将被年少不可得之物困其一生 依旧青山,本期给大家带来vue篇专栏内容:vue-keep-alive 目录 一、Keep-alive 是什么 二、使用场景 三、原理分析 四、案例实现 activa…...
软件设计师——程序设计语言基础(一)
📑前言 本文主要是【程序设计语言基础】——程序设计语言基础的相关题目,如果有什么需要改进的地方还请大佬指出⛺️ 🎬作者简介:大家好,我是听风与他🥇 ☁️博客首页:CSDN主页听风与他 &#…...
Apache简介与安装
先导概念: 静态网站: 最早的建站方式,每个页面都是一个独立的文件,需要手动上传或编辑。网页内容固定不变。例如,个人博客、静态企业官网等。 动态网站: 网站内容可根据不同情况动态变更,一般通过数据库进行架构。包含服务器端脚本,可以实现更丰富的功能。例如,社…...
set与map
set与map 一、序列式容器与关联式容器二、pair1、键值对2、作用3、构造函数4、make_pair(1)构造函数(2)作用 5、代码6、运行结果 三、set1、概念2、代码3、运行结果4、说明 四、multiset1、与set的关系2、代码3、运行结果 五、map…...
基于单片机智能液位水位监测控制系统
**单片机设计介绍, 基于单片机智能液位水位监测控制系统 文章目录 一 概要特点应用场景工作原理实现方式 系统功能实时监测控制调节报警功能数据记录与分析 总结 二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 ## 系统介绍 基于单片机…...
C#,《小白学程序》第十七课:随机数(Random)第四,移动平均值(Moving Average)的计算方法与代码
1 文本格式 /// <summary> /// 《小白学程序》第十七课:随机数(Random)第四,移动平均值的计算方法与代码 /// 继续学习数据统计,移动平均值的计算方法 /// 移动平均值就是一定步长内数值的平均值,用…...
行情分析——加密货币市场大盘走势(11.29)
大饼已经形成了底背离,即MACD往下走,而价格还在往上走,这种后续往往会大跌。继续把空单拿好,已经持仓的无需加仓。多次上涨却一直不能突破,说明多空和空军力量都很强,等待后续出方向。在笔者看来࿰…...
C++——string的字符串比较,字符存取,插入和删除和子串
一. string字符串比较 功能描述:字符串之间的比较 比较方式:字符串比较是按字符的ASCII码进行对比 返回 0 > 返回 1 < 返回 -1 函数原型: *int compare(const string &s) const; //与字符串s比较 *int compare(const char *s) const; //…...
字节10年经验之谈 —— 从0到1开发自动化测试框架!
一、序言 随着项目版本的快速迭代、APP测试有以下几个特点: 首先,功能点多且细,测试工作量大,容易遗漏;其次,代码模块常改动,回归测试很频繁,测试重复低效;最后&#x…...
Mysql(基本介绍+下载安装+服务器+基本使用+建库建表+navicat/mybitas工具+外键及实例)
一、Mysql基本介绍 当谈论MySQL时,通常指的是一个流行的开源关系型数据库管理系统(RDBMS)。MySQL是由瑞典的开发者在1995年创建的,后来被Sun Microsystems收购,最终成为Oracle Corporation的一部分。以下是关于MySQL的…...
Python+requests+Jenkins接口自动化测试实例
在做功能测试的基础上,我平时也会用postman测试接口,不过postman只能测试一个一个接口,不能连贯起来,特别是我们公司的接口很多都是要用到token的,导致我每次测个需要登录的接口都要去获取到token,做了很多…...
SpringBoot3核心原理
SpringBoot3核心原理 事件和监听器 生命周期监听 场景:监听应用的生命周期 可以通过下面步骤自定义SpringApplicationRunListener来监听事件。 ①、编写SpringApplicationRunListener实现类 ②、在META-INF/spring.factories中配置org.springframework.boot.Sprin…...
JS常用数据类型转换(数字型和字符串型之间转换)
提供了5中基本数据类型:数字 number 字符串 string 布尔 boolean 空值 null 未定义的 undefined 常用的是数字型和字符串型之间的转换,常用的转换方法如下: 1 数字型转换成字符串型 a) 使用String()方法…...
算法通关村第一关—青铜挑战—用Java基本实现各种链表操作
文章目录 第一关—链表【青铜挑战】1.1 单链表的概念1.2 链表的相关概念1.3 创建链表 - Java实现1.4 链表的增删改查1.4.1 遍历单链表 - 求单链表长度1.4.2 链表插入 - 三种位置插入(1)在链表的表头插入(2)在链表的中间插入&#…...
SparkRDD及算子-python版
RDD相关知识 RDD介绍 RDD 是Spark的核心抽象,即 弹性分布式数据集(residenta distributed dataset)。代表一个不可变,可分区,里面元素可并行计算的集合。其具有数据流模型的特点:自动容错,位置…...
嵌入式设备与PC上位机通信协议设计的几点原则
嵌入式设备在运行中需要设置参数,这个工作经常由PC机来实现,需要为双方通信设计协议,有代表性协议是如下三种: 从上表可以看到,一般嵌入式设备内存和运算性能都有限,因此固定二进制是首选通信协议。 一&am…...
Go 内置运算符
一、算数运算符 1、算数运算符使用 package mainimport ("fmt" )func main(){fmt.PrintIn("103",103) //10313fmt.PrintIn("10-3",10-3) //10-37fmt.PrintIn("10*3",10*3) //10*330//除法注意:如果运算的数都是…...
Table和HashBasedTable的使用案例
------------------- 1.普通使用 package org.example.testhashbasedtable;import com.google.common.collect.HashBasedTable; import com.google.common.collect.Table;import java.util.Map;public class TestHashBasedTable {public static void main(String[] args) {Ta…...
【执行批处理后 executeBatch() 没反应,一个参数相信就能搞定】
一、场景是在使用EasyExcel读取全表时,每次手动提交事务6w多条,总计190w数据量的情况下发生的。 博主比较fw,卡住了两天😶 此问题还有一个比较bug的地方,就是当你在 executeBatch() 上下打断点时还能够执行出来&…...
【LeetCode】每日一题 2023_11_25 二叉树中的伪回文路径(dfs,数组/位运算)
文章目录 刷题前唠嗑题目:二叉树中的伪回文路径题目描述代码与解题思路偷看大佬题解 结语 刷题前唠嗑 LeetCode?启动!!! 这个月第一次周末早起~ 题目:二叉树中的伪回文路径 题目链接:1457. 二…...
JavaSec-RCE
简介 RCE(Remote Code Execution),可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景:Groovy代码注入 Groovy是一种基于JVM的动态语言,语法简洁,支持闭包、动态类型和Java互操作性,…...
装饰模式(Decorator Pattern)重构java邮件发奖系统实战
前言 现在我们有个如下的需求,设计一个邮件发奖的小系统, 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其…...
基于大模型的 UI 自动化系统
基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...
macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用
文章目录 问题现象问题原因解决办法 问题现象 macOS启动台(Launchpad)多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显,都是Google家的办公全家桶。这些应用并不是通过独立安装的…...
TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案
一、TRS收益互换的本质与业务逻辑 (一)概念解析 TRS(Total Return Swap)收益互换是一种金融衍生工具,指交易双方约定在未来一定期限内,基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...
反射获取方法和属性
Java反射获取方法 在Java中,反射(Reflection)是一种强大的机制,允许程序在运行时访问和操作类的内部属性和方法。通过反射,可以动态地创建对象、调用方法、改变属性值,这在很多Java框架中如Spring和Hiberna…...
前端开发面试题总结-JavaScript篇(一)
文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包(Closure)?闭包有什么应用场景和潜在问题?2.解释 JavaScript 的作用域链(Scope Chain) 二、原型与继承3.原型链是什么?如何实现继承&a…...
【Oracle】分区表
个人主页:Guiat 归属专栏:Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...
如何在网页里填写 PDF 表格?
有时候,你可能希望用户能在你的网站上填写 PDF 表单。然而,这件事并不简单,因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件,但原生并不支持编辑或填写它们。更糟的是,如果你想收集表单数据ÿ…...
深度学习习题2
1.如果增加神经网络的宽度,精确度会增加到一个特定阈值后,便开始降低。造成这一现象的可能原因是什么? A、即使增加卷积核的数量,只有少部分的核会被用作预测 B、当卷积核数量增加时,神经网络的预测能力会降低 C、当卷…...
