7.Vue面试题

news2024/11/25 6:57:57

一、Vue面试基础知识

在这一小节中,我们先把一些常见的Vue的基础的面试题,总结出来。这些基础的知识点都是在面试的时候经常会被问到的一些内容。

当然关于基础的一些内容在前面的课程总咱们都已经讲解过来,所以这里我们只是把一些常见的内容与注意的问题再次强调 一下。

1、computed和watch

  • computed有缓存,如果数据data没有发生变化的话,则不会重新计算。
  • watch如何实现深度的监听?
  • watch监听引用类型,获取不到oldValue

下面看一下watch的伪代码

export default{
    data(){
        return {
            name:'zhangsan',
            info:{
                city:'上海'
            }
        }
    },
    watch:{
        name(oldVal,val){
            console.log(oldVal,val)//值类型,可以正常获取到值
        },
        info:{
            handler(oldVal,val){
                console.log(oldVal,val)//引用类型,获取不到oldVal,因为指针相同,此时已经指向了新的val
            },
            deep:true//深度监听
        }
    }
}

这里 还需要注意watch 的一个特点是,最初绑定的时候是不会执行的,要等到 firstName 改变时才执行监听计算。那我们想要一开始就让他最初绑定的时候就执行改怎么办呢?

watch: {
  firstName: {
    handler(newName, oldName) {
      this.fullName = newName + ' ' + this.lastName;
    },
    // 代表在wacth里声明了firstName这个方法之后立即先去执行handler方法
    immediate: true
  }
}

immediate:true代表如果在 wacth 里声明了 firstName 之后,就会立即先去执行里面的handler方法,如果为 false就跟我们以前的效果一样,不会在绑定的时候就执行。

2、v-if与v-show

简单的说一下,它两者的区别:如果条件满足,使用v-ifv-show都会创建对应的元素并展示出对应的内容,如果条件不满足v-else的内容不会展示也就是不会创建对应的元素,而v-show会创建出对应的元素,但是不会展示,使用style="display:none"将其隐藏掉。

两者如何选择呢?如果元素的创建不是很频繁,可以使用v-if与v-else,如果某些元素需要频繁的创建或者是需要不断的切换元素的显示隐藏状态,就需要使用v-show,这样性能会比较好,而如果使用v-ifv-else就需要不断创建与销毁元素,这样性能比较低了。

3、循环列表

  • key的重要性,注意key不能乱写,例如不能使用random或者是index
  • v-forv-if不能一起使用!
<ul>
    <li v-if="flag" v-for="item in lists" :key="item.id"></li>
    
</ul>
<script>
	export default {
        data(){
            return{
                flag:false,
                lists:[]
            }
        }
    }
</script>

v-for的优先级要高于v-if,这样的话就会先去执行循环,这样数组中的内容都循环完毕了,才会使用v-if进行判断。这样判断会被执行多次,而且是重复的判断。

4、父子组件如何通信

父子组件的通信通过props$emit完成,关于这块内容在前面的课程中已经重点讲解过了,这里不在进行讲解了。

5、兄弟组件之间的通信

自定义事件的实现方式

这里需要注意的一点就是最后要及时销毁自定义的事件,否则可能会造成内存泄漏的问题.

beforeDestroy(){
    event.$off('onAddSub',this.addSub)
}

6、生命周期

生命周期分为哪几个阶段?

  • 挂载阶段
  • 更新阶段
  • 销毁阶段

重点理解官网中的图

7、自定义v-model

v-modelvue实现数据双向绑定最好的一个指令, v-model本质上不过是语法糖,它负责监听用户的输入事件以更新数据,当你修改页面的时候 v-model 自动去更新数据层 (model),当你修改数据的时候v-model自动去更新视图层 (view)

8、$nextTick

  • Vue是异步渲染
  • data改变之后,DOM不会立刻渲染
  • $nextTick会在DOM渲染之后被触发,以获取最新的DOM节点。
<template>
	<div id="app">
        <ul ref="ul1">
        	<li v-for="(item,index) in list" :key="index">
                {{item}}
    		</li>    
    	</ul>
        <button @click="addItem">
        	添加一项    
    	</button>
    </div>
</template>
<script>
	export default {
        name:'app',
        data(){
            return{
                list:['a','b','c']
            }
        },
        methods:{
            addItem(){
                this.list.push(`${Date.now()}`)
                 this.list.push(`${Date.now()}`)
                 this.list.push(`${Date.now()}`)
                //获取dom元素
                const ulElem=this.$refs.ul1
                console.log(ulElem.childNodes.length)
            }
        }
    }
</script>

如果我们点击了按钮以后,输出的子元素的个数是多上呢?这里是3,可能你认为是6,因为在按钮所对应的处理函数中,我们向list数组中又添加了3项内容,这样ul中的子元素应该是6(list是响应式的,数据发生变化后,重新渲染视图). 但是实际的输出结果为3.

原因是:当datalist数组中的内容发生了变化后,DOM元素并不会立即改变。这时获取到的DOM元素的内容还是以前的内容。

但是,这里我们希望当单击完按钮后,立即获取到最新的DOM元素内容,应该怎样处理呢?

修改addItem方法中的代码如下:

  addItem(){
                this.list.push(`${Date.now()}`)
                 this.list.push(`${Date.now()}`)
                 this.list.push(`${Date.now()}`)
      			this.$nextTick(()=>{
                      //获取dom元素
                const ulElem=this.$refs.url1
                console.log(ulElem.childNodes.length)
                })
              
            }

把获取DOM元素的内容放到$nextTick方法对应的回调函数内部就可以了。

总结:第一:Vue是异步渲染,$nextTick是在DOM渲染完以后才执行的。

第二:页面渲染时会将data的修改做整合,也就是说多次data修改只会渲染一次,例如上面的案例中,我们对list数组做了三次的修改,但是最终只做了一次渲染。这样$nextTick也就只调用了一次。

9、slot

基本使用

作用域插槽

具名插槽

10、动态组件

:is="component-name"

什么时候用:需要根据数据,动态渲染的场景,即组件类型不确定。
在这里插入图片描述

!

在上图中,展示的是一个新闻的详情页面,在这个页面中,最开始展示了一个文本组件,然后下面紧跟着展示了一个图像组件,最后再展示文本组件。

但是,我们知道不同的详情页面可能展示的组件的顺序是不一样的,也就是说,另外一个详情页面,可能最开始展示的是图像组件,然后才是文本组件,所以到底先展示什么是不确定的,有具体的数据来决定。

下面看一下动态组件的基本使用

<div>
    <!--动态组件-->
    <component :is="NextTickName"/>
</div>
<script>
	import NextTick from './NextTick'
    export default{
        components:{
            NextTick
        },
        data(){
            return{
                name:'zhangsan',
                obj:{
                    username:'zs',
                    userpwd:'123'
                },
                NextTickName:'NextTick'
            }
        }
    }
</script>

现在,了解了动态组件的基本使用以后,下面我们通过一段伪代码,将上图的功能模拟一下。

<div>
    <!--动态组件-->
     <div v-for="item in newsData" :key="item.id">	
         <component :is="item.type"></component>
    </div>
</div>
<script>
	import NextTick from './NextTick'
    export default{
        components:{
            NextTick
        },
        data(){
            return{
                name:'zhangsan',
                obj:{
                    username:'zs',
                    userpwd:'123'
                },
               newData:[
                   //type:表示对应的组件
                   {id:1,type:'text'}
                   {id:2,type:'text'}
               	   {id:3,type:'imgage'}
               ]
            }
        }
    }
</script>

11、异步加载组件

在开发的时候,我们经常会加载一些体积比较大的组件,例如:编辑器,echarts等,

而这些组件的加载非常消耗性能,为了提高性能,可以采用异步的方式来进行加载。

·import( )函数实现按需加载,异步加载大组件

下面看一下import函数的使用。

<div>
    <!--异步组件-->
    <FormDemo v-if="showFormDemo" />
    <button @click="showFormDemo=true">show</button>
</div>
<script>
	//import FormDemo from './component/FormDemo' //同步加载组件
    export default {
        components:{
            //FormDemo
            FormDemo:()=>import('./component/FormDemo')
        },
        data(){
            return {
                showFormDemo:false
            }
        }
    }
</script>

通过上面的代码,我们可以看到最开始的时候是不会加载FormDemo这个组件的,当单击了show按钮的时候才会加载该组件,但是在加载该组件的时候是通过import方法来完成的,这就是异步加载组件,或者是按需加载,以前的加载方式是不管组件是否会用到都要进行加载,这其实就是同步的一种加载方式,这种方式会影响性能。

12、keep-alive

keep-alive实现缓存组件

什么时候会用到缓存组件呢?

需要进行频繁切换,不需要重复渲染的情况下,可以考虑使用keep-alive,例如 Tab页签组件

这也是常见的一种优化的手段。

13、mixin

mixin(混入)可以把多个组件中有相同的逻辑的内容,抽离出来。

<template>
   <div>
       <p>{{name}} {{major}} {{city}}</p> 
      <button @click="showName"> 
          显示姓名
    </button>
    </div>
</template>
<script>
	import myMixin from './mixin'
     export default {
         mixins:[myMixin],//可以添加多个,会自动的进行合并
         data(){
             return{
                 name:'zhangsan',
                 major:'web 前端'
             }
         },
         methods:{},
         mounted(){
          console.log('componet name',this.name)
     	}
     }
</script>

在上面的代码中,使用了cityshowName,这两项内容并没有在当前组件中进行定义,而是在mixin.js文件中进行定义的,这里进行了混入,那么这样当前组件就有了这些内容。而mixin.js文件中实现的内容都是其他组件相同的逻辑的内容。

mixin.js文件中的代码如下:

export default {
    data(){
        return{
            city:'北京'
        }
    },
    methods:{
        showName(){
            console.log(this.name)
        }
    },
    mounted(){
        console.log('mixin mounted',this.name)
    }
}

通过这个案例,我们可以看到,如果有很多组件,而且这些组件都有相同的逻辑,那么可以将这些相同的逻辑通过混入的方式引入到组件中,而在组件中定义的都是自己独有的内容。

当然,mixin也有自己的一些问题,

第一:变量来源不明确,不利于阅读,例如如下代码

  <p>{{name}} {{major}} {{city}}</p> 

假如当前组件混入了多项内容,那么在当前组件中我们使用了ciity变量,而该变量到底来自哪,不容易被查找。

第二:多mixin可能会造成命名冲突

第三点:mixin和组件可能出现多对多的关系,复杂度较高。

例如:一个组件可以引用多个mixin,而一个mixin可以被多个组件所引用,这样复杂度较高以后,很容易出现错误。

当然为了解决mixin的这些问题,在Vue3中提出了Composition API来进行解决。

二、Vue原理

1、MVVM

传统组件,只是静态渲染,更新还需要依赖于DOM操作。

数据驱动–Vue.js

所谓的数据驱动的理念:当数据发生变化的时候,用户界面也会发生相应的变化,开发者并不需要手动的去修改dom.

这样我们在开发的时候,更加关注的是数据(业务逻辑),而不是dom操作。
在这里插入图片描述

MVVM 框架主要包含三部分:Model,View,ViewMode

Model:指的是数据部分,对应到前端就是JavaScript对象。

View:指的就是视图部分

ViewModel: 就是连接视图与数据的中间件(中间桥梁)

数据(Model)和视图(View)是不能直接通讯的,而是需要通过ViewModel来实现双方的通讯。当数据(Model)变化的时候,ViewModel能够监听到这种变化,并及时通知View视图做出修改。同样的,当页面有事件触发的时候,ViewModel也能够监听到事件,并通知数据(Model)进行响应。所以ViewModel就相当于一个观察者,监控着双方的动作,并及时通知对方进行相应的操作。

简单的理解就是:MVVM 实现了将业务(数据)与视图进行分离的功能。

在这里还需要注意的一点就是:

MVVM框架的三要素:响应式,模板引擎,渲染

响应式:vue如何监听数据的变化?

模板:Vue的模板如何编写和解析?怎样将具体的值替换掉{{msg}}内容,这就是模板引擎的解析。

渲染:Vue如何将模板转换成html? 其实就是有虚拟DOM 向真实DOM的转换。

2、监听data变化的核心API是什么

响应式就是指:组件data的数据一旦发生变化,立刻触发视图的更新。

Vue2.x中的实现响应式的核心APIObject.defineProperty

Vue3响应式的核心Proxy

3、如何实现深度的监听

下面我们先来看一段代码:

//触发视图
 function updateView(){
     console.log('视图更新')
 }
//监听属性的变化
function defineReactive(target,key,value){
    Object.defineProperty(target,key,{
        get(){
            return value
        },
        set(newValue){
            if(newValue!==value){
                //设置新的值
                // 注意:value一直在闭包中,此处设置完之后,再get时也是会获取最新的值。
                value=newValue
                updateView()
            }
        }
    })
}
function observer(target){
    if(typeof target!=="object" || target===null){
        //不是对象或者是数组
        return target
    }
    for(let key in target){
        defineReactive(target,key,target[key])
    }
}
//准备数据
const data={
    name:'zhangsan',
    age:20
}
//监听数据
observer(data)
data.name="lisi"
data.age=21

以上通过Object.defineProperty这个api,将data转换成响应式的了。

下面把data对象中的内容修改一下:

const data={
    name:'zhansan',
    age:'21',
    info:{
        address:'北京'
    }
}
data.info.address='上海'

data中增加了一个info属性,该属性是一个对象,下面给该对象中的address属性赋值,但是视图没有进行更新。这里需要进行深度的监听。

//监听属性的变化
function defineReactive(target,key,value){
    observer(value)//深度监听
    Object.defineProperty(target,key,{
        get(){
            return value
        },
        set(newValue){
            if(newValue!==value){
                //深度监听
                 observer(newValue)
                //设置新的值
                // 注意:value一直在闭包中,此处设置完之后,再get时也是会获取最新的值。
                value=newValue
                updateView()
            }
        }
    })
}

在调用 Object.defineProperty之前进行了深度监听,同时在set方法的内部进行设置值也进行了深度的监听。

为什么在set方法的内部也要进行深度监听呢?

data.age={num:21}
data.age.num=22

如果不在set方法的内部设置深度监听,以上的内容无法更新视图。

Object.defineProperty的缺点:

第一:深度监听,需要递归到底,一次性计算量大。

第二:data.x='200'这种新增的属性,监听不到,需要用到Vue.set

delete data.name 删除属性,监听不到,需要使用Vue.delete

也就是说Object.defineProperty无法监听新增与删除属性.

4、vue如何监听数组的变化

关于Object.defineProperty的缺点还有一条,无法原生的监听数组,需要特殊处理。

 //重新定义数组原型
const oldArrayProperty=Array.prototype
//创建新的对象,原型指向oldArrayProperty,在扩展新的方法不会影响到原型.
const arrProto=Object.create(oldArrayProperty);
['push','pop','shift','unshift','splice'].forEach(methodName=>{
    arrProto[methodName]=function(){
    undateView();//更新视图
    
    oldArrayProperty[methodName].call(this,...arguments)
}
})

创建了一个新的对象,原型指向了oldArrayProperty.这样在扩展新的方法的时候不会影响到原型。

 //如果target是一个数组
    if(Array.isArray(target)){
        target.__proto__=arrProto
    }

如果target是一个数组,那么给原型赋值为arrProto.

这样,我们在使用data.nums.push(80)的时候,调用的是我们自己扩展的方法。

以上的操作相对来说比较麻烦,你可能有这样的想法,直接进行如下的修改:

function observer(target){
    if(typeof target!==object || target===null){
        //不是对象或者是数组
        return target
    }
    //如果target是一个数组
   // if(Array.isArray(target)){
     //   target.__proto__=arrProto
    //}
    
    Array.prototype.push=function(){
        updateView();
    }
    
    for(let key in target){
        defineReactive(target,key,target[key])
    }
}

在上面的代码中,我们直接修改了Array的原型的push方法中的代码,为其添加了更新视图的操作,这样不就很容易了吗?

但是,这样做是不行的。因为对全局的Array原型进行了污染。

//触发视图
 function updateView(){
     console.log('视图更新')
 }
 //重新定义数组原型
const oldArrayProperty=Array.prototype
//创建新的对象,原型指向oldArrayProperty,在扩展新的方法不会影响到原型.
const arrProto=Object.create(oldArrayProperty);
['push','pop','shift','unshift','splice'].forEach(methodName=>{
    arrProto[methodName]=function(){
    updateView();//更新视图
     console.log('this==',this)
    oldArrayProperty[methodName].call(this,...arguments)
}
})

//监听属性的变化
function defineReactive(target,key,value){
    Object.defineProperty(target,key,{
        get(){
            return value
        },
        set(newValue){
            if(newValue!==value){
                //设置新的值
                // 注意:value一直在闭包中,此处设置完之后,再get时也是会获取最新的值。
                value=newValue
                updateView()
            }
        }
    })
}
function observer(target){
    if(typeof target!==object || target===null){
        //不是对象或者是数组
        return target
    }
    //如果target是一个数组
    if(Array.isArray(target)){
        target.__proto__=arrProto
    }
    
    for(let key in target){
        defineReactive(target,key,target[key])
    }
}
//准备数据
const data={
    name:'zhangsan',
    age:20,
    nums:[10,20,30]
}
//监听数据
observer(data)
data.nums.push(80)

5、虚拟DOM(Virtual DOM)和diff

vdom是实现VueReact的重要基石

diff算法是vdom中最核心,最关键的部分,也是面试的过程中经常会被问到的一个问题。

我们知道DOM操作非常耗费性能,在以前的时候,可以使用jQuery,来自行控制DOM操作的时机,但是现在使用的VueReact是数据驱动视图,那么如何有效的控制DOM操作呢?

VueReact框架的内部通过虚拟DOM来完成对真实DOM的操作,也就是虚拟DOM就是用js模拟DOM结构,计算出最小的变更,然后在进行DOM的操作。

下面,我们看一段伪代码,是通过JS来模拟DOM结构的代码

<div id="div1" class="container">
    <p>
        vdom
    </p>
    <ul style="font-size:20px">
        <li>a</li>
    </ul>
</div>

对应的js模拟的DOM结构的代码如下:

{
    tag:'div',
    props:{
        className:'container',
         id:'div1'   
    }
    children:[
        {
            tag:'p',
            children:'vdom'
        },
        {
            tag:'ul',
            props:{style:'font-size:20px'}
            children:[
            	tag:'li',
                children:'a'
            ]
    		//......
        }
    ]
}

通过前面的学习,我们也知道在Vue中是通过snabbdom这个开源库来实现虚拟DOM与``diff算法的.

6、diff算法

关于diff算法,在前面的课程中,我们已经重点讲解过。如果忘记了可以复习。

这里首先注意的就是如下几点内容:

第一:只比较同一层级,不跨级比较

第二:tag不相同,则直接删掉重建,不再深度比较。

第三:tagkey,两者都相同,则认为是相同节点,则不再深度比较。

7、模板编译

模板不是html,模板中是有指令,插值表达式,js表达式,能够实现循环,判断。而html只是标签语言,不能实现循环,判断,只有js才能实现循环判断,因此模板一定是转换为某种js的代码,这个过程叫做编译模板。

  • 模板编译为render函数,执行render函数返回vnode
  • 基于vnode再执行patchdiff
  • 如果使用webpack vue-loader,会在开发环境下编译模板。

8、初次渲染过程

  • 解析模板为render函数
  • 触发响应式,监听data属性getter/setter
  • 执行render函数,生成vnode,执行patch(elem,vnode)

注意:在执行render 函数的时候会触发getter,例如,如下代码:

<p>
    {{message}}
</p>
<script>
	export default{
        data(){
            return {
                message :'hello world' //会触发get
            }
        }
    }
</script>

在上面的代码中,在模板中使用了message,所以会执行get操作。

更新过程

  • 修改data,触发setter
  • 重新执行render,生成newVnode
  • patch(vnode,newVnode),比较vnodenewVnode

9、异步渲染

Vue组件的渲染是异步渲染,这里可以参考$nextTick.

汇总data的修改,一次性更新视图

减少Dom操作次数,提高性能。

三、常见面试题

1、为何在v-for中使用key

v-for中必须使用key,key的取值不能是indexrandom.

使用key的原因:

diff算法中通过tagkey来判断,是否为sameNode,减少渲染次数,提升渲染的性能

2、Vue组件如何通讯

父子组件:propsthis.$emit

自定义事件event.$on event.$emit

vuex

3、双向数据绑定v-model的实现原理

input元素的value=this.msg

绑定input事件this.msg=$event.target.value

data更新触发render

4、computed的特点

缓存,data不变不会重新计算

提高性能

5、为什么组件data必须是一个函数

组件就是一个类,我们去使用组件,实际上就是对组件的一个实例化,如果data不是一个函数的话,每个组件实例的data都是一样的,那这样就共享了。

6、多个组件有相同的逻辑,如何抽离

使用mixin

mixin有一些缺点

7、何时使用异步组件

加载大组件

路由异步加载

8、何时需要使用keep-alive

缓存组件,不需要重复渲染

例如多个静态tab页的切换

性能优化

9、何时需要使用beforeDestory

解绑自定义事件event.$off

清除定时器

解绑自定义的DOM事件(注意是自己绑定的事件,VUe绑定的事件会自行解除)

10、Vuex中action和mutation有何区别

action中处理异步,mutation不可以

mutation做原子操作

action可以整合多个mutation

11、Vue-router常用的路由模式

hash模式

H5 history(需要服务端的支持)

两者的实现原理

12、Vue常见性能优化方式

合理使用v-showv-if

合理用computed

v-for时加上key

自定义事件,dom事件要及时的销毁

合理使用异步组件

合理使用keep-alive

data层级不要太深(递归次数多)

webpack的优化

前端通用的性能优化,如图片懒加载

使用ssr

t事件this.msg=$event.target.value`

data更新触发render

4、computed的特点

缓存,data不变不会重新计算

提高性能

5、为什么组件data必须是一个函数

组件就是一个类,我们去使用组件,实际上就是对组件的一个实例化,如果data不是一个函数的话,每个组件实例的data都是一样的,那这样就共享了。

6、多个组件有相同的逻辑,如何抽离

使用mixin

mixin有一些缺点

7、何时使用异步组件

加载大组件

路由异步加载

8、何时需要使用keep-alive

缓存组件,不需要重复渲染

例如多个静态tab页的切换

性能优化

9、何时需要使用beforeDestory

解绑自定义事件event.$off

清除定时器

解绑自定义的DOM事件(注意是自己绑定的事件,VUe绑定的事件会自行解除)

10、Vuex中action和mutation有何区别

action中处理异步,mutation不可以

mutation做原子操作

action可以整合多个mutation

11、Vue-router常用的路由模式

hash模式

H5 history(需要服务端的支持)

两者的实现原理

12、Vue常见性能优化方式

合理使用v-showv-if

合理用computed

v-for时加上key

自定义事件,dom事件要及时的销毁

合理使用异步组件

合理使用keep-alive

data层级不要太深(递归次数多)

webpack的优化

前端通用的性能优化,如图片懒加载

使用ssr

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

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

相关文章

C++PythonC# 三语言OpenCV从零开发(8):图像平滑处理

文章目录 相关链接前言图像资源图像平滑处理图像学知识补充(重点)什么是卷积什么是图像滤波什么是方框滤波和均值滤波 代码PythonCCsharp 总结 相关链接 C&Python&Csharp in OpenCV 专栏 【2022B站最好的OpenCV课程推荐】OpenCV从入门到实战 全套课程&#xff08;附带课…

UE4运用C++和框架开发坦克大战教程笔记(十七)(第51~54集)

UE4运用C和框架开发坦克大战教程笔记&#xff08;十七&#xff09;&#xff08;第51~54集&#xff09; 51. UI 框架介绍UE4 使用 UI 所面临的问题以及解决思路关于即将编写的 UI 框架的思维导图 52. 管理类与面板类53. 预加载与直接加载54. UI 首次进入界面 51. UI 框架介绍 U…

c#string方法对比

字符串的截取匹配操作在开发中非常常见&#xff0c;比如下面这个示例&#xff1a;我要匹配查找出来字符串数组中以“abc”开头的字符串并打印&#xff0c;我下面分别用了两种方式实现&#xff0c;代码如下&#xff1a; using System; namespace ConsoleApp23{ class Progra…

【计算机网络】物理层概述|通信基础|奈氏准则|香农定理|信道复用技术

目录 一、思维导图 二、 物理层概述 1.物理层概述 2.四大特性&#xff08;巧记"械气功程") 三、通信基础 1.数据通信基础 2.趁热打铁☞习题训练 3.信号の变身&#xff1a;编码与调制 4.极限数据传输率 5.趁热打铁☞习题训练 6.信道复用技术 推荐 前些天发…

flutter开发实战-可扩展popup弹窗template模版样式

flutter开发实战-可扩展popup弹窗template模版样式 最近在看到一个flutter_beautiful_popup&#xff0c;可以美化弹窗窗口样式。该插件通过一个template模版的类BeautifulPopupTemplate作为抽象的base类。 一、基类BeautifulPopupTemplate 在BeautifulPopupTemplate中&…

前端面试题——Vue的双向绑定

前言 双向绑定机制是Vue中最重要的机制之一&#xff0c;甚至可以说是Vue框架的根基&#xff0c;它将数据与视图模板相分离&#xff0c;使得数据处理和页面渲染更为高效&#xff0c;同时它也是前端面试题中的常客&#xff0c;接下来让我们来了解什么是双向绑定以及其实现原理。…

可解释性对人工智能发展的影响

文章目录 每日一句正能量前言可解释AI已成热点可解释性人工智能的重要性可解释性人工智能的研究现状推动可解释模型构建未来展望后记 每日一句正能量 不好等待运气降临&#xff0c;就应去发奋掌握知识。 前言 随着人工智能技术的快速发展&#xff0c;越来越多的应用场景需要人…

神经网络激活函数到底是什么?

激活函数 其实不是很难啦&#xff0c;归结一下就是大概这样几个分类&#xff0c;详情请参考【神经网络】大白话直观理解&#xff01;_哔哩哔哩_bilibili神经网络就是干这个事的~ 如果队伍不长&#xff0c;一个ykxb就可以了&#xff0c;如果 如果 队伍太长 就加一个激活函数也…

HBase相关面试准备问题

为什么选择HBase 1、海量存储 Hbase适合存储PB级别的海量数据&#xff0c;在PB级别的数&#xff0c;能在几十到几百毫秒内返回数据。这与Hbase的极易扩展性息息相关。正是因为Hbase良好的扩展性&#xff0c;才为海量数据的存储提供了便利。 2、列式存储 这里的列式存储其实说的…

Verilog实现2进制码与BCD码的互相转换

1、什么是BCD码&#xff1f; BCD码是一种2进制的数字编码形式&#xff0c;用4位2进制数来表示1位10进制中的0~9这10个数。这种编码技术&#xff0c;最常用于会计系统的设计里&#xff0c;因为会计制度经常需要对很长的数字做准确的计算。相对于一般的浮点式记数法&#xff0c;…

微信小程序 --- 腾讯地图线路规划

目录 微信小程序JavaScript 简介 Hello world&#xff01; geocoder(options:Object) 微信小程序插件 简介 路线规划插件 入驻腾讯位置服务平台 申请开发者密钥&#xff08;Key&#xff09;&#xff1a;申请秘钥 Key的作用与注意事项 微信公众平台绑定插件 方式一&a…

新型IT运维管理,基础设施和数据两手都要硬

编前语&#xff1a;数据是AI的基石&#xff0c;缺数据无AI。 AI大模型时代&#xff0c;数据赋予IT人“新使命” 当下IT人在企业中扮演着运营支撑的角色。说到运维管理&#xff0c;相信每人都是一把辛酸泪&#xff0c;每天承担着繁琐、高负荷且又高风险的运维工作&#xff0c;但…

开源软件全景解析:驱动技术创新与行业革新的力量

目录 什么是开源 开源的核心 开源软件的特点 为什么程序员应该拥抱开源 1.学习机会&#xff1a; 2.社区支持&#xff1a; 3.提高职业竞争力&#xff1a; 4.加速开发过程&#xff1a; 5.贡献和回馈&#xff1a; 开源软件的影响力 开源软件多元分析&#xff1a; 开源…

机器学习中常用的性能度量—— ROC 和 AUC

什么是泛化能力&#xff1f; 通常我们用泛化能力来评判一个模型的好坏&#xff0c;通俗的说&#xff0c;泛化能力是指一个机器学期算法对新样本&#xff08;即模型没有见过的样本&#xff09;的举一反三的能力&#xff0c;也就是学以致用的能力。 举个例子&#xff0c;高三的…

为什么说TiDB在线扩容对业务几乎没有影响

作者&#xff1a; 数据源的TiDB学习之路 原文来源&#xff1a; https://tidb.net/blog/e82b2c5f 当前的数据库种类繁多&#xff0c;墨天轮当前统计的所有国产数据库已经有 290个 &#xff0c;其中属于关系型数据库的有 166个 。关系型数据库从部署架构上又可以分为集中式…

AI克隆自己的声音只需5秒,MockingBird实现AI克隆声音!

一、环境搭建 搭建Anaconda运行环境 搭建Anaconda运行环境请跳转链接查看https://blog.csdn.net/m0_50269929/article/details/136036402安装pytorch pip3 install torch torchvision torchaudio安装ffmpeg 打开官网 https://ffmpeg.org/download.html#get-packages 下载地址…

Python实现PDF到HTML的转换

PDF文件是共享和分发文档的常用选择&#xff0c;但提取和再利用PDF文件中的内容可能会非常麻烦。而利用Python将PDF文件转换为HTML是解决此问题的理想方案之一&#xff0c;这样做可以增强文档可访问性&#xff0c;使文档可搜索&#xff0c;同时增强文档在不同场景中的实用性。此…

InnoDB 锁系统(小白入门)

1995年 &#xff0c;MySQL 1.0发布&#xff0c;仅供内部使用&#xff01; 开发多用户、数据库驱动的应用时&#xff0c;最大的一个难点是&#xff1a;一方面要最大程度地利用数据库的并发访问&#xff0c;另一方面还要确保每个用户能以一致性的方式读取和修改数据。 MVCC 并发…

list基本使用

list基本使用 构造迭代器容量访问修改 list容器底层是带头双向链表结构&#xff0c;可以在常数范围内在任意位置进行输入和删除&#xff0c;但不支持任意位置的随机访问&#xff08;如不支持[ ]下标访问&#xff09;&#xff0c;下面介绍list容器的基本使用接口。 template <…

CSS-IN-JS

CSS-IN-JS 为什么会有CSS-IN-JS CSS-IN-JS是web项目中将CSS代码捆绑在JavaScript代码中的解决方案。 这种方案旨在解决CSS的局限性&#xff0c;例如缺乏动态功能&#xff0c;作用域和可移植性。 CSS-IN-JS介绍 1&#xff1a;CSS-IN-JS方案的优点&#xff1a; 让css代码拥…