springboot 建readme_README
第一阶段 SpringBoot、JPA、Redis
第一章 Java编程思想深度理论知识
重点理论单纯interface可以统一方法调用,但是它不能统一对象实例化。
面向对象主要做两件事情:实例化对象和调用方法(完成业务逻辑)。
只有一段代码中没有new的出现,才能保持代码相对稳定,才能逐步实现OCP,实质是一段代码如果要保持稳定,就不应该负责对象的实例化。
对象的实例化是不可能消除的。
把对象实例化的过程,转移到其他代码片段。
代码中总是会存在不稳定,隔离这些不稳定,保证其他代码是稳定的。
变化造成了不稳定。
IOC、DI、DIP理论DIP(依赖倒置)高层模块不应该依赖低层模块,两者都应该依赖抽象
抽象不应该依赖细节
细节应该依赖抽象
总结一句话:面向抽象编程
DI(依赖注入)意义:松耦合,消除组件之间的直接依赖关系
实现原理:通过容器将对象注入进来。容器的作用就是装配对象,实现基本原理是工厂模式+反射。
IOC(控制反转)控制权的反转
PS积木生产厂家(程序员)
设计一个一个积木(类)
玩家/用户搭建一个一个形状
代码体现
程序员生产一个一个类,至于类如何使用,不再由程序员决定。
第二章 Spring与SpringBoot理论篇
2.1 模式注解
模式注解的目的为了实例化对象或者bean加入到IOC容器最基础的模式注解@Component
@Component的延申注解@Controller、@Service、@Repository,这三个注解与@Component的作用没多大区别,只是有语义的区分。
2.2 延迟实例化与注入时机SpringBoot默认机制会在SpringBoot应用启动时立即实例化并将实例注入到代码片段里。
可以通过@Lazy注解延迟实例化时机。可以通过无参构造函数测试@Lazy延迟实例化时机是否有效。
如果只在一方@Lazy,并没有在依赖注入一方加入@Lazy,那么延迟实例化时机没有效,原因是需要注入实例,需要立即实例化。
2.3 注入
注入方式成员变量注入
Setter方法注入
构造函数注入构造函数注入可以不用加@Autowried注解
注入分类被动注入类型byType:按照类型进行注入
byName:按照类名进行注入规则:类名UserService,变量名userService
优先级 先byType再ByName
规则不存在一个bean,直接报错
只存在一个bean,直接注入
存在多个bean,也有可能不报错。如果通过ByType之后,存在多个相同类型的bean,那么会按照byName注入。
如果以上的结果最后匹配失败,那么会报错
主动注入@Qualifier注解指定实例注入,相当于byName
2.4 应对变化的两种方案策略模式:制定一个接口,让多个类实现同一个接口解决方案:byName方式
@Qualifier指定bean名
有选择的只将一个bean加入到IOC容器
@Primary提高优先注入优先级
属性配置:修改类的属性应对变化为什么要把变化隔离到配置文件?配置文件具有集中性
清晰,没有业务逻辑
2.5 @Configuration配置原理
作用替换Bean在xml的配置方式
意义更加灵活地将一个实例加入到IOC容器
可以导入一组bean到IOC容器
2.6 条件注解
作用满足条件才会将一个bean加入到IOC容器
基本用法@Conditional + 实现Conditional接口@Conditional 注解要求传入一个元类型,而且这个类必须要实现Conditional接口。
Conditional接口提供了一个可以覆写的方法matches,这个方法要求返回boolean类型,如果true,则将bean加入到IOC容器;如果false,反之。
成品条件注解@ConditionOnProperty等@ConditionOnProperty 注解是需要跟配置文件搭配使用
其中有几个比较重要的参数
value 配置文件key名
havingValue 配置文件对应key的value
matchIfMissing 默认值false,如果为true,配置文件中没有对应key,则会加入到IOC容器@ConditionalOnBean:当SpringIoc容器内存在指定Bean的条件@ConditionalOnClass:当SpringIoc容器内存在指定Class的条件@ConditionalOnExpression:基于SpEL表达式作为判断条件@ConditionalOnJava:基于JVM版本作为判断条件@ConditionalOnJndi:在JNDI存在时查找指定的位置@ConditionalOnMissingBean:当SpringIoc容器内不存在指定Bean的条件@ConditionalOnMissingClass:当SpringIoc容器内不存在指定Class的条件@ConditionalOnNotWebApplication:当前项目不是Web项目的条件@ConditionalOnProperty:指定的属性是否有指定的值@ConditionalOnResource:类路径是否有指定的值@ConditionalOnSingleCandidate:当指定Bean在SpringIoc容器内只有一个,或者虽然有多个但是指定首选的Bean@ConditionalOnWebApplication:当前项目是Web项目的条件
2.7 自动装配原理
第二阶段 VUE
第一章 VUE的思想、WEB前端发展与Vue3.0新特性
1.1 vue3.0变化综述
vue3.0的一个很大的变动从options api -> composition api。options api 类似于小程序这种方式的api,vue2.x也是这种
const vm = new Vue(el,template)
composition api 更加函数式
1.2 vue的一些必备基础最基本三件套HTML+CSS+JAVASCRIPT
ES6
有小程序基础更好,如果没学习过小程序,推荐先学习小程序
1.3 前端发展四个阶段原生JS -> DOM
JQuery
vue/react/NG
工程化
1.5 服务端渲染VS前端渲染
一个页面三个要素:html+css+数据
服务端渲染:html+数据是在服务端结合,它最终返回的是一个html。技术栈:WEB框架+模板引擎
前端渲染:它仅仅返回一个模板html(css+js),通常来说是没有数据,数据是通过js请求api获取数据,最后才填充到html上。技术栈:Vue/React/NG
如何理解前端/后端?
可以理解为两个应用程序之间的通信。前端也是一个应用程序,服务端也是一个应用程序。服务端(B) - 前端(F)
应用场景:CMS/APP/H5,并不适合开发门户网站
第二章 vue3.0的初始化与常用指令
2.1 vue2.x options api
下面代码vue2.x版本的写法,属于options api风格,而vue3.0的思想是composition api风格。xxxxxxxxxx
const vm = new Vue({el:'#app',data: {message: 'hello 7yue'}})其实小程序也是options api风格xxxxxxxxxx
Page({data: {message: 'hello 7yue'}})
2.2 第一个vue3.0Demoxxxxxxxxxx
小结创建app并挂载到指定节点,需要调用createApp(app).mount('#app'),其中app是定义的对象,#app是挂载的节点。
始终要保证有一个节点能被vue托管,因为这样才可以在html里引用变量、指令等
vue3.0入口函数是setup()
2.3 指令v-text与v-html案例一正常显示两个内容
案例二只会显示message1内容,因为v-text指令有一个重要特性会替换标签内的内容,所以message2是不会显示的。
案例三是v-text指令和v-html指令的区别,v-text指令不会解析标签,而v-html指令会解析标签。x
{{message2}}
小结指令应用到根节点上是无效的。
v-text指令相当于innerText,v-html指令相当于innerHtml。
v-text指令不会解析标签而v-html指令会解析标签。
共同点都会替换标签内的内容。v-text指令相对使用的不多,因为{{}}的写法风格会更好。
v-html指令更多使用在动态html上。
2.4 指令v-bind案例一绑定属性值
案例二绑定属性以及属性值
案例三v-bind的省略形式xxxxxxxxxx
小结v-bind以及它的省略形式:都可以用于绑定标签的属性与小程序比较
小程序上绑定标签属性是可以直接使用{{}},如果是自定义属性是data-xxx={{...}}。
2.5 带入JS表达式进行动态计算
需要弄懂表达式与语句的区别,表达式如1+1,三元表达式等,而语句如if、const a = 1 + 1等。案例一字符串拼接
案例二三元表达式xxxxxxxxxx
{{flag?'missyou':'empty'}}
2.6 指令v-on案例一使用v-on:事件名称绑定click事件
案例二是v-on指令的省略形式xxxxxxxxxx
小结绑定事件可以使用指令v-on以及省略形式@
事件函数也需要定义在setup入口方法里面。与小程序比较
小程序绑定事件是使用bind:事件名或者bind事件名
2.7 条件渲染案例一v-if与v-show的区别
案例二多条件渲染xxxxxxxxxx
小结v-if 与 v-show区别,从显示结果上是看不出有什么区别,需要从功能上观察。v-if如果为true就渲染,否则就不渲染。
v-show不管是否为true都会渲染,它相当于display:none。
如果不是频繁切换可以考虑使用v-if,如果频繁切换使用v-show,从一定角度上频繁渲染dom节点会性能有一定影响
多条件渲染v-if、v-else-if、v-else与小程序比较
v-if 相当于小程序 wx:if,v-show 相当于小程序 wx:hidden
2.8 列表渲染案例一数组遍历(有序)
案例二对象遍历(无序)xxxxxxxxxx
- 序号{{index}} {{item}}
- value:{{value}} key:{{key}} index:{{index}}
小结数组遍历,第一个参数是数组元素,第二个参数是数组下标/序号。
对象遍历,第一个参数是值,第二个参数是键,第三个参数是序号。
共同点参数的顺序是不能改变的。
遍历哪个标签就写在哪个标签上。与小程序比较小程序遍历是使用wx:for,而且只能遍历数组。
默认参数item为数组元素,index为数组下标,如果需要改变参数名称,需要使用wx:for-item="xxx",wx:for-index="xxx"
小程序遍历需要写在父节点,更多使用占位符。
第三章Vue3定义响应对象的两种方法
3.1 双向数据绑定
双向数据绑定有两个关键字双向、绑定。双向:指的是数据既可以从HTML流行JAVASCRIPT,也可以从JAVASCRIPT流行HTML(如下图所示)。双向的概念并不是只有双向数据绑定的框架才有,即使是单向数据绑定框架或者原生JS的时代也是存在的。1 什么情况下下,数据从HTML流行JAVASCRIPT?
有一种常见的情况,当需要用户输入的时候,数据就会从HTML流向JAVASCRIPT,比如input。
2 在原生JS时代,数据如何从HTML流行JAVASCRIPT?
更多使用document获取节点,再获取数据
3 与小程序比较
虽然现在小程序也有双向数据绑定的概念,不过是一个简易版的双向数据绑定。在以前小程序都是通过事件event来获取WXML上的数据
绑定:指的是数据能够同步的更新。如果HTML数据发生变化,JAVASCRIPT能够及时监听,并同步数据,JAVASCRIPT数据发生变化,HTML上的数据也会同步变化。
下面代码并不是双向数据绑定,而是说明了什么是绑定?
如果用户在input上输入不同的值,点击保存触发click事件,如果onClick函数打印值是与input的值是一样的,那么这种情况就是绑定。
实际上,下面例子不管用户输入什么,onClick函数打印的还是原来的值,因为根本没有应用绑定。xxxxxxxxxx
小结双向:数据既可以从HTML流向JAVASCRIPT,也可以从JAVASCRIPT流向HTML。
绑定:HTML与JAVASCRIPT数据能够同步及时更新。
3.2 Vue3.0包装响应式对象
实现双向数据绑定需要使用指令v-model作为辅助,它还要与响应式对象搭配才能实现双向数据绑定。在Vue3.0中提供两个方法可以将JAVASCRIPT数据类型包装成响应式对象分别是ref、reactive。
下面代码分别使用ref、reactive将JAVASCRIPT数据类型包装成响应式对象。xxxxxxxxxx
小结包装响应式对象方法ref、reactive。
双向数据绑定的核心并不是指令v-model,而是响应式对象。
3.3 误区
在第二章节中,有很多例子的数据都是从JAVASCRIPT流向HTML,很明确的一点就是它肯定不是双向数据绑定。它既然不是双向数据绑定,那么它是单向数据绑定吗?
不是单向数据绑定。下面代码,通过click事件改变number的值,但是始终页面上显示的值都是1,但是javascript上的number实质已经发生改变了,这种情况也证明了一点JAVASCRIPT的数据变化,并没有影响HTML数据变化,所以它也不是单向数据绑定。解决这个问题也很简单,就是用ref或reactive包装成响应式对象xxxxxxxxxx
+1
第四章watch监听函数的基本用法和vue3中的高级特性
4.1 Vue3.0中的watch函数
watch函数主要作用监听到值变化的时候,给了我们一次机会,去做一些业务处理。
watch函数接受两个参数,第一个参数监听的变量,第二参数是回调函数xxxxxxxxxx
小结watch函数给了我们一次机会,去做一些业务处理。与小程序比较
小程序中也有监听器,不过在小程序叫observers
4.2 监听reactive对象
下面代码中不再使用ref包装firstName和lastName为响应式对象,而是使用reactive包装为响应式对象。
因为reactive响应式转换是“深层的”,会影响对象内部所有嵌套的属性,所以监听响应式对象name即可。xxxxxxxxxx
4.3 监听reactive对象下的某个属性
watch函数的第一个参数除了可以接受一个响应对象之外,还可以是一个拥有返回值的 getter 函数,使用reactive包装响应式对象是有getter方法的,你也可以把它理解成对象的某个属性。xxxxxxxxxx
小结用wacth函数监听时,推荐使用ref或getter,除非你是知道所有值都需要监听变化,这种情况可以监听reactive包装的响应式对象。
第五章 计算函数
5.1 computed函数基本用法
computed函数基本用法就是接受一个回调函数,它会监听函数内部变量的变化,发生变化都会执行一次。xxxxxxxxxx
5.2 watch、computed和普通JS函数的场景和区别
watch使用场景是在于监听,它的目的监听ref或reactive对象的变化。场景:当数据发生变更的时候,我们需要处理一些业务逻辑。
computed主要的目的是得到最终一个结果,并不在于监听。
普通JS函数与computed函数作用没什么区别,它们都能返回一个结果,但是性能不够computed函数好,computed函数更加智能,因为它能缓存,如果参与计算函数的的变量没有发生变化,那么它会从缓存中获取。
小结
watch函数看重的是监听变量的变化,而computed函数看重的是返回结果
5.3 computed的set和get方法
computed函数的高级用法编写set和get方法,如果需要修改计算属性返回结果的值,一定要编写set方法,因为computed函数是只读的,只能通过set方法修改。下面代码如果没有编写set方法,直接修改fullName.value = '8yue',会报错xxxxxxxxxx
小结computed函数是只读的
如果要修改computed函数返回结果的值,一定要编写set方法
第六章创建Vue3.0项目和组件编程概述
6.1 Vue3.0中组件如何编写?xxxxxxxxxx
'})vm.mount('#app')对比Vue2.x写法
在vue2.x中注册全局组件使用Vue.component
6.2 Vue4.xcli或者使用Vite创建Vue3.0项目
使用cli创建项目使用npm全局安装或者升级4.xclinpm i -g @vue/cli
使用vue-cli创建vue应用程序vue create project-name注意创建的项目还是vue2.x应用程序
将vue2.x项目升级到vue3.x需要安装一个插件vue add vue-next
使用Vite创建项目
使用vite创建vue3.x项目只需要一条命令npm init vite-app project-name现在vite还不太成熟,实际开发还是使用vue-cli
6.3 一切皆组件
传统网页开发html、js、css,如果使用vue开发应用程序,要以app或者小程序的视觉看待vue。可以理解为对于一个vue应用程序来说一切都是组件,不能再用页面的概念看待vue应用程序。
6.4 组件编程思想代码复用
代码分离
6.5自定义组件props属性
vue单向数据流特性:指的是父组件传给子组件的数据应该由父组件决定,子组件的数据更新不应该影响父组件。实际上在vue中props对象的属性都是只读(reading only)的。
在这里还要注意一下值类型和引用类型。
如果引用类型,对象属性是可以修改的。
props可以是一个数组,也可以是一个对象数组:xxxxxxxxxx
props: ['a','b','c']
对象:xxxxxxxxxx
props: {a: {type: String, // 数据类型value: 'hello' // 默认参数// 关于props的参数还有很多,甚至可以校验参数是否合法}}
setup方法的第一个参数是props
6.6 自定义事件
在Vue3.0中自定义事件需要使用setup方法中的第二个参数context调用emit()方法。
emit()方法第一个参数方法名:方法名推荐规则全小写或单词之间使用-分割
第二个参数数据:要返回给父组件的数据
事件监听机制事件监听只能一步一步往上监听,不能跨过中间间隔的组件监听。对比小程序
小程序是使用triggerEvent()方法
第七章vue-route
7.1 前端路由的意义
在传统的项目并没有前端路由,页面都是后端路径渲染而来。
在现代web开发中其实前后端没有多大区别,前端也是通过一个url跳转页面/组件,而且要注意的是前端路由并不会去服务器发送请求,不会访问我们的服务端的。对比小程序
小程序中也有路由的概念,只不过它比较简单只有几个api,而vue的前端路由而是需要安装一个vue-route插件
7.2 router-view与router-link
router-view它会匹配当前路由配置的组件来替换router-view。
router-link它的行为类似a标签,不过它是跳转的是路由。
7.3 vue-router 编程思想入口组件规范
router-view监听事件
组件的切换优先考虑路由而不是条件渲染
7.4 嵌套路由
在配置路由的时候,需要在父路由配置children属性,并且需要与router-view搭配,它也只能显示在父路由所配置组件的router-view里面。
7.5 vue3获取路由参数
在2.x中获取路由参数是使用this.$route
在3.0中需要使用router.currentRoute
7.6 动态组件与keep-alive
在vue中集中切换视图的方案v-if
router-view
动态组件
动态组件xxxxxxxxxx
keep-alive
缓存组件,保存组件之前的状态xxxxxxxxxx
keep-alive 还有exclude属性,作用与include相反
除了可以用','分割之外,还可以使用数组或者正则表达式
主要组件名大小写敏感
第八章 vuex
第三阶段 前端面试
第一章变量类型和计算思考typeof能判断哪些类型?
何时使用===或==?
值类型与引用类型的区别?
手写深拷贝
1.1 值类型与引用类型
值类型本质:如果定义了一个值类型变量a=100,那么他会在栈中创建a=100。
常见值类型:undefinednumberstringboolean、symbol
代码演示xxxxxxxxxx
let a = 100let b = aa = 200console.log(b) // 100
引用类型本质:如果定义了一个引用类型变量a,那么它会在栈中创建a=内存地址,内存地址是在堆中生成。
常见引用类型:ArrayObjectnullfunctionxxxxxxxxxx
const a = {age: 10}const b = aa.age = 20console.log(b.age) // 20
小结值类型各走各的
引用类型随它变化而变化
1.2 typeof运算符识别所有值类型
识别函数
识别引用类型,但是不可再细分
1.3 深拷贝xxxxxxxxxx
function deepClone(obj = {}) {// 如果为null或者不是object,直接返回if(obj === null || typeof obj !== 'object') {return obj}// 如果是数组返回[],否则返回{}let result = obj instanceof Array ? [] : {}for(let key in obj) {// 保证key不是原型的属性if(obj.hasOwnProperty(key)) {result[key] = deepClone(obj[key])}}return result}
1.4 变量计算-类型转换==运算符运算会自动类型转换,建议除了判断null之外,一切使用===运算符==与===区别==会自动类型转换
===不但会判断值是否相等,还要判断类型是否相等
第二章原型与原型链思考如何准确判断一个变量是不是数组?
class的原型本质,怎么理解?
知识点class和继承
类型判断instanceof
原型和原型链
2.1 原型
原型关系每个class都用显式原型prototype
每个实例都有隐式原型proto
实例的proto指向对应class的prototype
原型执行规则先在自身属性和方法寻找
如果找不到则自动取proto隐式原型寻找
2.5 原型链每个class的显式原型prototype也有一个隐式原型proto,
如果这个类存在继承关系,那么这个隐式原型会指向父类显式原型,直到Object显式原型为止,最终Object的隐式原型proto指向null
第三章 作用域和闭包思考this的不同应用场景,如何取值?
手写bind函数
实际开发中闭包的应用场景,举例说明
知识点作用域和自由变量
闭包
this
3.1 作用域和自由变量所有的自由变量查找,是在函数定义的地方,向上级作用域查找,不是在执行的地方。xxxxxxxxxx
// 函数作为返回值function fun1() {const a = 100return function() {console.log(a) //100}}const fn1 = fun1()const a = 200fn1()// 函数作为参数function print(fun2) {const a = 200fun2()}const a = 100function fun2() {console.log(a) // 100}print(fun2)
3.2 this
this 指向什么值,取决于函数执行时确定,不是在函数定义时确定
3.3 手写bind、apply、callbind函数:返回一个函数,第一个参数改变this的指向,其余参数直接传递。
apply函数:直接调用,第一个参数改变this的指向,其余参数用数组包裹。
call函数:直接调用,第一个参数改变this指向,其余参数直接传递。
手写bindxxxxxxxxxx
Function.prototype.mybind = function() {// 将arguments参数分解为argsconst args = Array.prototype.slice.a(arguments)const obj = args.shift()const self = this //指向fn1return function() {self.apply(obj,args)}}function fn1(a,b,c) {console.log(this)console.log(a,b,c)}const fun2 = fn1.mybind({x:100},1,2,3)// 相当于fn1.bind的作用fun2()
手写applyxxxxxxxxxx
Function.prototype.myapply = function(obj,args) {const self = this // 指向fn1self.call(obj,...args)}function fn1(a,b,c) {console.log(this)console.log(a,b,c)}fn1.myapply({x:100},[1,2,3])
手写callxxxxxxxxxx
Function.prototype.mycall = function() {// 将arguments参数分解为argsconst args = Array.prototype.slice.apply(arguments)const obj = args.shift()const self = this // 指向fn1self.apply(obj,args)}function fn1(a,b,c) {console.log(this)console.log(a,b,c)}fn1.mycall({x:100},1,2,3)
第四章 同步和异步
同步与异步区别同步会阻塞代码执行
异步不会阻塞代码执行
异步应用场景加载图片
网络请求
定时任务思考:Promise解决什么问题?
解决回调地狱(callback hell)
异步进阶
Promise三种状态:pending、resolved、rejected
then和catch链式调用的影响then正常返回resolved,里面有报错则返回rejected
catch正常返回resolved,里面有报错则返回rejected
async/await有async的存在一定会返回一个promise,如果不主动返回promise会包装成promise
await 可以理解为求值,类似then中的数据。
await一定要搭配await使用
async/await在for...of起作用
微任务和宏任务微任务和宏任务分别有哪些?微任务:promise,async/await
宏任务:setInterval、setTimeout、AJAX、DOM事件等
为什么微任务的执行时机比宏任务早?微任务是在DOM渲染之前执行
宏任务是在DOM渲染之后执行
为什么微任务和宏任务队列是分开的?微任务是语法规定
宏任务是浏览器规定
第五章 WEB API
5.1 DOM
节点操作getElementById()通过id选择器获取一个节点元素
getElementsByTagName()通过标签名称获取一组节点元素
getElementsByClassName()通过类名获取一组节点元素
querySelectorAll()通过一个或多个css选择器获取一组节点元素
结构操作新增/插入一个节点xxxxxxxxxx
移动节点xxxxxxxxxx
hello
获取子元素列表,使用父节点属性childNodes,注意包含文本节点,文本节点nodeType = 3,DOM节点nodeType = 1
获取父元素,使用子节点属性parentNode
删除子节点:使用removeChild()
5.2 BOMnavigator:获取浏览器信息
screen:获取屏幕信息
localtion:获取网址信息
history:前进和后退
5.3 事件阻止默认行为:event.preventDefault()
阻止冒泡:event.stopPropagation()
事件代理:其实也是冒泡的一个应用。
第六章AJAX
6.1 模拟AJAX-get请求xxxxxxxxxx
const xhr = new XmlHttpRequest('GET','/data.json',true) // true代表异步,false代表同步xhr.onreadystatechange = function() {if(xhr.readyState === 4) {if(xhr.status === 200) {console.log(xhr.responseText)}}}xhr.send(null)
readyState0:还没有调用send方法
1:已调用send方法,正在发送请求
2:send方法执行完成,已接受到全部响应内容,但是数据还未回来
3:正在解析响应内容
4:响应内容解析完成,可以在客户端调用,除了4这种情况,其他情况都拿不到响应内容
6.2 同源策略
ajax请求时,浏览器要求当前网页和server必须同源(安全)。
同源协议、域名、端口,三者必须一致xxxxxxxxxx
// 注意:img,link,script,都可以无视同源
6.3 跨域
所有跨域都必须经过server端允许和配合,未经过server端允许就实现跨域,说明浏览器有漏洞,危险信号。
实现跨域两种方式JSONP:可以绕过跨域限制,服务器可以任意动态拼接数据返回,所以就可以获得跨域的数据,只要服务端愿意返回
CROS
第七章存储
cookie,localStorage,sessionStorage的区别容量:cookie只能存储4kb,localStorage、sessionStorage能存储5kb。
是否跟随http请求发送出去:cookie会,localStorage、sessionStorage不会。
localStorage,sessionStorage的区别localStorage数据会永久存储,除非代码或手动删除。
sessionStorage数据只存在于当前会话,浏览器关闭则清空。
第八章 HTML语义化理解?提高代码阅读性
让搜索引擎更容易读懂
块级元素和内联元素块级元素display:block/table:div、p、h1-h5、p、ul、ol、table等
内联元素display:inline/inline-block:span、img、input、button
第九章 CSS
9.1 BFC理解与应用Blcok format contexxt 块级格式化上下文
一块独立渲染区域,内部元素的渲染不会影响外界以外的元素
形成BFC条件float 不是 none
position是absoluted或者fixed
overflow不是visible
display是flex、inline-block等
第十章 运行环境
10.1 网页加载和渲染
资源的形式html代码
媒体文件,图片或者视频等
js、css
加载过程输入urlDNS解析:域名——>IP地址
浏览器根据P地址向服务器发起HTTP请求
服务器处理HTTP请求,并返回给浏览器
渲染过程根据HTML代码生成DOM Tree
根据CSS代码生成CSSOM
讲DOM Tree和CSSOM整合形成Render Tree渲染树
根据渲染树渲染页面
遇到则暂停渲染,优先加载并执行JS代码,完成再继续
直到把渲染树渲染完成
10.2 性能优化手写防抖、节流
性能优化原则缓存
减少CPU计算量,减少网络加载耗时
加载更快减少资源体积,压缩代码
减少访问次数:合并代码,SSR服务端渲染、缓存。
使用更快网络:CDN
渲染更快CSS放在head,JS放在body下面
尽早开始执行JS,用DOMContentLoaded
懒加载(图片懒加载,上滑加载更多(分页))
对DOM查询进行缓存,频繁DOM操作,合并到一起插入DOM结构
节流throttle,防抖debouncexxxxxxxxxx
// 防抖function debounce(fn,delay=500) {let timer = nullreturn function() {if(timer) {clearInterval(timer)}timer = setTimeout(()=>{fn.apply(this,arguments)timer = null},delay)}}// 节流function throttle(fn,delay=100) {let timer = nullreturn function() {if(timer) returntimer = setTimeout(()=>{fn.apply(this,arguments)timer = null},delay)}}
springboot 建readme_README相关推荐
- springboot 建readme_经验分享:给项目创建和编写README.md文件的步骤
在项目开发过程中,不仅要注意代码的编写质量,也要为合作开发打好基础,尤其是合作开发的时候,同事直接的代码需要熟悉,这就需要在开发的时候进行注释操作,方便别人维护和熟悉代码.除了上述两个重要的点之外,还 ...
- 智能门禁(6)---调用face++实现人脸检测
人脸识别(一)调用face++实现人脸检测 2017年下半年以来,随着iPhoneX的人脸解锁功能把人脸识别这一黑科技带入大家的视野中之后,各种有关人脸识别功能的新闻和报道层出不穷.不仅是对普通群众来 ...
- 人脸识别(一)调用face++实现人脸检测
2017年下半年以来,随着iPhoneX的人脸解锁功能把人脸识别这一黑科技带入大家的视野中之后,各种有关人脸识别功能的新闻和报道层出不穷.不仅是对普通群众来说,对我们程序猿来说,百度,微软,阿里等各大 ...
- 人脸识别(一)调用face++实现人脸检测。
2017年下半年以来,随着iPhoneX的人脸解锁功能把人脸识别这一黑科技带入大家的视野中之后,各种有关人脸识别功能的新闻和报道层出不穷.不仅是对普通群众来说,对我们程序猿来说,百度,微软,阿里等各大 ...
- SpringBoot 集成 clickhouse + mybatis-plus 配置及使用问题说明(含建表语句、demo源码、测试说明)
1.建表语句 -- 建表 CREATE TABLE IF NOT EXISTS tb_stat ( id String, region String, group String, yesterday ...
- springboot mybatis ehcache_SpringBoot入门建站全系列(十四)集成Redis缓存
SpringBoot入门建站全系列(十四)集成Redis缓存 一.概述 本地缓存,就是使用应用内使用本地内存将数据暂缓存储,一般数据库的查询如果不怎么改动,可以用本地缓存暂存. 远程缓存,比如redi ...
- springboot util 测试类怎么写_SpringBoot入门建站全系列(九)文件上传功能与下载方式...
SpringBoot入门建站全系列(九)文件上传功能与下载方式 Spring对文件上传做了简单的封装,就是用MultipartFile这个对象去接收文件,当然有很多种写法,下面会一一介绍. 文件的下载 ...
- Springboot 之 Hibernate自动建表(Mysql)
前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家.点击跳转到教程. 引入Maven依赖包 <dependency><groupId>org.sp ...
- idea 建nodejs 项目_三种方法带你新建SpringBoot项目
SpringBoot 的设计目的是简化Spring的搭建与开发,尤其是没有了好多繁琐的配置.本篇文章主要介绍如何搭建SpringBoot项目. 从官网创建 访问Spring的官方网站 start.sp ...
- Springboot,Mybatis根据实体类自动建表
Springboot,Mybatis根据实体类自动建表 在创建实体类的同时还要在数据库建表,如果只是很少的属性那么无所谓,但是当实体类很多或者字段很多时这就是一个非常让人不爽的事情了 通常有两种思路, ...
最新文章
- 操作系统学习:基础轮廓梳理
- nrf51822-主从通信分析1
- a类网络被谁用了_谁说学考没有用?浙江三位一体报名要求,需要几A几B都在这里...
- ArcGIS 10.0安装之 ArcSDE的安装
- 想申请AI方向硕、博,这个内容一定要提前准备!!
- php生成pdf中文断码_Rmarkdown导出中文PDF解决方案
- InceptionNet V2整理总结
- Centos7 yum 安装 oracle-rdbms-server-11gR2-pre
- IO is frozen on database xxx, No user action is required
- 设计师必备超人气设计素材网站
- socket read time out解决方法_深入浅出讲解:php的socket通信
- 根据ip高精度查地址网址
- DocumentFormat.OpenXml
- 二分算法:数的三次方根
- python聚类系数_NetworkX 计算聚类系数的Python实现
- 用Python爬了我的微信好友,他们是这样的...
- Leetcode个人题解714
- 【数据结构】树与二叉树的基本概念及性质
- 捍宇医疗再冲刺科创板上市:核心产品专利来自购买,暂未商业化
- 安卓手机各种信息获取---(通讯录短信息通话记录)