Wendy
文章17
标签13
分类6
总结

总结

面试总结

HTML

CSS

CSS盒模型以及有哪几种

标准盒模型(content-box): height=content (浏览器默认)

IE盒模型(border-box):height=content+padding+border

盒模型的种类通过box-sizing设置,如 box-sizing:border:box

flex:1

flex: 1是CSS中用于布局的一个属性,它的作用是指定元素在弹性布局中的伸缩比例。当一个容器中有多个子元素时,可以通过flex属性来控制它们在容器中的占比。

具体来说,flex属性是一个简写属性,包括了flex-grow、flex-shrink和flex-basis三个属性。这三个属性分别代表了弹性容器中的三个伸缩属性:

  • flex-grow属性表示元素的放大比例,默认值为0,即不放大。
  • flex-shrink属性表示元素的缩小比例,默认值为1,即按比例缩小。
  • flex-basis属性表示元素在分配多余空间之前的基准大小,默认值为auto,即根据元素的实际大小来分配空间。

当使用flex:1时,实际上是将flex-grow属性设置为1,其它属性保持默认值。这样,所有具有flex:1样式的子元素都将按照相同的比例来分配容器中的剩余空间,使它们占据相等的空间。

需要注意的是,如果弹性容器中有多个子元素,且它们的flex属性不同,那么它们将按照flex属性的大小来分配空间。如果一个元素的flex属性值为2,而另一个元素的flex属性值为1,则前者占用的空间是后者的两倍。

总之,使用flex:1可以很方便地实现等比例的布局效果,特别是在响应式布局中,可以避免写复杂的媒体查询和计算百分比宽度的麻烦。

画一条0.5px的线

transform:scaleY(0.5)+transfom-origin:50% 100%

内联样式与样式表的区别

内联样式和样式表都是用于设置网页样式的方法,它们的区别在于:

  • 内联样式是直接在HTML元素中设置样式,而样式表是在HTML文档中引用的外部样式文件。
  • 内联样式的优先级比样式表高,即如果同时设置了相同的样式属性,内联样式会覆盖样式表中的设置。
  • 样式表可以应用于多个HTML元素,而内联样式只能应用于单个元素。
  • 样式表可以通过媒体查询设置响应式样式,而内联样式不能。

综上所述,虽然内联样式和样式表都可以用于设置网页样式,但样式表更加灵活、可维护性更好,适用于大规模的网站开发。而内联样式则适用于少量样式的个别元素设置。

内联样式的优先级更高,是在标签中的属性中添加

样式表是写在style标签中用的

如何实现水平垂直居中

  1. 可以用table形式实现(display:table)
  2. 可以用弹性盒子的方式(display:flex)推荐
    • justify-content: center;
    • align-items: center;
  3. 网格布局(display:grid)
    • align-self: center;
    • justify-self: center;

Javascript

js性能的优化

  • 减少DOM操作:DOM操作是一项非常消耗性能的操作,因此应该尽可能减少DOM操作次数。可以考虑使用innerHTML代替大量的DOM操作,或者使用文档片段(DocumentFragment)等技术来减少DOM操作次数。
1
2
3
4
5
6
常见的DOM操作包括:
获取元素:通过getElementById、getElementsByTagName、getElementsByClassName等方法获取页面元素。
修改元素属性:通过setAttribute、removeAttribute、className等方法修改元素属性。
修改元素内容:通过innerHTML、textContent等属性或者innerText、appendChild等方法修改元素内容。
添加元素:通过createElement、createTextNode、appendChild等方法添加新的元素。
删除元素:通过removeChild等方法删除元素。
  • 避免全局变量:在JavaScript中,全局变量的访问比局部变量的访问要慢得多,因此应该尽可能避免使用全局变量。可以使用闭包或模块模式等技术来封装变量,或者使用ES6中的let和const来声明变量。

  • 避免重复计算:在一些复杂的算法中,重复计算可能会导致性能问题。可以将计算结果缓存起来,避免重复计算。例如,可以将某个函数的计算结果缓存到对象中,下次调用时直接从缓存中获取结果。

  • 使用事件委托:事件委托是一种优化性能的常见方法。它通过将事件处理程序绑定到父元素上,而不是绑定到每个子元素上,从而减少了事件处理程序的数量。这样可以减少内存占用和提高性能。

  • 使用异步加载:异步加载可以提高页面的加载速度,从而提高性能。可以使用异步加载技术来加载JavaScript文件、CSS文件等资源。

  • 使用缓存:JavaScript代码可以被缓存到客户端,从而减少服务器负载和提高性能。可以使用HTTP缓存、本地存储等技术来缓存JavaScript代码。

  • 代码优化:JavaScript代码的优化可以提高代码的执行效率和性能。例如,可以尽可能使用简单的算法,避免过多的循环嵌套等。

总的来说,JavaScript性能的优化是一个复杂的过程,需要在实际项目中根据具体情况进行调优。以上是一些常见的优化方法,可以作为参考。

Js跨域的定义

当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域。

this的作用

  1. 全局代码中的this是指向全局对象,在浏览器中是window
  2. 作为单纯的函数调用,在普通函数中的this,指向了全局函数,即window ,在严格模式下,是undefined
  3. 作为对象的方法调用,this指向当前对象
  4. 作为构造函数内部的this指向新创建的对象
  5. 内部函数
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    var name = "clever coder";  
    var person = {
    name : "foocoder",
    hello : function(sth){
    var sayhello = function(sth) {
    console.log(this.name + " says " + sth);
    };
    sayhello(sth);
    }
    }
    person.hello("hello world");//clever coder says hello world
    在内部函数中,this没有按预想的绑定到外层函数对象上,而是绑定到了全局对象。这里普遍被认为是JavaScript语言的设计错误,因为没有人想让内部函数中的this指向全局对象。一般的处理方式是将this作为变量保存下来,一般约定为that或者self:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    var name = "clever coder";  
    var person = {
    name : "foocoder",
    hello : function(sth){
    var that = this;
    var sayhello = function(sth) {
    console.log(that.name + " says " + sth);
    };
    sayhello(sth);
    }
    }
    person.hello("hello world");//foocoder says hello world

js实现继承的方式

事件捕获与事件冒泡

事件冒泡是由里到外,向上层延申;
事件捕获是由外到里,前往捕获,形成向下趋势。

图片懒加载如何实现?

  1. img元素的自定义属性上data-xxx上挂载目标图片url, src属性指向默认图片地址。
  2. 监听图片是否出现在用户的可视区域内。
  3. 出现在可视区域内后更新src属性为目标图片url。

js实现代理和事件冒泡的区别

  • 事件代理:把原本需要绑定在子元素上的事件(onclick、onkeydown 等)委托给它的父元素,让父元素来监听子元素的冒泡事件,并在子元素发生事件冒泡时找到这个子元素。
  • 事件冒泡: 当一个子元素的事件被触发的时候(如onclick事件),该事件会从事件源(被点击的子元素)开始逐级向上传播,触发父级元素的点击事件。

防抖节流的区别

防抖(debounce): 所谓防抖,就是指触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。

节流(throttle): 所谓节流,就是指连续触发事件但是在 n 秒中只执行一次函数。节流会稀释函数的执行频率。

防抖:在单位时间内频繁触发事件,只有最后一次生效
节流:在单位时间内频繁触发事件,只生效一次(也就是只有第一次生效)

相同点
1.都可以通过使用 setTimeout 来实现
2.都可以降低回调执行频率,节省计算资源

闭包

闭包是指有权访问另一个函数作用域中变量的函数,创建闭包的最常见的方式就是在一个函数内创建另一个函数,创建的函数可以访问到当前函数的局部变量。

闭包的特点

  1. 让外部访问函数内部变量变成可能
  2. 变量会常驻在内存中
  3. 可以避免使用全局变量防止全局变量污染

好处:可以读取其他函数内部的变量,并将其一直保存在内存中。
坏处:可能会造成内存泄漏或溢出

两个常见用途:

  • 闭包的第一个用途是使我们在函数外部能够访问到函数内部的变量。通过使用闭包,可以通过在外部调用闭包函数,从而在外部访问到函数内部的变量,可以使用这种方法来创建私有变量。
  • 闭包的另一个用途是使已经运行结束的函数上下文中的变量对象继续留在内存中,因为闭包函数保留了这个变量对象的引用,所以这个变量对象不会被回收。

点击事件代理的几种方式

var dom = document.getElementByClasses(“first”);  

dom[0].onclick = function(){alert(111);};  

dom[0].onclick = function(){alert(222);}; 

这里千万注意!!!
这种做法只能绑定一个事件处理函数,后面的会覆盖前面的。比如这里只会输出222,这只是其中一种

还有写了监听器和两个内联的。

监听器的三个参数代表了什么含义

第一个参数是事件类型,比如点击(click)、双击(dbclick)

第二个参数就是函数,触发事件后,需要执行的函数。

第三个参数就是事件的捕获与冒泡, 为true时捕获,false时冒泡。

ES6

原型与原型链

每一个构造函数的内部都有一个 prototype 属性值,这个属性值是一个对象,这个对象包含了可以由该构造函数的所有实例共享的属性和方法。当我们使用构造函数新建一个对象,在这个对象的内部将包含一个指针,这个指针指向构造函数的 prototype 属性对应的值,在 ES5 中这个指针被称为对象的原型。

当我们访问一个对象的属性时,如果这个对象内部不存在这个属性,那么它就会去它的原型象里找这个属性,这个原型对象又会有自己的原型,于是就这样一直找下去,也就是原型链的概念。

属性constructor指回构造函数本身

属性 proto 指向构造函数的prototype 原型对象

HTTP

Http协议的方法有哪些

  1. GET:请求指定的页面信息,并返回实体主体。
  2. HEAD:类似于 GET 请求,只不过返回的响应中没有具体的内容,用于获取报头
  3. POST:向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含请求体中。POST 请求可能会导致新的资源的建立和/或已有资源的修改。
  4. PUT:从客户端向服务器传送的数据取代指定的文档的内容。
  5. DELETE:请求服务器删除指定的页面。
  6. CONNECT:HTTP/1.1 协议中预留给能够将连接改为管道方式的代理服务器。
  7. OPTIONS:允许客户端查看服务器的性能。
  8. TRACE:回显服务器收到的请求,主要用于测试或诊断。

状态码

301 永久性重定向,表示请求的资源已被分配了新的 URI
302 临时性重定向,资源的 URL 已临时定位到其他位置

OSI七层

Vue

vue2.0 与 vue3.0 数据双向绑定的区别

vue2.x实现双向数据绑定的原理是利用Object.defineProperty() 这个方法重新定义了对象获取属性值(get)和设置属性值(set)的操作来实现的,当数据发生改变发出通知。
在MDN上对该方法的说明是:Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象。
它接收三个参数,要操作的对象,要定义或修改的对象属性名,属性描述符。重点就是最后的属性描述符。
属性描述符是一个对象,主要有两种形式:数据描述符和存取描述符。
这两种对象只能选择一种使用,不能混合两种描述符的属性同时使用。上面说的 get 和 set 就是属于存取描述符对象的属性。
然后我们可以通过在存取描述符中的get和set方法内写入自定义的逻辑来实现对象获取属性和设置属性时的行为。

相比于vue2.x,vue3.0使用proxy的优势如下区别:

  1. 可以省去for in、闭包等内容来提升效率(直接绑定整个对象即可)
  2. vue3.x可以监听到数组内部数据的变化,不用再去单独的对数组做特异性操作
  3. proxy可以劫持整个对象,并返回一个新对象
  4. Vue2.x版本中的双向绑定不能检测到下标的变化
  5. defineProperty只能监听某个属性,不能对全对象监听

vue生命周期以及每个大概的概述

  • beforeCreate:
    在实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用。在new一个vue实例后,只有一些默认的生命周期钩子和默认事件,其他的东西都还没创建。在beforeCreate生命周期执行的时候,data和methods中的数据都还没有初始化。不能在这个阶段使用data中的数据和methods中的方法
  • created:
    在实例创建完成后被立即调用。在这一步,实例已完成以下的配置:数据观测 (dataobserver),roperty 和方法的运算,watch/event 事件回调。然而,挂载阶段还没开始,$el property 目前尚不可用。data 和 methods都已经被初始化好了,如果要调用 methods 中的方法,或者操作 data 中的数据,最早可以在这个阶段中操作
  • beforeMount:
    在挂载开始之前被调用:相关的 render 函数首次被调用。执行到这个钩子的时候,在内存中已经编译好了模板了,但是还没有挂载到页面中,此时,页面还是旧的
  • mounted:
    实例被挂载后调用,这时 el 被新创建的 vm.$el 替换了。如果根实例挂载到了一个文档内的元素上,当 mounted 被调用时 vm.$el 也在文档内。执行到这个钩子的时候,就表示Vue实例已经初始化完成了。此时组件脱离了创建阶段,进入到了运行阶段。如果我们想要通过插件操作页面上的DOM节点,最早可以在这个阶段中进行
  • beforeUpdate:
    当执行这个钩子时,页面中的显示的数据还是旧的,data中的数据是更新后的, 页面还没有和最新的数据保持同步
  • updated:
    页面显示的数据和data中的数据已经保持同步了,都是最新的
  • beforeDestroy:
    Vue实例从运行阶段进入到了销毁阶段,这个时候上所有的 data 和 methods,指令,过滤器……都是处于可用状态,还没有真正被销毁
  • destroyed:
    这个时候上所有的 data 和 methods,指令,过滤器……都是处于不可用状态,组件已经被销毁了。
  • activated:
    被 keep-alive 缓存的组件激活时调用。
  • deactivated:
    被 keep-alive 缓存的组件停用时调用。

vue3核心原理

响应式系统:Vue 3使用了Proxy代理实现了更高效的响应式系统。当数据发生变化时,会自动触发视图的更新。这个特性使得Vue 3的性能比Vue 2更高效,且在处理大型应用程序时表现更加出色。

组合式API:Vue 3提供了新的组合式API,使得开发者可以更好地组织和复用代码逻辑。通过这个API,我们可以将逻辑代码按功能划分为多个逻辑单元,然后可以将它们组合在一起使用,从而提高代码的可读性和可维护性。

Teleport组件:Vue 3的Teleport组件可以在DOM层级中移动任意组件或元素,从而使得开发者可以更灵活地进行页面布局。

Composition API:Vue 3的Composition API提供了更为灵活和可组合的功能,能够更好地与TypeScript等其他工具和库配合使用。

性能优化:Vue 3在性能上做出了很多优化,例如将虚拟DOM的生成和比较算法进行了优化,使得页面渲染更加高效。同时,Vue 3还通过Tree Shaking等技术,使得打包后的代码更加轻量级。

总的来说,Vue 3的核心原理在于响应式系统、组合式API和性能优化等方面的创新,使得Vue 3在开发效率、代码可维护性和性能等方面都有很大的提升。

watch和computed的区别,异步操作选哪个?

  • computed支持缓存,只有依赖数据发生改变,才会重新进行计算;而watch不支持缓存,数据变,直接会触发相应的操作。
  • computed不支持异步,当computed内有异步操作时无效,无法监听数据的变化;watch支持异步。
  • computed属性值会默认走缓存,计算属性是基于它们的响应式依赖进行缓存的,也就是基于data中声明过或者父组件传递的props中的数据通过计算得到的值;而watch监听的函数接收两个参数,第一个参数是最新的值,第二个参数是输入之前的值。
  • 如果一个属性是由其它属性计算而来的,这个属性依赖其它属性,是一个多对一或者一对一,一般用computed;而当一个属性发生变化时,需要执行对应的操作;一对多一般用watch。
  • 如果computed属性属性值是函数,那么默认会走get方法;函数的返回值就是属性的属性值;在computed中的,属性都有一个get和一个set方法,当数据变化时,调用set方法。而watch监听数据必须是data中声明过或者父组件传递过来的props中的数据,当数据变化时,触发其它操作,函数有两个参数。

vue组件之间的通信

ref被用来给元素或子组件注册引用信息,引用信息将会注册在父组件的$refs对象上,如果是在普通的DOM 元素上使用,引用指向的就是DOM 元素,如果是在子组件上,引用就指向组件的实例。

‘$refs’是一个对象,持有已注册过ref的所有的子组件。

ref有三种用法:

  1. ref加在普通的元素上,用this.$refs.name获取到的是dom元素
  2. ref加在子组件上,用this.$refs.name获取到的是组件实例,可以使用组件的所有方法。
  3. 利用v-for和ref获取一组数组或者dom节点。

注意:

  • ref需要在dom渲染完成后才会有,在使用的时候确保dom已经渲染完成。比如在生命周期mounted(){}钩子中调用,或者在this.$nextTick(()=>{})中调用。
  • 如果ref是循环出来的,有多个重名,那么ref的值会是一个数组,此时要拿到单个的ref只需要循环就可以了。

vue由什么可以优化的地方

  • 使用Vue.js的编译器来预编译Vue组件,以提高渲染速度。
  • 尽可能使用v-if代替v-show来避免在组件之间切换时重复渲染DOM元素。
  • 使用v-bind来动态地绑定属性和class,避免在DOM元素之间切换时重复渲染。
  • 避免在v-for循环中使用复杂的计算属性,尽可能将计算属性转移到数据中,以提高渲染速度。
  • 使用Vue.js的keep-alive组件来缓存已渲染的组件,以便在切换时快速重用。
  • 尽可能使用异步组件加载和懒加载来减少初始加载时间。
  • 对于大型应用程序,使用Vue.js的路由懒加载来延迟加载路由组件,以提高初始加载时间。
  • 避免频繁的操作DOM,尽可能使用Vue.js提供的指令和组件来处理DOM操作。
  • 使用Vue.js提供的响应式数据绑定来避免手动处理DOM事件和状态更新。
  • 对于需要大量数据的列表,使用Vue.js的虚拟滚动组件来提高性能并避免卡顿。
    总的来说,优化Vue.js应用程序的最佳方法是避免不必要的DOM操作,减少网络请求和数据处理,并最大限度地利用Vue.js提供的优化工具和组件。

vue数据更新后的底层逻辑

vue3的优化

  1. 在main.js中引入的不再是Vue构造函数,而是一个名为creatApp的工厂函数(不用通过new调用)
  2. 创建实例对象方式不同,Vue2是用vm来创建对象,Vue3是用app来创建
  3. 在main.js中不兼容Vue2的写法
  4. 在Vue3的模板结构可以没有根标签,template中可以直接包其他标签
  5. Composition API 组合式API
    • setup是Vue3.0中一个新的配置项是个函数,所有数据方法都是setup中,用setup代替了data,methods,钩子等,当Vue2与Vue3混用时Vue3优先
    • 在setup中return需要返回数据
  6. 需要引入ref来实现响应式数据,但是,如果引用的是ref函数,在调用变量时需要加.value
  7. 因此可以使用reactive函数来实现,但是reactive函数不能给基本类型使用,会报错;当对象类型的数据调用后,引用数据就不再需要加.value,可以直接调
    • reactive函数嵌套使用也很方便
    • 可以直接索引修改数组的数据
    • 会接收一个对象(或数组),返回一个代理对象(Proxy的实例对象,简称proxy对象)
    • 内部基于ES6的Proxy实现,通过代理对象操作源对象内部数据进行操作
  8. Vue2响应式存在的问题在Vue3被解决了
    • 进行新增属性、删除属性等操作时,数据改变了却没有被Vue2捕获,因此界面也不会发生变化
    • 直接通过下边修改数组,界面不会自动更新
  9. Vue3用到了Proxy代理,Reflect反射
    • 通过Proxy(代理)拦截对象中任意属性的变化
    • 通过Reflect(反射)对被代理对象的属性进行操作
  10. Vue3的watch在监视reactive所定义的一个响应式数据没有oldValue,并且强制开启了深度监视,所以此时deep配置无效,但是如果是监视该数据中的某个属性时,deep配置奏效。
  11. watchEffect监视,立即执行,想监视啥,就在里面写啥,和computed有点像,但是computed有返回值。
  12. 生命周期不同。
  13. hook函数,可以将同个功能的相关函数、钩子、数据包在一个js中,方便后续调用,整洁美观不凌乱
  14. provide inject实现祖先与后代组件通信

浏览器

浏览器的本地缓存方式

localStorage,sessionStorage,cookie 的区别

  1. cookie数据始终在同源的http请求中携带(即使不需要),即cookie在浏览器和服务器来回传递
       sessionStorage和localStorage不会自动把数据发给服务器,仅在本地保存
  2. 存储大小限制也不同
    • cookie数据不能超过4k
    • sessionStorage和localStorage 虽然也有存储大小的限制,但比cookie大得多,可以到5M(这个大小也问到了)或更大
  3. 数据有效期不同
    • sessionStorage:仅在当前浏览器窗口关闭前有效,自然也就不可能持久保持;
    • localStorage:始终有效,窗口或浏览器关闭也一直保存,因此用作持久数据;
    • cookie只在设置的cookie过期时间之前一直有效,即使窗口或浏览器关闭;
  4. 作用域不同
    • sessionStorage不在不同的浏览器窗口中共享,即使是同一个页面;
    • localStorage 在所有同源窗口中都是共享的;
    • cookie也是在所有同源窗口中都是共享的

垃圾回收机制

普通刷新与强制刷新

缓存相关知识

保持数据不变

如果我打开了页面A,又打开了页面B,此时我从页面B返回了页面A,如何实现页面A的数据还是我离开页面A时的数据?

使用浏览器的缓存机制:当用户从页面 A 跳转到页面 B 时,可以将页面 A 的数据存储到浏览器的缓存中。当用户从页面 B 返回页面 A 时,可以先检查缓存中是否存在页面 A 的数据,如果存在则直接从缓存中读取数据渲染页面,否则重新加载页面并获取数据。
当使用浏览器的缓存机制来实现页面数据的持久化时,可以使用以下步骤:

  1. 在页面 A 中将需要持久化的数据存储到浏览器的缓存中。可以使用 localStorage 或 sessionStorage 对象来进行存储。这些对象提供了键值对的存储方式,并且可以存储字符串类型的数据。
    例如,在页面 A 中可以使用以下代码将数据存储到 localStorage 中:

    localStorage.setItem(‘data’, JSON.stringify(data));

其中,data 是需要存储的数据对象,JSON.stringify 函数用于将对象转换为字符串。

  1. 当用户从页面 B 返回页面 A 时,可以检查缓存中是否存在页面 A 的数据。可以使用 localStorage 或 sessionStorage 对象的 getItem 方法来获取存储在缓存中的数据。
    例如,在页面 A 中可以使用以下代码检查缓存中是否存在数据:

    1
    2
    3
    4
    5
    6
    7
    8
    const data = localStorage.getItem('data');
    if (data) {
    // 缓存中存在数据,将数据解析为对象并渲染页面
    render(JSON.parse(data));
    } else {
    // 缓存中不存在数据,重新加载页面并获取数据
    loadData();
    }
  2. 当用户再次离开页面 A 时,可以将数据从缓存中删除,以避免缓存过多无用数据占用浏览器的存储空间。可以使用 localStorage 或 sessionStorage 对象的 removeItem 方法来删除缓存中的数据。
    例如,在页面 A 中可以使用以下代码删除缓存中的数据:

    localStorage.removeItem(‘data’);

使用浏览器的缓存机制来实现页面数据的持久化需要注意以下几点:

  • 缓存中存储的数据必须是字符串类型,因此需要将对象序列化为字符串或从字符串中解析为对象。
  • 缓存中的数据可能会被清除或过期,因此在获取数据时需要先检查数据是否存在,如果不存在则需要重新加载页面并获取数据。
  • 缓存中存储的数据会占用浏览器的存储空间,因此需要注意清理无用的数据以避免浏览器存储空间的浪费。

数据结构

数组去重用哪些方法

  • 利用Set()+Array.from()
  • 利用两层循环+数组的splice方法
  • 利用数组的indexOf方法
  • 利用数组的includes方法
  • 利用数组的filter()+indexOf()

堆栈和队列的区别

其他

你有了解过webpack吗?

Webpack是一个开源的前端构建工具,它可以将多个模块打包成一个或多个浏览器可识别的JavaScript文件。Webpack提供了一个灵活的插件系统,可以通过配置文件对其进行配置以满足各种不同的构建需求。

Webpack的主要功能包括:

  • 模块化管理:Webpack可以将JavaScript代码拆分成多个模块,每个模块可以独立开发、测试和维护,然后通过Webpack打包成一个或多个JavaScript文件,使得代码的复用性和可维护性得到提升。
  • 资源加载器:Webpack支持加载各种类型的文件,包括JavaScript、CSS、图片等,并提供了丰富的加载器,可以对各种类型的文件进行处理,例如使用babel-loader对ES6语法进行转换,使用css-loader和style-loader对CSS文件进行处理等。
  • 代码分割:Webpack支持将代码拆分成多个包,并根据需要异步加载,从而实现按需加载和提高页面加载速度的目的。
  • 插件系统:Webpack提供了丰富的插件系统,可以通过配置文件对其进行配置以满足各种不同的构建需求,例如压缩代码、提取公共代码、生成HTML模板等。

总的来说,Webpack可以帮助我们更方便、高效地管理和打包项目中的各种资源,提高项目的可维护性和性能。

git merge,git rebase的区别

git merge 和 git rebase 都是 Git 版本控制系统中用于合并代码分支的命令,但是它们的实现方式不同。

git merge 命令会将两个不同的分支合并成一个新的分支。它会创建一个新的提交来整合两个分支的更改,并将这个新的提交添加到当前分支中。使用 git merge 时,需要先切换到要接收合并的分支,然后执行命令。

例如,假设当前在分支 A 上,要将分支 B 合并到分支 A 上:

1
2
git checkout A
git merge B

这会将分支 B 中的更改合并到分支 A 中,并生成一个新的合并提交。

git rebase 命令的作用是将当前分支的提交基础转移到另一个分支上。这意味着 Git 会将当前分支的所有提交按照时间顺序依次应用到目标分支上,使得目标分支的历史记录变得更加线性。使用 git rebase 时,需要先切换到要接收变基的分支,然后执行命令。

例如,假设当前在分支 A 上,要将分支 A 变基到分支 B 上:

1
2
git checkout A
git rebase B

这会将分支 A 上的提交基础转移到分支 B 上,并生成一个新的历史记录。请注意,由于重新应用提交,这可能会改变提交的哈希值,因此需要小心处理可能影响其他人协作的提交。

最主要的区别在于合并历史记录的方式不同。

git merge 命令将两个分支的历史记录合并成一个新的提交,并将该新提交添加到当前分支上,从而创建一个新的合并分支。这样做可以保留原始分支的历史记录,但会创建一个额外的合并提交,使得历史记录更加分叉。

git rebase 命令会将当前分支的历史记录“移动”到目标分支上,并重新应用每个提交。这样做可以使得历史记录更加线性,但会破坏原始分支的历史记录,因为提交的哈希值会发生变化。

总的来说,如果只是想简单地将两个分支合并,那么使用 git merge 更为直观和简单。但如果您想要保持一个线性的历史记录,或者需要在协作时避免创建额外的合并提交,那么使用 git rebase 更为合适。

npm和yarn的区别

npm是一个包管理器,它让 javascript 开发者分享、复用代码更方便.在程序开发中我们常常需要依赖别人提供的框架,写js 也不例外。这些可以重复的框架代码被称作包(package)或者模块(module),一个包可以是一个文件夹里放着几个文件,同时有一个叫做 package.json的文件。

npm(node package manager):node.js 的包管理器,用于node插件管理(包括安装、卸载、管理依赖等) ,npm 是随同 node.js 一起安装的包管理工具,能解决 node.js 代码部署上的很多问题,常见的使用场景有以下几种:
1.允许用户从 npm 服务器下载别人编写的第三方包到本地使用。
允许用户从 npm 服务器下载并安装别人编写的命令行程序到本地使用。
允许用户将自己编写的包或命令行程序上传到 npm 服务器供别人使用。

npm 的缺陷:npm install 下载速度慢,重新 install 时速度依旧慢。
同一个项目,安装的无法保持一致性。原因是因为 package.json 文件中版本号的特点导致的,下面三个版本号在安装的时候代表不同的含义。
“5.0.3” # 表示安装指定的5.0.3版本
“~5.0.3” # 表示安装5.0.X中最新的版本
“^5.0.3” # 表示安装5.X.X中最新的版本

使用 npm 安装多个 js 包时,包会在同一时间下载和安装。安装过程中,其中一个包抛出了一个异常,但 npm 会继续安装其他包,所以错误信息就会在一大堆提示信息中丢失掉,以至于直到执行前,都不会发现实际发生的错误。

yarn 是由 Facebook、Google、Exponent 和 Tilde 联合推出了一个新的 JS 包管理工具,yarn 是为了弥补 npm 的一些缺陷而出现的。

Yarn 优点
1.速度快 。速度快主要来自以下两个方面:

2.并行安装:无论 npm 还是 Yarn 在执行包的安装时,都会执行一系列任务。npm 是按照队列执行每个 package,也就是说必须要等到当前 package 安装完成之后,才能继续后面的安装。而 Yarn 是同步执行所有任务,提高了性能。

3.离线模式:如果之前已经安装过一个软件包,用Yarn再次安装时之间从缓存中获取,就不用像npm那样再从网络下载了。

4.安装版本统一:为了防止拉取到不同的版本,Yarn 有一个锁定文件 (lock file) 记录了被确切安装上的模块的版本号。每次只要新增了一个模块,Yarn 就会创建(或更新)yarn.lock 这个文件。这么做就保证了,每一次拉取同一个项目依赖时,使用的都是一样的模块版本。npm 其实也有办法实现处处使用相同版本的 packages,但需要开发者执行 npm shrinkwrap 命令。这个命令将会生成一个锁定文件,在执行 npm install 的时候,该锁定文件会先被读取,和 Yarn 读取 yarn.lock 文件一个道理。npm 和 Yarn 两者的不同之处在于,Yarn 默认会生成这样的锁定文件,而 npm 要通过 shrinkwrap 命令生成 npm-shrinkwrap.json 文件,只有当这个文件存在的时候,packages 版本信息才会被记录和更新。

5.更简洁的输出:npm 的输出信息比较冗长。在执行 npm install 的时候,命令行里会不断地打印出所有被安装上的依赖。相比之下,Yarn 简洁太多:默认情况下,结合了 emoji直观且直接地打印出必要的信息,也提供了一些命令供开发者查询额外的安装信息。

6.多注册来源处理:所有的依赖包,不管他被不同的库间接关联引用多少次,安装这个包时,只会从一个注册来源去装,要么是 npm 要么是 bower, 防止出现混乱不一致。

7.更好的语义化: yarn改变了一些npm命令的名称,比如 yarn add/remove,感觉上比 npm 原本的 install/uninstall 要更清晰。

你认为一个好的前端技术人员需要具备什么能力

如何提升用户体验

如何加快页面加载速度

描述一下做的项目

这个系统采用了前后端分离的模式,主要是通过使用后端给的接口来实现的,前端是使用了vue3.0的框架,界面是使用了element-ui组件。包含登录注册页面,人员信息管理,核酸检测管理,疫苗信息管理,隔离信息管理等几个模块。其中使用vuex进行组件之间的状态管理,解决了多级组件之间传值困难的问题,然后利用vue-router实现了组件和渲染路径的映射切换。我实现的功能主要是将数据展现在页面上,并实现针对不同的管理员给予不同的权限,实现了对列表信息的增删改查以及分页展示功能,新增时刷新页面,编辑时传递当前的id展示编辑内容,然后form表单提交编辑信息,然后是首页,通过npm引入echarts,初始化一个echarts实例,将配置的option赋值给实例,在mounted确定dom加载完毕调用,对学生的各项信息进行可视化展示。

首先就是用了脚手架来初始化了整个项目,然后构思了二手商城的主要页面,分别是登录注册,首页,购物车页面,个人中心,商品详情页等,然后根据构思再来设计好路由,再新建各个组件,将各个页面的公用部分提取出来比如说header和footer是每个页面公用的,接下来就是element-ui搜罗合适的组件放入,然后用less语言来修改一下组件的样式,数据接收与展现大部分就是在script里写方法,数据的交互的话就通过封装axios来实现,封装了一次之后,接下来再调用的话就会很方便使用

首先就是利用HBuilder新建了一个uni-app框架项目,再想好了自己有四个主页面就设置了四个tabbar的图标名字样式等,分别是首页,分类,购物车和个人中心,首页的话有搜索框、轮播图和一些甜品图片的展示,点击轮播图的图片可以进入到对应商品的详情页,点击搜索框会跳转到搜索界面,搜索界面和商品详情页是放在了分包里面,搜索界面主要就是搜索框和搜索历史,如果在搜索框里输入关键词,并且能搜索出一些商品的话,就会有搜索列表代替掉了搜索历史展示出来,点击搜索列表中的某一项就会跳转去对应商品的商品详情页,商品详情页就是利用后端的接口将商品的所有信息展示出来,在tabbar的区域的话用了uni的组件展现了加入购物车与结算的按钮,第二页是分类点单页面,分为了左右两个滑动区域,点击左边的种类就会展现对应种类的商品,默认是第一项,点击某个商品也是会跳转到商品详情页,第三页是购物车页面,用户在商品详情页点击加入购物车后,购物车的徽标就会加一,对购物车内的商品每进行一次操作,相同的也会对本地存储进行一次操作,从而实现了购物车的信息实时的保存在了本地,选中某些商品进行结算的话,订单界面就会多一项记录,但是如果在没有登录的情况下就会提醒你先登录再下单,就会等3秒后跳转到个人中心,第四页就是个人中心,分成了有无登录的两种情况,利用v-if判断有无token来展示,用户没有登录的话就会有按钮提醒用户登录,利用了wx.login获取到code,然后将code传给后端,后端再返回token以及一些用户信息,登录之后展示的就是用户界面,有用户头像,昵称等内容,还有一个订单框,点击这个框就跳转到订单页面,记录了该用户的消费记录,当然,个人页面还可以退出登录就又变成了授权登录的界面。
然后是B端用的vue-cli脚手架创建了一个vue项目,分别有商品管理,订单查询,商品种类管理,轮播图管理等功能,利用axios和后端交互实现了对各种数据的增删改查,然后轮播图管理的话,实现了图片的上传和回显。

本文作者:Wendy
本文链接:https://wendy-ljw.github.io/2023/03/17/sum-1/
版权声明:本文采用 CC BY-NC-SA 3.0 CN 协议进行许可
×