前端vue面试题集锦1

news2024/11/25 11:46:31

Vue.extend 作用和原理

官方解释:Vue.extend 使用基础 Vue 构造器,创建一个“子类”。参数是一个包含组件选项的对象。

其实就是一个子类构造器 是 Vue 组件的核心 api 实现思路就是使用原型继承的方法返回了 Vue 的子类 并且利用 mergeOptions 把传入组件的 options 和父类的 options 进行了合并

相关代码如下

export default function initExtend(Vue) {
  let cid = 0; //组件的唯一标识
  // 创建子类继承Vue父类 便于属性扩展
  Vue.extend = function (extendOptions) {
    // 创建子类的构造函数 并且调用初始化方法
    const Sub = function VueComponent(options) {
      this._init(options); //调用Vue初始化方法
    };
    Sub.cid = cid++;
    Sub.prototype = Object.create(this.prototype); // 子类原型指向父类
    Sub.prototype.constructor = Sub; //constructor指向自己
    Sub.options = mergeOptions(this.options, extendOptions); //合并自己的options和父类的options
    return Sub;
  };
}

虚拟DOM真的比真实DOM性能好吗

  • 首次渲染大量DOM时,由于多了一层虚拟DOM的计算,会比innerHTML插入慢。
  • 正如它能保证性能下限,在真实DOM操作的时候进行针对性的优化时,还是更快的。

Vue complier 实现

  • 模板解析这种事,本质是将数据转化为一段 html ,最开始出现在后端,经过各种处理吐给前端。随着各种 mv* 的兴起,模板解析交由前端处理。
  • 总的来说,Vue complier 是将 template 转化成一个 render 字符串。

可以简单理解成以下步骤:

  • parse 过程,将 template 利用正则转化成AST 抽象语法树。
  • optimize 过程,标记静态节点,后 diff 过程跳过静态节点,提升性能。
  • generate 过程,生成 render 字符串

Vue.mixin的使用场景和原理

  • 在日常的开发中,我们经常会遇到在不同的组件中经常会需要用到一些相同或者相似的代码,这些代码的功能相对独立,可以通过 Vuemixin 功能抽离公共的业务逻辑,原理类似“对象的继承”,当组件初始化时会调用 mergeOptions 方法进行合并,采用策略模式针对不同的属性进行合并。当组件和混入对象含有同名选项时,这些选项将以恰当的方式进行“合并”;如果混入的数据和本身组件的数据冲突,会以组件的数据为准
  • mixin有很多缺陷如:命名冲突、依赖问题、数据来源问题

基本使用

<script>
    // Vue.options
    Vue.mixin({ // 如果他是对象 每个组件都用mixin里的对象进行合并
        data(){
            return {a: 1,b: 2}
        }
    });
    // Vue.extend
    Vue.component('my',{ // 组件必须是函数 Vue.extend  => render(xxx)
        data(){
            return {x:1}
        }
    }) 
    // 没有 new 没有实例  _init()
    // const vm = this
    new Vue({
        el:'#app',
        data(){ // 根可以不是函数 
            return {c:3}
        }
    })
</script>

相关源码

export default function initMixin(Vue){
  Vue.mixin = function (mixin) {
    //   合并对象
      this.options=mergeOptions(this.options,mixin)
  };
}
};

// src/util/index.js
// 定义生命周期
export const LIFECYCLE_HOOKS = [
  "beforeCreate",
  "created",
  "beforeMount",
  "mounted",
  "beforeUpdate",
  "updated",
  "beforeDestroy",
  "destroyed",
];

// 合并策略
const strats = {};
// mixin核心方法
export function mergeOptions(parent, child) {
  const options = {};
  // 遍历父亲
  for (let k in parent) {
    mergeFiled(k);
  }
  // 父亲没有 儿子有
  for (let k in child) {
    if (!parent.hasOwnProperty(k)) {
      mergeFiled(k);
    }
  }

  //真正合并字段方法
  function mergeFiled(k) {
    // strats合并策略
    if (strats[k]) {
      options[k] = strats[k](parent[k], child[k]);
    } else {
      // 默认策略
      options[k] = child[k] ? child[k] : parent[k];
    }
  }
  return options;
}

Vue-router 导航守卫有哪些

  • 全局前置/钩子:beforeEach、beforeResolve、afterEach
  • 路由独享的守卫:beforeEnter
  • 组件内的守卫:beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave

Vuex有哪几种属性?

有五种,分别是 State、 Getter、Mutation 、Action、 Module

  • state => 基本数据(数据源存放地)
  • getters => 从基本数据派生出来的数据
  • mutations => 提交更改数据的方法,同步
  • actions => 像一个装饰器,包裹mutations,使之可以异步。
  • modules => 模块化Vuex

参考 前端进阶面试题详细解答

Vue 中的 key 到底有什么用?

key 是给每一个 vnode 的唯一 id,依靠 key,我们的 diff 操作可以更准确、更快速 (对于简单列表页渲染来说 diff 节点也更快,但会产生一些隐藏的副作用,比如可能不会产生过渡效果,或者在某些节点有绑定数据(表单)状态,会出现状态错位。)

diff 算法的过程中,先会进行新旧节点的首尾交叉对比,当无法匹配的时候会用新节点的 key 与旧节点进行比对,从而找到相应旧节点.

更准确 : 因为带 key 就不是就地复用了,在 sameNode 函数 a.key === b.key 对比中可以避免就地复用的情况。所以会更加准确,如果不加 key,会导致之前节点的状态被保留下来,会产生一系列的 bug。

更快速 : key 的唯一性可以被 Map 数据结构充分利用,相比于遍历查找的时间复杂度 O(n),Map 的时间复杂度仅仅为 O(1)

Vue 单页应用与多页应用的区别

概念:

  • SPA单页面应用(SinglePage Web Application),指只有一个主页面的应用,一开始只需要加载一次js、css等相关资源。所有内容都包含在主页面,对每一个功能模块组件化。单页应用跳转,就是切换相关组件,仅仅刷新局部资源。
  • MPA多页面应用 (MultiPage Application),指有多个独立页面的应用,每个页面必须重复加载js、css等相关资源。多页应用跳转,需要整页资源刷新。

什么是 MVVM?

Model–View–ViewModel (MVVM) 是一个软件架构设计模式,由微软 WPF 和 Silverlight 的架构师 Ken Cooper 和 Ted Peters 开发,是一种简化用户界面的事件驱动编程方式。由 John Gossman(同样也是 WPF 和 Silverlight 的架构师)于2005年在他的博客上发表

MVVM 源自于经典的 Model–View–Controller(MVC)模式 ,MVVM 的出现促进了前端开发与后端业务逻辑的分离,极大地提高了前端开发效率,MVVM 的核心是 ViewModel 层,它就像是一个中转站(value converter),负责转换 Model 中的数据对象来让数据变得更容易管理和使用,该层向上与视图层进行双向数据绑定,向下与 Model 层通过接口请求进行数据交互,起呈上启下作用

(1)View 层

View 是视图层,也就是用户界面。前端主要由 HTML 和 CSS 来构建 。

(2)Model 层

Model 是指数据模型,泛指后端进行的各种业务逻辑处理和数据操控,对于前端来说就是后端提供的 api 接口。

(3)ViewModel 层

ViewModel 是由前端开发人员组织生成和维护的视图数据层。在这一层,前端开发者对从后端获取的 Model 数据进行转换处理,做二次封装,以生成符合 View 层使用预期的视图数据模型。需要注意的是 ViewModel 所封装出来的数据模型包括视图的状态和行为两部分,而 Model 层的数据模型是只包含状态的,比如页面的这一块展示什么,而页面加载进来时发生什么,点击这一块发生什么,这一块滚动时发生什么这些都属于视图行为(交互),视图状态和行为都封装在了 ViewModel 里。这样的封装使得 ViewModel 可以完整地去描述 View 层。

MVVM 框架实现了双向绑定,这样 ViewModel 的内容会实时展现在 View 层,前端开发者再也不必低效又麻烦地通过操纵 DOM 去更新视图,MVVM 框架已经把最脏最累的一块做好了,我们开发者只需要处理和维护 ViewModel,更新数据视图就会自动得到相应更新。这样 View 层展现的不是 Model 层的数据,而是 ViewModel 的数据,由 ViewModel 负责与 Model 层交互,这就完全解耦了 View 层和 Model 层,这个解耦是至关重要的,它是前后端分离方案实施的重要一环。

我们以下通过一个 Vue 实例来说明 MVVM 的具体实现,有 Vue 开发经验的同学应该一目了然:

(1)View 层

<div id="app">
    <p>{{message}}</p>
    <button v-on:click="showMessage()">Click me</button>
</div>

(2)ViewModel 层

var app = new Vue({
    el: '#app',
    data: {  // 用于描述视图状态   
        message: 'Hello Vue!', 
    },
    methods: {  // 用于描述视图行为  
        showMessage(){
            let vm = this;
            alert(vm.message);
        }
    },
    created(){
        let vm = this;
        // Ajax 获取 Model 层的数据
        ajax({
            url: '/your/server/data/api',
            success(res){
                vm.message = res;
            }
        });
    }
})

(3) Model 层

{
    "url": "/your/server/data/api",
    "res": {
        "success": true,
        "name": "IoveC",
        "domain": "www.cnblogs.com"
    }
}

Vue template 到 render 的过程

vue的模版编译过程主要如下:template -> ast -> render函数

vue 在模版编译版本的码中会执行 compileToFunctions 将template转化为render函数:

// 将模板编译为render函数const { render, staticRenderFns } = compileToFunctions(template,options//省略}, this)

CompileToFunctions中的主要逻辑如下∶ (1)调用parse方法将template转化为ast(抽象语法树)

constast = parse(template.trim(), options)

  • parse的目标:把tamplate转换为AST树,它是一种用 JavaScript对象的形式来描述整个模板。
  • 解析过程:利用正则表达式顺序解析模板,当解析到开始标签、闭合标签、文本的时候都会分别执行对应的 回调函数,来达到构造AST树的目的。

AST元素节点总共三种类型:type为1表示普通元素、2为表达式、3为纯文本

(2)对静态节点做优化

optimize(ast,options)

这个过程主要分析出哪些是静态节点,给其打一个标记,为后续更新渲染可以直接跳过静态节点做优化

深度遍历AST,查看每个子树的节点元素是否为静态节点或者静态节点根。如果为静态节点,他们生成的DOM永远不会改变,这对运行时模板更新起到了极大的优化作用。

(3)生成代码

const code = generate(ast, options)

generate将ast抽象语法树编译成 render字符串并将静态部分放到 staticRenderFns 中,最后通过 new Function(`` render``) 生成render函数。

Vue3.0 为什么要用 proxy?

在 Vue2 中, 0bject.defineProperty 会改变原始数据,而 Proxy 是创建对象的虚拟表示,并提供 set 、get 和 deleteProperty 等处理器,这些处理器可在访问或修改原始对象上的属性时进行拦截,有以下特点∶

  • 不需用使用 Vue.$setVue.$delete 触发响应式。
  • 全方位的数组变化检测,消除了Vue2 无效的边界情况。
  • 支持 Map,Set,WeakMap 和 WeakSet。

Proxy 实现的响应式原理与 Vue2的实现原理相同,实现方式大同小异∶

  • get 收集依赖
  • Set、delete 等触发依赖
  • 对于集合类型,就是对集合对象的方法做一层包装:原方法执行后执行依赖相关的收集或触发逻辑。

Vue中如何检测数组变化

前言

Vue 不能检测到以下数组的变动:

  • 当你利用索引直接设置一个数组项时,例如:vm.items[indexOfItem] = newValue
  • 当你修改数组的长度时,例如:vm.items.length = newLength

Vue 提供了以下操作方法

// Vue.set
Vue.set(vm.items, indexOfItem, newValue)
// vm.$set,Vue.set的一个别名
vm.$set(vm.items, indexOfItem, newValue)
// Array.prototype.splice
vm.items.splice(indexOfItem, 1, newValue)

分析

数组考虑性能原因没有用 defineProperty 对数组的每一项进行拦截,而是选择对 7 种数组(push,shift,pop,splice,unshift,sort,reverse)方法进行重写(AOP 切片思想)

所以在 Vue 中修改数组的索引和长度是无法监控到的。需要通过以上 7 种变异方法修改数组才会触发数组对应的 watcher 进行更新

  • 用函数劫持的方式,重写了数组方法,具体呢就是更改了数组的原型,更改成自己的,用户调数组的一些方法的时候,走的就是自己的方法,然后通知视图去更新
  • 数组里每一项可能是对象,那么我就是会对数组的每一项进行观测,(且只有数组里的对象才能进行观测,观测过的也不会进行观测)

原理

Vuedata 中的数组,进行了原型链重写。指向了自己定义的数组原型方法,这样当调用数组api 时,可以通知依赖更新,如果数组中包含着引用类型。会对数组中的引用类型再次进行监控。

手写简版分析

let oldArray = Object.create(Array.prototype);
['shift', 'unshift', 'push', 'pop', 'reverse','sort'].forEach(method => {
    oldArray[method] = function() { // 这里可以触发页面更新逻辑
        console.log('method', method)
        Array.prototype[method].call(this,...arguments);
    }
});
let arr = [1,2,3];
arr.__proto__ = oldArray;
arr.unshift(4);

源码分析

// 拿到数组原型拷贝一份
const arrayProto = Array.prototype 
// 然后将arrayMethods继承自数组原型
// 这里是面向切片编程思想(AOP)--不破坏封装的前提下,动态的扩展功能
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) 
        // 这句话是关键
        // this代表的就是数据本身 比如数据是{a:[1,2,3]} 那么我们使用a.push(4)  this就是a  ob就是a.__ob__ 这个属性就是上段代码增加的 代表的是该数据已经被响应式观察过了指向Observer实例
        const ob = this.__ob__ 

        // 这里的标志就是代表数组有新增操作
        let inserted
        switch (method) { 
            case 'push': 
            case 'unshift': 
                inserted = args 
                break 
            case 'splice': 
                inserted = args.slice(2) 
                break 
        }
        // 如果有新增的元素 inserted是一个数组 调用Observer实例的observeArray对数组每一项进行观测
        if (inserted) ob.observeArray(inserted) 

        ob.dep.notify() // 当调用数组方法后,手动通知视图更新 

        return result 
    }) 
})

this.observeArray(value) // 进行深度监控

vue3:改用 proxy ,可直接监听对象数组的变化

写过自定义指令吗 原理是什么

指令本质上是装饰器,是 vue 对 HTML 元素的扩展,给 HTML 元素增加自定义功能。vue 编译 DOM 时,会找到指令对象,执行指令的相关方法。

自定义指令有五个生命周期(也叫钩子函数),分别是 bind、inserted、update、componentUpdated、unbind

1. bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。

2. inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。

3. update:被绑定于元素所在的模板更新时调用,而无论绑定值是否变化。通过比较更新前后的绑定值,可以忽略不必要的模板更新。

4. componentUpdated:被绑定元素所在模板完成一次更新周期时调用。

5. unbind:只调用一次,指令与元素解绑时调用。

如何在组件中重复使用Vuex的mutation

使用mapMutations辅助函数,在组件中这么使用

import { mapMutations } from 'vuex'
methods:{
    ...mapMutations({
        setNumber:'SET_NUMBER',
    })
}

然后调用this.setNumber(10)相当调用this.$store.commit('SET_NUMBER',10)

常见的事件修饰符及其作用

  • .stop:等同于 JavaScript 中的 event.stopPropagation() ,防止事件冒泡;
  • .prevent :等同于 JavaScript 中的 event.preventDefault() ,防止执行预设的行为(如果事件可取消,则取消该事件,而不停止事件的进一步传播);
  • .capture :与事件冒泡的方向相反,事件捕获由外到内;
  • .self :只会触发自己范围内的事件,不包含子元素;
  • .once :只会触发一次。

Vue 3.0 中的 Vue Composition API?

在 Vue2 中,代码是 Options API 风格的,也就是通过填充 (option) data、methods、computed 等属性来完成一个 Vue 组件。这种风格使得 Vue 相对于 React极为容易上手,同时也造成了几个问题:

  1. 由于 Options API 不够灵活的开发方式,使得Vue开发缺乏优雅的方法来在组件间共用代码。
  2. Vue 组件过于依赖this上下文,Vue 背后的一些小技巧使得 Vue 组件的开发看起来与 JavaScript 的开发原则相悖,比如在methods 中的this竟然指向组件实例来不指向methods所在的对象。这也使得 TypeScript 在Vue2 中很不好用。

于是在 Vue3 中,舍弃了 Options API,转而投向 Composition API。Composition API本质上是将 Options API 背后的机制暴露给用户直接使用,这样用户就拥有了更多的灵活性,也使得 Vue3 更适合于 TypeScript 结合。

如下,是一个使用了 Vue Composition API 的 Vue3 组件:

<template>
  <button @click="increment">
    Count: {{ count }}  </button>
</template>

<script>
// Composition API 将组件属性暴露为函数,因此第一步是导入所需的函数
import { ref, computed, onMounted } from 'vue'

export default {  setup() {
// 使用 ref 函数声明了称为 count 的响应属性,对应于Vue2中的data函数
    const count = ref(0) 
// Vue2中需要在methods option中声明的函数,现在直接声明
    function increment() {      count.value++    } // 对应于Vue2中的mounted声明周期
    onMounted(() => console.log('component mounted!'))     return {      count,      increment    }  }}
</script>

显而易见,Vue Composition API 使得 Vue3 的开发风格更接近于原生 JavaScript,带给开发者更多地灵活性

DIFF算法的原理

在新老虚拟DOM对比时:

  • 首先,对比节点本身,判断是否为同一节点,如果不为相同节点,则删除该节点重新创建节点进行替换
  • 如果为相同节点,进行patchVnode,判断如何对该节点的子节点进行处理,先判断一方有子节点一方没有子节点的情况(如果新的children没有子节点,将旧的子节点移除)
  • 比较如果都有子节点,则进行updateChildren,判断如何对这些新老节点的子节点进行操作(diff核心)。
  • 匹配时,找到相同的子节点,递归比较子节点

在diff中,只对同层的子节点进行比较,放弃跨级的节点比较,使得时间复杂从O(n3)降低值O(n),也就是说,只有当新旧children都为多个子节点时才需要用核心的Diff算法进行同层级比较。

Vuex和单纯的全局对象有什么区别?

  • Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
  • 不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样可以方便地跟踪每一个状态的变化,从而能够实现一些工具帮助更好地了解我们的应用。

Vue 组件间通信有哪几种方式?

Vue 组件间通信是面试常考的知识点之一,这题有点类似于开放题,你回答出越多方法当然越加分,表明你对 Vue 掌握的越熟练。Vue 组件间通信只要指以下 3 类通信:父子组件通信、隔代组件通信、兄弟组件通信,下面我们分别介绍每种通信方式且会说明此种方法可适用于哪类组件间通信。

(1)props / $emit 适用 父子组件通信 这种方法是 Vue 组件的基础,相信大部分同学耳闻能详,所以此处就不举例展开介绍。

(2)ref 与 $parent / $children 适用 父子组件通信

  • ref:如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例
  • $parent / $children:访问父 / 子实例

(3)EventBus ($emit / $on) 适用于 父子、隔代、兄弟组件通信 这种方法通过一个空的 Vue 实例作为中央事件总线(事件中心),用它来触发事件和监听事件,从而实现任何组件间的通信,包括父子、隔代、兄弟组件。

(4)$attrs/$listeners 适用于 隔代组件通信

  • $attrs:包含了父作用域中不被 prop 所识别 (且获取) 的特性绑定 ( class 和 style 除外 )。当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定 ( class 和 style 除外 ),并且可以通过 v-bind="$attrs" 传入内部组件。通常配合 inheritAttrs 选项一起使用。
  • $listeners:包含了父作用域中的 (不含 .native 修饰器的) v-on事件监听器。它可以通过 v-on="$listeners" 传入内部组件

(5)provide / inject 适用于 隔代组件通信 祖先组件中通过 provider 来提供变量,然后在子孙组件中通过 inject 来注入变量。 provide / inject API 主要解决了跨级组件间的通信问题,不过它的使用场景,主要是子组件获取上级组件的状态,跨级组件间建立了一种主动提供与依赖注入的关系。 (6)Vuex 适用于 父子、隔代、兄弟组件通信 Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。每一个 Vuex 应用的核心就是 store(仓库)。“store” 基本上就是一个容器,它包含着你的应用中大部分的状态 ( state )。

  • Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
  • 改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化。

如何获取页面的hash变化

(1)监听$route的变化

// 监听,当路由发生变化的时候执行
watch: {
  $route: {
    handler: function(val, oldVal){
      console.log(val);
    },
    // 深度观察监听
    deep: true
  }
},

(2)window.location.hash读取#值 window.location.hash 的值可读可写,读取来判断状态是否改变,写入时可以在不重载网页的前提下,添加一条历史访问记录。

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

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

相关文章

使用Mock技术帮助提升测试效率的小tips,你知道几个?

Mock是什么&#xff1f; 我给你描述一下这几个场景&#xff0c;你看看是不是熟悉的呢&#xff1f; 测试一个业务模块&#xff0c;这个业务模块中有几个接口对接到了第三方&#xff0c;因为第三方延期交付&#xff0c;导致项目延期&#xff0c;我又背锅了 我想测试前端页面字体…

作为测试人员,你需要掌握哪些,常用软件测试工具?

前言 作为软件测试人员&#xff0c;你最常用到的测试工具都有哪些呢&#xff1f;本文总结了测试过程中常用的工具&#xff0c;希望对从业人员日常工作有所助益&#xff01; 包含工具内容 测试管理工具 连接服务器 抓包工具 接口测试工具 app自动化工具 性能测试工具 持续集成…

[附源码]计算机毕业设计Node.js橙光公司网站设计论文(程序+LW)

项目运行 环境配置&#xff1a; Node.js最新版 Vscode Mysql5.7 HBuilderXNavicat11Vue。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分离等等。 环境需要 1.运行环境&#xff1a;最好是Nodejs最新版&#xff0c;我…

nodejs+vue067高校 校园疫情防控系统

录 1 绪论 1 1.1 研究背景 1 1.2 研究现状 1 1.3 研究内容 2 2 系统关键技术 3 2.3 MYSQL数据库 4 2.4 B/S结构 4 3 系统分析 5 3.1 可行性分析 5 3.1.1 技术可行性 5 3.1.2经济可行性 5 3.1.3操作可行性 5 3.2 系统性能分析 5 3.3 …

Windows10下用Vscode配置OpenCV (解包即用版)

Windows10下用Vscode配置OpenCV (解包即用版) 维基百科&#xff1a; OpenCV的全称是Open Source Computer Vision Library&#xff0c;是一个跨平台的计算机视觉库。OpenCV是由英特尔公司发起并参与开发&#xff0c;以BSD许可证授权发行&#xff0c;可以在商业和研究领域中免费…

三、详细功能

详细功能 1.去除不同数据库间重复的文献&#xff1a;Reference->Find Duplicates &#xff08;1&#xff09;找到4篇重复的文章&#xff1a;Keep this record可以一篇篇的保留、删除 &#xff08;2&#xff09;按Cancel再按ctrl找到所有重复&#xff1a; &#xff08;3&am…

长达22643字的博客:自定义游戏三子棋超详细解说手把手式教学,人机大战,PVP玩家对战功能制作详解

&#x1f992;这个游戏相信大家都听过&#xff0c;三子棋&#xff0c;不就是井字棋吗&#xff1f;那么今天我们就来亲手制作一个三子棋游戏&#xff0c;实现人机“智能”大战以及玩家PVP对战。 &#x1f412;三子棋的基本功能构思 &#x1f992;面对一个较大的游戏程序我们要做…

(附源码)Springboot社区疫情防控管理系统 毕业设计 164621

Springboot 社区疫情防控管理系统 摘 要 信息化社会内需要与之针对性的信息获取途径&#xff0c;但是途径的扩展基本上为人们所努力的方向&#xff0c;由于站在的角度存在偏差&#xff0c;人们经常能够获得不同类型信息&#xff0c;这也是技术最为难以攻克的课题。针对社区疫情…

校园生活互助网站

开发工具(eclipse/idea/vscode等)&#xff1a; 数据库(sqlite/mysql/sqlserver等)&#xff1a; 功能模块(请用文字描述&#xff0c;至少200字)&#xff1a; 体智慧校园生活互助系统主要实现以下功能&#xff1a; (一)网站前台&#xff1a;关于我们、联系我们、公告信息、求助信…

DataGear 添加 Http 数据集是请求头 JSON 的格式说明

背景 玩了一下 DataGear &#xff0c;添加了一个 Http 接口的数据集&#xff0c;由于目标接口请求必须包含 Token 信息&#xff0c;所以按照配置提示添加 JSON 格式的头信息时&#xff0c;想象成了 JSON 对象&#xff0c;结果预览请求始终报错。 DataGear 的后台异常信息&…

【JUC】JMM内存模型

JMM是什么 JMM是Java内存模型&#xff0c;也就是Java Memory Model&#xff0c;简称JMM&#xff0c;本身是一种抽象的概念,并不真实存在&#xff0c;它描述的是一组规则或规范&#xff0c;通过这组规范定义了程序中各个变量&#xff08;包括实例字段&#xff0c;静态字段和构成…

Graphviz 排版思路 Graphviz 如何控制节点位置

有个画图需求是需要生成特定排版的关系图。 graphviz 对于一般情况都是自动排的&#xff0c;有时候会抽风&#xff0c;比如这种情况&#xff1a; 而我们想要这样&#xff1a; 对初学者提一下 &#xff0c;如何实现 3 2 5 &#xff0c;1467 从左到右排列呢&#xff1f;待会会顺…

HTML小游戏18 —— html5版街头霸王游戏(附完整源码)

&#x1f482; 网站推荐:【神级源码资源网】【摸鱼小游戏】&#x1f91f; 前端学习课程&#xff1a;&#x1f449;【28个案例趣学前端】【400个JS面试题】&#x1f485; 想寻找共同学习交流、摸鱼划水的小伙伴&#xff0c;请点击【摸鱼学习交流群】&#x1f4ac; 免费且实用的计…

【Three.js】Three.js快速上手教程

1. Three.js简介 官网对 Three.js 的介绍非常简单&#xff1a;“Javascript 3D library”。 即&#xff1a;three.js是JavaScript编写的WebGL第三方库。提供了非常多的3D显示功能&#xff0c;是一个常见的web 3D库。 相关概念解释&#xff1a;three.js > webGL > openG…

QT QTabWidget 控件 使用详解

本文详细的介绍了QTabWidget控件的各种操作&#xff0c;例如&#xff1a;新建界面、设置页面名字、设置提示信息、设置页面激活、设置标题栏位置、设置页面关闭按钮、设置页面关闭按钮、获取页面下标、获取页面总数、清空所有页面、删除某个页面、设置拖拽移动、设置显示页面、…

全国职业技能大赛网络安全-金砖技能大赛——应急响应内存镜像分析(超详细解析)

全国职业技能大赛网络安全-金砖技能大赛——应急响应内存镜像分析&#xff08;超详细解析&#xff09; 背景&#xff1a;作为信息安全技术人员必须能够掌握内容镜像分析、重要数据恢复、 恶意文件分析等相关技能&#xff0c;利用这些技能我们能够第一时间分析相关恶意文件、 分…

美少女怒肝20天用C语言写出的排序集合

文章目录 排序的概念一、常见的排序算法二、代码实现总结排序的概念 排序&#xff1a;所谓排序&#xff0c;就是使一串记录&#xff0c;按照其中的某个或某些关键字的大小&#xff0c;递增或递减的排列起来的操作。稳定性&#xff1a;假定在待排序的记录序列中&#xff0c;存在…

作为前端,你是否了解链表这种数据结构?

在面试中只要被问到React Hooks就常被问到为什么Hooks不能在循环和条件判断嵌套函数当中使用&#xff1b;相信很多人都知道标准答案&#xff0c;【因为声明的Hooks保存在链表当中】&#xff0c;但是你真的知道链表吗&#xff1f; 什么是链表 我们先看来看一个简单的单向链表结…

华为珍藏版:SpringBoot全优笔记,面面俱到太全了

前言 作为开发人员&#xff0c;对于Spring全家桶肯定是不陌生的&#xff0c;而来自于Spring大家族的Spring Boot&#xff0c;作为Spring团队提供的流行框架&#xff0c;它的存在解决的Spring框架使用较为繁琐的问题&#xff0c;所以掌握SpringBoot是精通Spring必不可少的一个过…

[附源码]Python计算机毕业设计Django血库管理系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…