- 博客(77)
- 收藏
- 关注
原创 算法——希尔排序
希尔排序希尔排序是插入排序的一种高效的改进版,并且效率比插入排序要更快,因为它突破了时间复杂度为O(n^2的限制)。由于希尔排序是基于插入排序的,所以有必要回顾一下插入排序:插入排序的问题:1,假设一个很小的数据项在很靠近右端的位置上,这里本来应该是较大的数据项的位置。2,把这个小数据项移动到左边的正确位置,那么所有的中间数据项都必须向右移动一位。3,因此我们通常认为插入排序的时间复杂度为O(n^2)。4,如果有某种方式,不需要一个个移动所有中间的数据项,就能把较小的数据项移动到左边,那么这个算
2022-03-09 10:59:43 771
原创 插入排序(insertionSort)
插入排序插入排序是简单排序中效率最好的一种,它也是学习其他高级排序的基础,比如希尔排序/快速排序,所以非常重要,而它相对于选择排序的优点就在于比较次数几乎是少了一半。插入排序的思路:(1)从第一个元素开始,该元素可以认为已经被排序。(2)取出下一个元素,在已经排序的元素序列中从后向前扫描。(3)如果该元素(已排序)大于新元素,则将该元素移动到下一个位置。(4)重复上一个步骤,直到找到已排序的元素小于或者等于新元素的位置,将新元素插入到该位置后,重复上面的步骤。如图所示:function i
2022-03-04 09:50:18 9001 12
原创 2022.1.5 犹豫不决的开始
想了很久,却迟迟无法下笔,算了,随心所欲的写吧!其实这篇日记应该是属于昨天的,但是由于昨晚大概是10点左右开始玩王者吧,玩起来就不想学习了,当然也就没有心情再去写本该昨天完成的日记了。昨天是元旦假期之后,是大家开始正式上班工作的一天,所以我也不能再歇着了,于是早早起了床,去餐厅买了自己一直惦记着的寇记大包,买了两个鲜肉包吃着很爽,有点渴也是买了一杯豆浆哐哐就给喝完了,唯一可惜的是没有我必吃的鸡蛋了,说断供了。当然了,吃早餐的同时肯定是要看会我没看完的《长津湖》这种感觉真的是很爽。吃完早餐,写了会小程序
2022-01-05 10:02:54 246
原创 指令
自定义指令认识自定义指令在vue的模板语法中我们学习过各种各样的指令:v-show、v-for、v-model等等,除了使用这些指令之外,vue也允许我们来自定义自己的指令,注意:在vue中,代码的复用和抽象主要还是通过组件实现,但是通常在某些情况下,你需要对DOM元素进行底层操作,这个时候就会用到自定义指令,以下是自定义指令的两种类型:(1)局部指令:组件中通过directives选项,只能在当前组件中使用。(2)全局指令:app的directive方法,可以在任意组件中被使用。比如我们来做一个
2021-09-12 09:19:45 185
原创 composition api学习——数据响应式处理
vue3中要求数据如果依然是响应式的话,必须在定义数据时通过以下方式去对数据做一个处理(因为vue3中使用proxy的方式对这些api做了监听):Reactive API如果想为在setup中定义的数据提供响应式的特性,我们则必须使用reactive这个函数对定义的数据进行一个包裹,那么为什么这样数据就会变成响应式的呢?这是因为当我们使用reactive函数处理我们的数据之后 ,数据再次被使用时就会进行依赖收集,当数据发生改变时,所有收集到的依赖都会进行对应的响应式操作(比如更新界面); 事实上,我们
2021-09-12 08:26:14 288
原创 ref的使用
ref的使用在react的开发模式中,通常情况下不需要、也不建议直接操作DOM;但是某些特殊的情况,确实需要获取到DOM进行某些操作,如何通过创建ref来获取对应的DOM元素呢?目前有三种方式(首先需要说明的是,在这里既然有了ref,就不会再通过document的方式去直接操作DOM了)import React, { PureComponent, createRef, Component } from 'react';class Counter extends PureComponent { c
2021-09-10 11:22:13 342
原创 简单聊聊大家所常说的浅拷贝、深拷贝
数据存储问题基本数据类型因为占用内存较小从而存储在栈内存中,方便查找,同时当基本类型的变量互相赋值时,不会出现值共享问题(即污染变量)。而引用数据类型因为存储在堆内存中,通过一个引用(即内存地址)指向其在堆内存中的空间,因此互相赋值的时候便会出现引用值共享问题。那么如何解决这个问题呢?浅拷贝let arr = [1, 2, 3];let newArr = arr;newArr[0] = 100;console.log(arr);//[100, 2, 3]这是直接赋值的情况,不涉及任何拷贝
2021-09-08 09:01:54 268
原创 javascript数据类型中——null和undefined的区别
null和undefined的区别对于大多数计算机语言,有且仅有一个表示"无"的值,比如:C语言的NULL,Java语言的null,Python语言的None。有点奇怪的是,JavaScript语言居然有两个表示"无"的值:undefined和null。这是为什么呢?在JavaScript中,将一个变量赋值为undefined或null,老实说,几乎没啥区别。因为undefined和null在if语句中,都会被自动转为false;相等运算符甚至直接报告两者相等。//undefined和null在if
2021-09-08 08:13:27 134
原创 js的单线程问题
js的单线程问题js是单线程的,其工作原理是将每一个任务切分成多个片段然后交给v8引擎去快速交替按照顺序执行这些片段,这个过程也称为轮转时间片。注意:我们可以借助于 web worker 来模拟实现多线程:worker线程的基础概念web worker 线程的作用就是给 js 创造多线程运行环境,它允许主线程创建一个worker线程,主线程运行的同时worker线程也在运行,两者互不干扰,worker线程运行结束后会将运行的最终结果返回给主线程。这样做的好处是主线程可以把计算密集型或高延迟的任务交给
2021-09-08 07:52:50 443
原创 组件间的通信方式
父子组件间的通信父传子:子组件会通过props获取到父组件传递过来的数据(这个和vue一样)这里需要注意一下:对于传递给子组件的数据,有时候我们可能希望对其进行验证,尤其是对于大型项目来说: (1)如果项目中使用了ts,那么可以直接进行类型验证。 (2)如果没有的话,也可以通过prop-types库进行类型验证。import React, { Component } from 'react';import PropTypes from 'prop-types';function Chil
2021-09-07 08:35:23 205
原创 this的绑定问题
this的绑定问题在事件执行后,我们可能需要获取当前类的对象中相关的属性,这个时候需要用到this,如果我们这里直接打印this,会发现它是一个undefined为什么是undefined呢?原因是btnClick函数并不是我们主动调用的,而且当button发生改变时,React内部调用了btnClick函数;而它内部调用时,并不知道要如何绑定正确的this;如何解决this的问题呢?方案一:使用bind给btnClick显示绑定this方案二:定义函数时, 使用箭头函数方案三:在事件监听时直
2021-09-07 08:17:11 119
原创 Mixin
认识Mixin在组件和组件之间有时候会存在相同的代码逻辑,我们希望对相同的代码逻辑进行抽取。在vue2和vue3中都支持的一种方式就是使用Mixin来完成:Mixin提供了一种非常灵活的方式,来分发vue组件中的可复用功能。一个Mixin对象可以包含任何组件选项:当组件使用Mixin对象时,所有Mixin对象的选项都将被混合进入该组件本身的选项中。Mixin的合并规则如果Mixin对象中的选项和组件对象中的选项发生了冲突,那么vue会如何进行操作呢?这里分成不同的情况来进行处理:情况一:如果是
2021-09-06 10:52:31 242
原创 Typescript——泛型的学习
泛型认识泛型软件工程的主要目的是构建不仅仅明确一致的API,还要让你的代码具有很强的可重用性:比如我们可以通过函数来封装一些API,通过传入不同的函数参数,让函数帮助我们完成不同的操作;但是对于参数的类型是否也可以参数化呢?什么是类型的参数化?我们来提一个需求:封装一个函数,传入一个参数,并且返回这个参数;如果我们是TypeScript的思维方式,要考虑这个参数和返回值的类型需要一致:function add(num: number): number{ return num;}上面的代
2021-09-05 12:14:54 173
原创 Typescript——接口的学习
接口的声明声明对象类型的2种方式:(1)类型别名的方式:即通过type。(2)接口的方式:即通过interface。至于它们在使用上的区别,后续再进行说明。接口中我们也可以定义可选属性、只读属性。// 通过类型(type)别名来声明对象类型// type InfoType = {name: string, age: number}// 另外一种方式声明对象类型: 接口interface// 在其中可以定义可选类型// 也可以定义只读属性interface IInfoType {
2021-09-05 00:34:25 176
原创 Typescript——函数类型的深入学习
函数类型函数是JavaScript中非常重要的组成部分,typeScript也允许我们指定函数的参数和返回值的类型。声明函数时,可以在每个参数后添加类型注解,用以声明函数接受的参数类型:function sum(num1: number, num2: number) { return num1 + num2}sum(123, 321)我们也可以为函数添加返回值的类型注解,这个注解出现在函数列表的后面:function sum(num1: number, num2: number):nu
2021-09-04 22:46:14 274 2
原创 methods属性
methods属性是一个对象,通常我们会在这个对象中定义很多的方法: 这些方法可以被绑定到 template 模板中;在该方法中,我们便可以使用this关键字来直接访问到data中返回的对象的属性。下面是一段官方文档的描述: 注意:不应该使用箭头函数来定义method中的函数,理由是箭头函数绑定了父级作用域的上下文,所以this将不会按照期望指向组件实例,this.a将是undefined。而根据官方文档的这段描述便可以对以下两个问题作出简要的回答了:问题一:为什么不能使用箭头函数去定义呢?我们
2021-08-30 13:31:24 932
原创 data属性
这里主要解决一个问题:那就是为什么data属性必须是一个函数?首先,需要了解在Vue2.x(注意这里说的是脚手架的版本)的时候,也可以传入一个对象(虽然官方推荐是一个函数);但是在Vue3.x的时候,必须传入一个函数,否则就会直接在浏览器中报错。根据个人理解以及查阅相关资料得知之所以将data属性设置为函数是因为在项目开发中,我们会尽可能的提高组件的复用性,因此如果data属性是一个对象时,那么在复用该组件时,它们的data引用的将都是同一个内存地址,那么多个组件实例之间便可能会在使用时互相产生影响。所
2021-08-30 13:22:08 292
原创 redux-hooks的使用
redux-hooks的使用useDispatch我们在项目中不再使用繁琐的connect函数了,而是借助于redux-hoos的useDispatch来直接dispatch,而不再需要connect的mapStateToDispatch了。useSelector由于我们不再使用connect函数的mapStateToprops了,因此我们需要借助于useSelector来获取到请求回来的数据。接受两个参数: 参数一:它会接受你所想要返回的数据。 参数二:shallowEqual在不使用第
2021-07-27 17:56:56 860
原创 immutableJS的使用
immutableJS的使用数据可变性的问题在React开发中,我们总是会强调数据的不可变性: 无论是对于类组件中的state,还是redux中管理的state都是不建议直接去修改state本身的; 事实上在整个JavaScript编码过程中,数据的不可变性都是非常重要的;数据的可变性引发的问题(案例):我们明明没有修改obj,只是修改了obj2,但是最终obj也被我们修改掉了;原因非常简单,对象是引用类型,它们指向同一块内存空间,两个引用都可以任意修改;有没有办法解决上面的问题呢?进行对象的拷贝即
2021-07-27 17:36:22 467
原创 Typescript——数据类型的深入学习
变量定义声明了类型后typeScript就会进行类型检测,声明的类型称之为类型注解;比如我们声明一个message变量,完整的写法如下:const message: string = "Hello World"注意:这里的string是小写的,和String是有区别的,string是typeScript中定义的字符串类型,而String是ECMAScript中定义的一个类。如果我们给message赋值其他类型的值,那么就会报错。在开发中,有时候为了方便起见我们并不会在声明每一个变量时都写上对应的
2021-07-25 20:51:37 248
原创 Typescript——简单介绍
前言JavaScript因为从设计之初就没有考虑类型约束问题,所以造成了我们前端开发人员关于类型思维的缺失,前端开发人员通常不关心变量或者参数是什么类型的,如果当必须确定函数的参数类型时,我们往往需要使用各种判断验证;比如:(1)当我们去实现一个核心类库时,如果没有类型约束,那么需要对别人传入的参数进行各种验证来保证我们代码的健壮性;(2)当我们去调用别人的函数时,对方并没有对函数进行任何的注释,我们只能去看里面的逻辑来理解这个函数需要传入什么参数,返回值是什么类型;为了弥补javaScript在类
2021-07-25 20:31:45 155
原创 生命周期函数
生命周期1,什么是生命周期每个组件都可能会经历从创建、挂载、更新、卸载等一系列的过程; 在这个过程中的某一个阶段,有可能会想要添加一些属于自己的代码逻辑(比如组件创建完后就请求一些服务器数据);但是我们如何可以知道目前组件正在哪一个过程呢?因此Vue给我们提供了组件的生命周期函数;2,生命周期函数:生命周期函数是一些钩子函数,在某个时间会被Vue源码内部进行回调; 通过对生命周期函数的回调,我们可以知道目前组件正在经历什么阶段; 那么我们就可以在该生命周期中编写属于自己的逻辑代码了;我们前面说过s
2021-07-23 09:13:46 165
原创 ref的使用
ref的使用某些情况下,我们在组件中想要直接获取到元素对象或者子组件实例:在vue开发中我们是不推荐DOM操作的,这个时候,我们可以给元素或者组件绑定一个ref的attribute属性,而组件实例有一个$refs属性。//父组件<template> <div> <!-- 绑定到一个元素上 --> <h2 ref="title">哈哈哈</h2> <!-- 绑定到一个组件实例上 --> <
2021-07-23 08:49:42 173
原创 异步组件的了解
异步组件1,webpack分包机制学习异步组件之前,先来学习一下webpack如何对文件进行分包的(1)默认的打包过程: 默认情况下,在构建整个组件树的过程中,因为组件和组件之间是通过模块化直接依赖的,那么webpack在打包时就会将组件模块打包到一起(比如一个app.js文件中)这个时候随着项目的不断庞大,app.js文件的内容过大,便会造成首屏的渲染速度变慢;(2)打包时,代码的分包: 所以,对于一些不需要立即使用的组件,我们可以单独对它们进行拆分,拆分成一些小的代码块chunk.js
2021-07-23 08:42:59 346
原创 keep-alive内置组件
keep-alive内置组件我们先对上面案例中的组件进行改造,在其中一个组件增加按钮,实现点击可以递增的功能。比如:我们将某个数据发生后了改变,那么希望在切换组件后,切换回来时依然保持这个改变后的数据,那么就需要用到keep-alive这个内置组件了(默认情况下,组件切换时是有完整的重建和销毁的过程的)keep-alive的常用 属性:(1)include:只有名称匹配的组件会被缓存。(2)exclude:任何名称匹配的组件都不会被缓存。(3)max:最多可以缓存多少组件实例,一旦达到这个数字,
2021-07-23 08:16:31 181
原创 动态组件
动态组件比如我们想要实现一个切换组件的功能,这个功能我们可以通过两种不同的实现思路来实现:方式一:通过v-if来判断,显示不同的组件。方式二:动态组件的方式。动态组件是使用component组件,通过一个特殊的attrubute :is来实现。<template> <div> <button v-for="item in tabs" :key="item" @click="itemClick(item)" :
2021-07-23 08:09:16 355
原创 插槽
插槽的使用在开发中,我们会经常封装一个个可复用的组件:前面我们会通过props传递给组件一些数据,让组件来进行展示;但是为了让这个组件具备更强的通用性,我们不能将组件中的内容限制为固定的div、span等等这些元素;比如某种情况下我们希望组件显示的是一个按钮又或者某种情况下我们使用组件希望显示的是一张图片; 因此我们应该让使用者可以决定某一块区域到底存放什么内容和元素;1,插槽的基本使用(1)我们某个组件中有一个插槽,我们可以在插槽中放入需要显示的内容;<template> <
2021-07-23 07:54:00 3488
原创 vue3中事件总线的使用
事件总线Vue3从实例中移除了 on、on、on、off 和 $once 方法,所以我们如果希望继续使用全局事件总线的话,就需要通过第三方库:Vue3官方有推荐一些库,例如 mitt 或 tiny-emitter;这里我们主要说一下mitt库的使用;首先,我们需要先安装这个库:npm install mitt其次,我们为了 避免对其的依赖,因此需要封装成一个单独的eventbus.js文件:import mitt from 'mitt';const emitter = mitt();
2021-07-23 07:03:47 2558 4
原创 Typescript——函数的重载
函数的重载在TypeScript中,如果我们编写了一个add函数,希望可以对字符串和数字类型进行相加,我们可能会使用联合类型来编写,但是使用联合类型会有两个缺点:(1)需要进行很多的逻辑判断(即类型缩小)(2)返回值的类型依然不能确定。function add(a1: number | string, a2: number | string) { if (typeof a1 === "number" && typeof a2 === "number") { return
2021-07-22 15:46:09 1568 1
原创 Typescript——类的使用
类的使用在早期的JavaScript开发中(ES5)我们需要通过函数和原型链来实现类和继承,从ES6开始,引入了class关键字,可以更加方便的定义和使用类。TypeScript作为JavaScript的超集,也是支持使用class关键字的,并且还可以对类的属性和方法等进行静态类型检测。实际上在JavaScript的开发过程中,我们更加习惯于函数式编程:(1)比如React开发中,目前更多使用的函数组件以及结合Hook的开发模式;(2)比如在Vue3开发中,目前也更加推崇使用 Composition
2021-07-22 15:38:23 293 1
原创 读写样式属性的兼容性写法
DOM是无法直接操作css样式的,它只是通过操作元素标签的style属性从而间接操作css样式的。由于我们是无法直接通过DOM操作访问到css样式表的,所以必须通过以下的方法:(1)window.getComputedStyle(elem, null)[prop];(IE8及以下是不支持的)(2)document.currentStyle(只有IE兼容并且IE8及以下是支持的)兼容模式的封装写法:<style> div { width: 200px;
2021-07-22 07:53:42 91
原创 算法——冒泡排序
冒泡排序的思路:(1)比较所有相邻元素,如果第一个比第二个大,则交换它们。(2)一轮下来,可以保证最后一个数是最大的。(3)执行n-1轮,就可以完成排序。Array.prototype.bubbleSort = function () { for (let i = 0; i < this.length - 1; i += 1) { for (let j = 0; j < this.length - 1 - i; j += 1) { if (
2021-07-20 17:50:09 61
原创 个人使用 Git 后的实战总结
基本操作假设你已经安装好git了。安装完成后,还需要最后一步设置:(因为Git是分布式版本控制系统,所以需要填写用户名和邮箱作为一个标识)git config --global user.name '用户名'git config --global user.email '配置用户邮箱'git config --list //查询信息是否配置成功完成后创建一个仓库test:并通过命令 git init 初始化仓库即把这个仓库变成git可以管理的仓库,这时候你当前test目录下就会多了一个.git的
2021-07-20 17:17:00 193
原创 算法设计思想——回溯算法
回溯算法是算法设计中的一种方法,是一种渐进式寻找并构建问题解决方式的策略,它会从一个可能的动作开始解决问题,如果不行,就回溯并选择另一个动作,直到将问题解决 。leetcode 46 全排列/** * 解题思路: * (1)所有排列;没有重复元素。 * (2)有出路,有死路。 * * 解题步骤: * (1)使用递归模拟出所有的情况 * (2)遇到包含重复元素的情况,就回溯 * (3)收集所有到达递归终点的情况并返回 */var permute = function (num
2021-07-20 09:23:50 230
原创 算法设计思想——贪心算法
贪心算法贪心算法是算法设计中的一种方法,期盼通过每个阶段的局部最优选择,从而达到全局的最优,但结果并不一定是最优的。leetcode 455 分发饼干/** * 解题思路: * (1)局部最优:既能满足孩子,还消耗最少 * (2)因此先将‘较小的饼干’分给‘胃口最小的孩子’ * * 解题步骤: * (1)对饼干数组和胃口数组进行升序排序 * (2)遍历饼干数组,找到能满足第一个孩子的饼干 * (3)然后继续遍历饼干数组,找到满足第二、三、····、n个孩子的饼干 */
2021-07-19 22:36:26 364
原创 组件间的通信方式
父子组件间通信基础的传递不再赘述,这里只说明一些重要的注意点。1,父传子:相信大家对父传子都很熟悉,但是其实在这个过程中也是有很多注意事项的。props的两种常见用法:方式一:字符串数组,数组中的字符串就是attribute的名称,数组用法中我们只能说明传入的attribute的名称,并不能对其进行任何形式的限制,所以一般不建议使用。props: ['title', 'content']方式二:对象类型,对象类型我们可以在指定attribute名称的同时,指定它需要传递的类型、是否是必须的、默
2021-07-19 21:47:07 1161
原创 侦听器
侦听器watch需要侦听特定的数据源,并在回调函数中执行副作用;默认情况下它是惰性的,只有当被侦听的数据源发生改变时才会执行回调。watch允许我们:(1)懒执行副作用(当然可以设置deep属性让其立即执行);(2)更具体的说明当哪些状态发生变化时,触发侦听器的执行;(3)访问侦听状态变化前后的值。问题:默认情况下,侦听器只能监听数据本身的改变,并不会监听到数据内部所发生的改变。解决方式:使用对象的方式,从而使用更多的属性(例如:handler、deep)去完成对其内部数据的监听。<d
2021-07-19 21:00:38 279
原创 计算属性
在某些情况下,我们可能需要对数据进行转化或者需要将多个数据结合起来再去显示同时也是为了模板中的表达式更加简洁。computed本质(1)使用computed时,为什么不是通过函数的方式而是通过属性的方式进行使用呢?我们所定义的computed属性里面其实是由get和set方法组成的(而平常使用时调用的其实就是我们computed里面的get方法),我们一般只需要实现computed的get方法就可以了。<template id="my-app"> <h2>{{full
2021-07-19 17:49:42 110
原创 算法设计思想——动态规划
动态规划动态规划是算法设计中的一种方法,它将一个问题分解为相互重叠的子问题,通过反复求解子问题,来解决原来的问题。它与分而治之思想的区别主要在于子问题是否是重叠的,如果子问题是相互独立的那么便使用分而治之,如果子问题是相互重叠的那么便使用动态规划。leetcode 70 爬楼梯/** * 解题思路:爬到第n阶可以在第n-1阶爬1个台阶或者在第n-2阶爬2个台阶,所以我们可以定义这样一个子问题:F(n) = F(n - 1) + F(n - 2); * 解题步骤: * (1)定义子问题:F(n)
2021-07-19 11:11:18 203
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人