前端面试-经典的Vue面试题
面试总结三大模块:Vue双向绑定及原理、生命周期、组件通信、Vue官方API
目录:1.Vue双向绑定及原理
1.1你对MVVM是怎么理解的?
1.2你对Vue响应式原理是怎么理解的?是否可以实现一个简版的?Vue2中是如何监听数组的变化的?Vue3使用Proxy重写,相比Vue2的Object.defineProperty,有哪些优势?
1.2.1响应式原理
1.2.2 Vue2 Object.defineProperty简版实现代码
1.2.3 针对弊端解决 无法监听数组问题:Vue2中是如何监听数组的变化的?
1.2.4 针对弊端解决 无法劫持对象的新增属性:this.$set能够解决对象新增属性问题。延伸问题:$set为啥能监测数组变动?
1.2.5 Vue3 proxy简版实现代码
1.3你对Vue的v-model双向绑定是怎么理解的?是否可以实现一个简版的
1.3.1 v-model双向绑定理解
1.3.2 v-model双向绑定实现原理代码简版
1.3.3 双向绑定原理
2.生命周期
2.1Vue有哪些生命周期?它们有哪些使用场景?你的接口请求一般都放在哪个生命周期方法中,为什么?你的获取dom的方法一般都放在哪个生命周期方法中,为什么?
2.1.1vue3中的选项式生命周期钩子及使用场景
3.组件通信
$emit
向父组件触发一个事件,父组件监听这个事件就行了1.你对MVVM是怎么理解的?
MVVM是Model-View-ViewModel
缩写。Model层代表数据模型,View代表视图层,ViewModel是MVVM的核心,它是连接View和Model层的桥梁,数据会绑定到viewModel层并自动将数据渲染到页面中,视图变化的时候会通知viewModel层更新数据,实现数据的双向绑定。可以不用再去低效又麻烦地通过操纵 DOM 去更新视图,专心处理和维护 ViewModel层。
2.你对Vue响应式原理是怎么理解的?是否可以实现一个简版的?Vue2中是如何监听数组的变化的?Vue3使用Proxy重写,相比Vue2的Object.defineProperty,有哪些优势?
2.1响应式原理
- Vue2的响应式是基于
Object.defineProperty
实现的 - Vue3的响应式是基于ES6的
Proxy
来实现的
2.2 Vue2 Object.defineProperty简版实现代码
// 响应式函数
function reactive(obj, key, value) {
Object.defineProperty(data, key, {
get() {
console.log(`访问了${key}属性`)
return value
},
set(val) {
console.log(`将${key}由->${value}->设置成->${val}`)
if (value !== val) {
value = val
}
}
})
} const data = {
name: '林三心',
age: 22
}
Object.keys(data).forEach(key => reactive(data, key, data[key]))
console.log(data.name)
// 访问了name属性
// 林三心
data.name = 'sunshine_lin' // 将name由->林三心->设置成->sunshine_lin
console.log(data.name)
// 访问了name属性
// sunshine_lin
弊端:1.data新增了hobby
属性,进行访问和设值,但是都不会触发get和set
,所以弊端就是:Object.defineProperty
只对初始对象里的属性有监听作用,而对新增的属性无效。这也是为什么Vue2中对象新增属性的修改需要使用Vue.$set
来设值的原因;2.不能对数组数据进行劫持,无法监测到数组长度变化,需重写数组方法。
// 接着上面代码 data.hobby = '打篮球'
console.log(data.hobby) // 打篮球
data.hobby = '打游戏'
console.log(data.hobby) // 打游戏
2.3 针对弊端解决 无法监听数组问题:Vue2中是如何监听数组的变化的?
import { def } from '../util/index' const arrayProto = Array.prototype
export const arrayMethods = Object.create(arrayProto) const methodsToPatch = [
'push',
'pop',
'shift',
'unshift',
'splice',
'sort',
'reverse'
] methodsToPatch.forEach(function (method) {
// 缓存原来的方法
const original = arrayProto[method]
def(arrayMethods, method, function mutator (...args) {
const result = original.apply(this, args)
const ob = this.__ob__
let inserted
switch (method) {
case 'push':
case 'unshift':
inserted = args
break
case 'splice':
inserted = args.slice(2)
break
}
if (inserted) ob.observeArray(inserted)
// notify change
ob.dep.notify()
return result
})
})
看来Vue能对数组进行监听的原因是,把数组的方法重写了。总结起来就是这几步:
01先获取原生 Array 的原型方法,因为拦截后还是需要原生的方法帮我们实现数组的变化。
02对 Array 的原型方法使用 Object.defineProperty 做一些拦截操作。
03把需要被拦截的 Array 类型的数据原型指向改造后原型
2.4 针对弊端解决 无法劫持对象的新增属性:this.$set能够解决对象新增属性问题。延伸问题:$set为啥能监测数组变动?
function set (target, key, val) {
//...
if (Array.isArray(target) && isValidArrayIndex(key)) {
target.length = Math.max(target.length, key);
target.splice(key, 1, val);
return val
}
if (key in target && !(key in Object.prototype)) {
target[key] = val;
return val
}
//...
defineReactive$$1(ob.value, key, val);
ob.dep.notify();
return val
}
- 如果target是一个数组且索引有效,就设置length的属性。
- 通过splice方法把value设置到target数组指定位置。
- 设置的时候,vue会拦截到target发生变化,然后把新增的value也变成响应式
- 最后返回value
这就是vue重写数组方法的原因,利用数组这些方法触发使得每一项的value都是响应式的。
2.5 Vue3 proxy简版实现代码(优势是解决了弊端)
target:源对象 prop:要进行操作的属性 value:set操作时的最新值
js是单线程遇到错误会直接挂机,Reflect兼容性更好,否则需要使用try catch捕获错误
3.你对Vue的v-model双向绑定是怎么理解的?是否可以实现一个简版的?
3.1 v-model双向绑定理解
v-model可以实现表单元素和数据之间的双向绑定,即修改表单的值,data中对应变量的值也会被修改。在data对应变量中修改值,被绑定的表单值也会被修改;所以称之为双向绑定。
3.2 v-model双向绑定实现原理代码简版
使用v-bind将文本框的value绑定给数据变量,实现变量改变,文本框值也随之改变的单向绑定;然后使用v-on绑定文本框的值改变事件,最后将事件对象中的文本框值传递给变量,即实现了双向绑定。
不使用方法实现:
<div id="ab">
<!-- <input type="text" v-model="msg"> -->
<input type="text" name="" id="" v-bind:value="msg" v-on:input="msg = $event.target.value">
<h4>{{msg}}</h4>
</div>
<script>
const app = new Vue({
el:'#ab',
data:{
msg:'起飞'
}
})
</script>
使用方法实现:
<div id="ab">
<!-- <input type="text" v-model="msg"> -->
<input type="text" name="" id="" v-bind:value="msg" v-on:input="Value">
<h4>{{msg}}</h4>
</div>
<script>
const app = new Vue({
el:'#ab',
data:{
msg:'起飞'
},
methods:{
Value(event){
this.msg = event.target.value;
}
}
})
</script>
3.3双向绑定原理
Vue 主要通过以下 4 个步骤来实现数据双向绑定的:
实现一个监听器 Observer:对数据对象进行遍历,包括子属性对象的属性,利用 Object.defineProperty() 对属性都加上 setter 和 getter。这样的话,给这个对象的某个值赋值,就会触发 setter,那么就能监听到了数据变化。
实现一个解析器 Compile:解析 Vue 模板指令,将模板中的变量都替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,调用更新函数进行数据更新。
实现一个订阅者 Watcher:Watcher 订阅者是 Observer 和 Compile 之间通信的桥梁 ,主要的任务是订阅 Observer 中的属性值变化的消息,当收到属性值变化的消息时,触发解析器 Compile 中对应的更新函数。
实现一个订阅器 Dep:订阅器采用 发布-订阅 设计模式,用来收集订阅者 Watcher,对监听器 Observer 和 订阅者 Watcher 进行统一管理。
二、生命周期
1.Vue有哪些生命周期?它们有哪些使用场景?你的接口请求一般都放在哪个生命周期方法中,为什么?你的获取dom的方法一般都放在哪个生命周期方法中,为什么?
1.1 vue3中的选项式生命周期钩子及使用场景
beforeCreate
: 在实例初始化之后、进行数据侦听和事件/侦听器的配置之前同步调用created
:在实例创建完成后被立即同步调用beforeMount
:在挂载开始之前被调用mounted
:在实例挂载完成后被调用beforeUpdate
:在数据发生改变后,DOM 被更新之前被调用updated
:在数据更改导致的虚拟 DOM 重新渲染和更新完毕之后被调用beforeUnmount
(在Vue2中是:beforeDestroy
):在卸载组件实例之前调用unmounted
(在Vue2中是:destroyed
):卸载组件实例后调用
1.2 vue3中的组合式生命周期钩子(使用场景对比选项式生命周期钩子)
beforeCreate
和 Create
函数的。官方解释: 因为
setup
是围绕 beforeCreate
和 created
生命周期钩子运行的,所以不需要显式地定义它们。换句话说,在这些钩子中编写的任何代码都应该直接在 setup
函数中编写。- 对于作为子组件被调用的组件里,异步请求应当在
mounted
里调用,因为这个时候子组件可能需要涉及到对dom的操作; - 对于页面级组件,当我们需要使用
ssr
(服务端渲染)的时候,只有created
是可用的,所以这个时候请求数据只能用它;能更快获取到服务端数据,减少页面 loading 时间; - 对于页面级组件, 当我们做异步操作时,涉及到要访问dom的操作,我们仍旧只能使用
mounted
; - 对于一般情况,
created
和mounted
都是可以的;
1.4获取DOM的方法放在哪个生命周期方法中?为什么?
1. beforeCreated:生成$options选项,并给实例添加生命周期相关属性。在实例初始化之后,在 数据观测(data observer) 和event/watcher 事件配置之前被调用,也就是说,data,watcher,methods都不存在 这个阶段。但是有一个对象存在,那就是$route,因此此阶段就可以根据路由信息进行重定向等操作。
2. created:初始化与依赖注入相关的操作,会遍历传入methods的选项,初始化选项数据,从$options获取数据选项(vm.$options.data),给数据添加‘观察器’对象并创建观察器,定义getter、setter存储器属 性。在实例创建之后被调用,该阶段可以访问data,使用watcher、events、methods,也就是说 数据观测(data observer) 和event/watcher 事件配置 已完成。但是此时dom还没有被挂载。该阶段允许执行 http请求操作。
3. beforeMount:将HTML解析生成AST节点,再根据AST节点动态生成渲染函数。相关render函数首次被调用(划重点)。
4. mounted:在挂载完成之后被调用,执行render函数生成虚拟dom,创建真实dom替换虚拟dom,并挂载到实例。可以操作dom,比如事件监听
5. beforeUpdate:$vm.data更新之后,虚拟dom重新渲染之前被调用。在这个钩子可以修改$vm.data,并不会触发附加的冲渲染过程。
6. updated:虚拟dom重新渲染后调用,若再次修改$vm.data,会再次触发beforeUpdate、updated,进入死循环。
7. beforeDestroy:实例被销毁前调用,也就是说在这个阶段还是可以调用实例的。
8. destroyed:实例被销毁后调用,所有的事件监听器已被移除,子实例被销毁。
总结来说,虚拟dom开始渲染是在beforeMount时,dom实例挂载完成在mounted阶段显示。
在选项式生命周期中只有mounted时期挂载完成后才能够获取DOM,mounted时期前DOM未生成,mounted时期后调用进入死循环,同理在组合式生命周期只有在onMounted时期,setup时期等都不可以获取DOM。(或者可以在created时期使用$nextTick函数)
三、组件通信
1.Vue的子组件如何调用父组件的方法?
1.1直接在子组件中通过this.$parent.event来调用父组件的方法
// 父组件
<template>
<div>
<child></child>
</div>
</template>
<script>
import child from '~/components/dam/child';
export default {
components: {
child
},
methods: {
fatherMethod() {
console.log('测试');
}
}
};
</script>
// 子组件
<template>
<div>
<button @click="childMethod()">点击</button>
</div>
</template>
<script>
export default {
methods: {
childMethod() {
this.$parent.fatherMethod();
}
}
};
</script>
1.2在子组件里用$emit
向父组件触发一个事件,父组件监听这个事件就行了
// 父组件
<template>
<div>
<child @fatherMethod="fatherMethod"></child>
</div>
</template>
<script>
import child from '~/components/dam/child';
export default {
components: {
child
},
methods: {
fatherMethod() {
console.log('测试');
}
}
};
</script>
// 子组件
<template>
<div>
<button @click="childMethod()">点击</button>
</div>
</template>
<script>
export default {
methods: {
childMethod() {
this.$emit('fatherMethod');
}
}
};
</script>
1.3父组件把方法传入子组件中,在子组件里直接调用这个方法
// 父组件
<template>
<div>
<child :fatherMethod="fatherMethod"></child>
</div>
</template>
<script>
import child from '~/components/dam/child';
export default {
components: {
child
},
methods: {
fatherMethod() {
console.log('测试');
}
}
};
</script>
// 子组件
<template>
<div>
<button @click="childMethod()">点击</button>
</div>
</template>
<script>
export default {
props: {
fatherMethod: {
type: Function,
default: null
}
},
methods: {
childMethod() {
if (this.fatherMethod) {
this.fatherMethod();
}
}
}
};
</script>
2.Vue组件通信有哪些方式?
- 父子通信: 父向子传递数据是通过 props,子向父是通过 events(
$emit
);通过父链 / 子链也可以通信($parent
/$children
);ref 也可以访问组件实例;provide / inject API;$attrs/$listeners
- 兄弟通信: Bus;Vuex
- 跨级通信: Bus;Vuex;provide / inject API、
$attrs/$listeners
- https://juejin.cn/post/6877101934600273934
2. Vue列表中加的key是干什么的?
vue中列表循环需加:key="唯一标识" 唯一标识可以是item里面id 等,因为vue组件高度复用增加Key可以标识组件的唯一性,为了更好地区别各个组件 key的作用主要是为了高效的更新虚拟DOM。
key在diff算法中的用法演示:https://juejin.cn/post/7156507746555133965#heading-5
延申问题:不推荐index作为key值
- 登录的状态、以及用户的信息
- 购物车的信息,收藏的信息等
- 用户的地理位置
- URL 中的 hash 值只是客户端的一种状态,向服务端发送请求的时候,hash 部分不会被发送。
- hash 值得改变会在浏览器的历史记增加访问记录,所以可以通过浏览器的回退、前进控制 hash 值的改变。
- 可以通过 a 标签设置 href 值或者通过 js 给location.hash 赋值来改变 hash 值。
- 可以通过hashchang 事件来监听 hash 值的变化,从而对页面进行跳转(渲染)。
popstate事件的执行是在点击浏览器的前进后退按钮的时候,才会被触发(popstate控制浏览器历史记录的api)
使用history模式需要更改router.js的mode为history,设置vue.config.js的publicPath:'/‘
- 通过 pushState 和 replaceState 两个API 来操作实现 URL 的变化。
- 可以通过 popstate 事假来监听 URL 的变化,从而对页面进行跳转(渲染)。
- history.pushState() 或 history.replaceState() 不会触发 popstate 事件,需要手动触发页面跳转
2.功能上:比如我们在开发app的时候有分享页面,那么这个分享出去的页面就是用vue或是react做的,咱们把这个页面分享到第三方的app里,有的app里面url是不允许带有#号的,所以要将#号去除那么就要使用history模式,但是使用history模式还有一个问题就是,在访问二级页面的时候,做刷新操作,会出现404错误,那么就需要和后端人配合,让他配置一下apache或是nginx的url重定向,重定向到你的首页路由上就ok了
传统的路由指的是:当用户访问一个url时,对应的服务器会接收这个请求,然后解析url中的路径,从而执行对应的处理逻辑。这样就完成了一次路由分发
前端路由是:不涉及服务器的,是前端利用hash或者HTML5的history API来实现的,一般用于不同内容的展示和切换
5.有没有写过Vue的指令,它的实现原理是什么?有没有写过Vue的插件,它的实现原理是什么?
5.1指令api:生命周期和钩子函数参数
bind
:指令第一次绑定到元素时调用,此钩子只会调用一次。在这里可以进行一次性的初始化设置。inserted
:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。update
:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。componentUpdated
:指令所在组件的 VNode 及其子 VNode 全部更新后调用。unbind
:只调用一次,指令与元素解绑时调用。
el
:指令所绑定的元素,可以用来直接操作DOM
。binding
:一个对象,包含以下属性:name
:指令名,不包括v-
前缀。value
:指令的绑定值,例如:v-my-directive="1 + 1"
中,绑定值为2
。oldValue
:指令绑定的前一个值,仅在update
和componentUpdated
钩子中可用。无论值是否改变都可用。expression
:字符串形式的指令表达式。例如v-my-directive="1 + 1"
中,表达式为 "1 + 1
"。arg
:传给指令的参数,可选。例如v-my-directive:foo
中,参数为 "foo
"。modifiers
:一个包含修饰符的对象。例如:v-my-directive.foo.bar
中,修饰符对象为{ foo: true, bar: true }
。vnode
:Vue
编译生成的虚拟节点。移步VNode API
来了解更多详情。oldVnode
:上一个虚拟节点,仅在update
和componentUpdated
钩子中可用。
5.2 指令和插件本质
Vue 插件机制的原理:本质上插件就是一个对象,在对象里面调用install 方法
Vue指令的原理:本质上插件就是一个对象
5.3 实现一键复制文本内容,用于鼠标右键粘贴的指令(配合插件执行全局注册)
import { Message } from 'ant-design-vue'; const vCopy = { // 名字爱取啥取啥
/*
bind 钩子函数,第一次绑定时调用,可以在这里做初始化设置
el: 作用的 dom 对象
value: 传给指令的值,也就是我们要 copy 的值
*/
bind(el, { value }) {
el.$value = value; // 用一个全局属性来存传进来的值,因为这个值在别的钩子函数里还会用到
el.handler = () => {
if (!el.$value) {
// 值为空的时候,给出提示,我这里的提示是用的 ant-design-vue 的提示,你们随意
Message.warning('无复制内容');
return;
}
// 动态创建 textarea 标签
const textarea = document.createElement('textarea');
// 将该 textarea 设为 readonly 防止 iOS 下自动唤起键盘,同时将 textarea 移出可视区域
textarea.readOnly = 'readonly';
textarea.style.position = 'absolute';
textarea.style.left = '-9999px';
// 将要 copy 的值赋给 textarea 标签的 value 属性
textarea.value = el.$value;
// 将 textarea 插入到 body 中
document.body.appendChild(textarea);
// 选中值并复制
textarea.select();
// textarea.setSelectionRange(0, textarea.value.length);
const result = document.execCommand('Copy');
if (result) {
Message.success('复制成功');
}
document.body.removeChild(textarea);
};
// 绑定点击事件,就是所谓的一键 copy 啦
el.addEventListener('click', el.handler);
},
// 当传进来的值更新的时候触发
componentUpdated(el, { value }) {
el.$value = value;
},
// 指令与元素解绑的时候,移除事件绑定
unbind(el) {
el.removeEventListener('click', el.handler);
},
}; export default vCopy;
5.3.2定义一个能够注册指令的插件(不使用插件注册的方法是直接在main调用directive注册就可以)
import copy from './v-copy';
// 自定义指令
const directives = {
copy,
};
// 这种写法可以批量注册指令
export default {
install(Vue) { //install函数是插件的语法
Object.keys(directives).forEach((key) => {
Vue.directive(key, directives[key]); //注册指令对象
});
},
};
5.3.3在main中引入插件来进行指令注册
import Vue from 'vue';
import Directives from './directives'; Vue.use(Directives); //插件使用方法use
5.3.4使用指令方法
<template>
<button v-copy="copyText">copy</button>
</template> <script>
export default {
data() {
return {
copyText: '要 Copy 的内容',
};
},
};
</script>
6.nxetTick是干什么用的?
将传入的回调函数包装成异步任务,异步任务又分微任务和宏任务,为了尽快执行所以优先选择微任务,把微任务放在DOM 更新后执行;
Vue2根据环境是否支持,选择的微任务优先级为:Promise---> MutationObserver---> setImmediate---> setTimeout
Vue3直接选用Promise,添加几个维护队列queueJob
-> queueFlush
-> flushJobs
-> nextTick参数的 fn,详情看 https://juejin.cn/post/7021688091513454622#heading-9
v-for
比v-if
具有更高的优先级,意味着v-if
将分别重复运行于每个v-for
循环中。v-for
的数据中v-if
的数据项给过滤处理了。const Foo = () => import('./Foo.vue')
const router = new VueRouter({
routes: [
{ path: '/foo', component: Foo }
]
})
8.vue的虚拟dom你是怎么理解的?是否可以实现一个简版的?
var element = {
tagName: 'ul', // 节点标签名
props: { // DOM的属性,用一个对象存储键值对
id: 'list'
},
children: [ // 该节点的子节点
{tagName: 'li', props: {class: 'item'}, children: ["Item 1"]},
{tagName: 'li', props: {class: 'item'}, children: ["Item 2"]},
{tagName: 'li', props: {class: 'item'}, children: ["Item 3"]},
]
}
8.3实现原理
- 用 JavaScript 对象模拟真实 DOM 树,对真实 DOM 进行抽象;
- diff 算法 — 比较两棵虚拟 DOM 树的差异;
- pach 算法 — 将两个虚拟 DOM 对象的差异应用到真正的 DOM 树。
前端面试-经典的Vue面试题的更多相关文章
- JQuery选择器大全 前端面试送命题:面试题篇 对IOC和DI的通俗理解 c#中关于协变性和逆变性(又叫抗变)帮助理解
JQuery选择器大全 jQuery 的选择器可谓之强大无比,这里简单地总结一下常用的元素查找方法 $("#myELement") 选择id值等于myElement的元素 ...
- 阿里巴巴前端面试parseInt()函数的面试题
JavaScript 是弱类型语言,为了保证数值的有效性,在处理数值的时候,我们可以对数值字符串进行强行转换.如 parseInt 取整和 parseFloat 取浮点数.Java 也有 Intege ...
- 前端面试经典题目合集(HTML+CSS)一
1.说说你对HTML语义化的理解? (1)什么是HTML语义化? 根据内容的结构化(内容语义化),选择合适的标签(代码语义化)便于开发者阅读和写出更优雅的代码的同时让浏览器的爬虫和机器很好地解析. ( ...
- 前端面试经典题目(HTML+CSS)二
1.浏览器页面由哪三层构成,分别是什么,作用是什么? 构成:结构层.表示层.行为层 分别是:HTML.CSS.JavaScript 作用:HTML实现页面结构,CSS完成页面的表现与风格,JavaSc ...
- 前端面试经典题之ES6新特性
ES6 主要是为了解决 ES5 的先天不足,在原先ES5的基础上新增了许多内容,本篇文章将列举出ES6中新增的10大特性. 一. let 和 const 与var不同,let和const都是用于命名局 ...
- 前端面试经典题之apply与call的比较
在讲apply和call之前,我们需要先清楚在js中,this指向的是什么. 大家可以参考一下阮一峰老师写的关于JavaScript中this的原理讲解文章:http://www.ruanyifeng ...
- 2019前端面试系列——Vue面试题
Vue 双向绑定原理 mvvm 双向绑定,采用数据劫持结合发布者-订阅者模式的方式,通过 Object.defineProperty()来劫持各个属性的 setter.getter,在数 ...
- 【前端面试】Vue面试题总结(持续更新中)
Vue面试题总结(持续更新中) 题目参考链接 https://blog.csdn.net/weixin_45257157/article/details/106215158 由于已经有很多前辈深造VU ...
- web前端面试试题总结---css篇
CSS 介绍一下标准的CSS的盒子模型?低版本IE的盒子模型有什么不同的? (1)有两种, IE 盒子模型.W3C 盒子模型: (2)盒模型: 内容(content).填充(padding).边界(m ...
- 2019前端面试系列——JS面试题
判断 js 类型的方式 1. typeof 可以判断出'string','number','boolean','undefined','symbol' 但判断 typeof(null) 时值为 'ob ...
随机推荐
- ES6的Set详解
数组去重 let arr = [ 1,2,3,4,5,3,2 ] // 数组去重 // 方法一 let newArr = [new Set(arr)] console.log(newArr); // ...
- 微信小程序wxs封装使用以及公共js组件封装
wxs封装 wxs可以直接写在wxml页面中,并且在对应的位置调用,比如在{{ xxx.xxx() }}调用wxs的函数 <view> <view>第{{m1.getMax(1 ...
- JZOJ 5343. 【NOIP2017模拟9.3A组】健美猫
题面 其中 \(1 \leq n \leq 2 \times 10^6\) 分析 考虑每次移动,发现负数对答案贡献少 \(1\),非负数多 \(1\) 每次移动都加了 \(1\) 负数变非负数关键点在 ...
- 血药谷浓度能否区分经TNF拮抗剂诱导获得缓解和低活动度的RA患者
血药谷浓度能否区分经TNF拮抗剂诱导获得缓解和低活动度的RA患者? Sanmarti R, et al. EULAR 2015. Present ID: FRI0133. 原文 译文 FRI0133 ...
- gin 01
1.gin介绍: 2.gin的安装 go get -u github.com/gin-gonic/gin 3.gin的第一个helloWord package main import ( " ...
- 3.基于Label studio的训练数据标注指南:文本分类任务
文本分类任务Label Studio使用指南 1.基于Label studio的训练数据标注指南:信息抽取(实体关系抽取).文本分类等 2.基于Label studio的训练数据标注指南:(智能文档) ...
- 浅析容器运行时奥秘——OCI标准
背景 2013年Docker开源了容器镜像格式和运行时以后,为我们提供了一种更为轻量.灵活的"计算.网络.存储"资源虚拟化和管理的解决方案,在业界迅速火了起来. 2014年更是容器 ...
- Qt中的多窗体编程
在某些应用中,会用到多窗体功能,这里就来讨论一下Qt下多窗体功能的实现.本例仍以qt4.8.7版本为例,并基于QtCreator4.6.2环境进行开发.在本例中,以一个能显示实时时钟的第二窗体为例进行 ...
- USACO2023Feb游记
由于学校要求,过来打 USACO. 由于上次已经打到白金了,所以继续. 然后还是 AK 了. 感觉题意很迷惑,所以都翻译一下. Hungry Cow Bessie 很饿,每天晚饭如果有干草就会吃 \( ...
- EveryCircuit_v2.15汉化破解版apk下载
安卓手机扫码下载 大小 6.44M EveryCircuit(电子电路模拟器)是一个专为电子信息技术专业的人士所打造的软件,它能够让你轻松的了解到电子电路究竟是如何进行工作的. 下载地址:https ...