暂时未有相关云产品技术能力~
1995年12月4日,Netscape 公司与 Sun 公司联合发布JavaScript 以来,JavaScript从推出就开始了飞速的发展,2015年6,ES6正式发布,此后JavaScript正式进入新阶段,成为企业级大规模开发语言,并仍以高速度不断发展。下面的表格对应这版本变化:全称发布年份缩写 / 简称ECMAScript 20152015ES2015 / ES6ECMAScript 20162016ES2016 / ES7ECMAScript 20172017ES2017 / ES8ECMAScript 20182018ES2018 / ES9ECMAScript 20192019ES2019 / ES10ECMAScript 20202020ES2020 / ES11ECMAScript 20212021ES2021 / ES12ECMAScript 20222022ES2022 / ES13本文主要介绍几个已经进入stage4的提案,这几个提案有望在2022年逐步纳入标准。(请注意:纳入标准并不等同于浏览器支持)PS:科普-Javascript的新语法,从提出到纳入标准一共经历下面几个stagestage-0:新语法还是一个设想,(只能由TC39成员或TC39贡献者提出)stage-1::提案阶段,比较正式的提议,只能由TC39成员发起,这个提案要解决的问题必须有正式的书面描述。stage-2:草案,有了初始规范,必须对功能语法和语义进行正式描述,包括一些实验性的实现。stage-3:候选,该提议基本已经实现,需要等待实验验证,用户反馈及验收测试通过。stage-4:已完成,必须通过 Test262 验收测试,下一步就纳入ECMA标准。.at()TC39建议在所有基本可索引类,例如:数组、字符串、类数组(arguments)中添加.at()方法。例如lat arr=[1,2,3,4,5]之前我们想获取数组中的第二位arr[1] //2最后一位的话,可能就是arr[4] // 5但是如果arr长度是动态的呢?我们要如何让取出最后一位? 通常的写法是:arr[arr.length-1]但是有了.at()方法就很简单了,.at()支持正索引和负索引。例如arr.at(-1) //5 arr.at(-2) //4具体提案:https://github.com/tc39/proposal-relative-indexing-methodObject.hasOwn(object, property)Object.hasOwn(object, property)主要是用来替代Object.prototype.hasOwnProperty()。目前我们想要判断对象是否具有指定的对象,主要写法如下: if (Object.prototype.hasOwnProperty.call(object, "fn")) { console.log('有') }而Object.hasOwn的写法:if (Object.hasOwn(object, "fn")) { console.log("有") }具体提案:https://github.com/tc39/proposal-accessible-object-hasownproperty目前来看,V8引擎的9.3版本已经开始支持,所以说chrome应该会很快支持。类的私有方法和getter/setter类是所有支持面向对象语言的基本,而Javascript虽然支持使用class定义类,但是并没有提供 定义私有属性/方法的的 方案。本提案提出使用#来定义私有属性/方法class Person{ name = '小芳'; #age = 16; consoleAge(){ console.log(this.#age) } } const person = new Person(); console.log(person.name); //小芳 console.log(button.#age); //报错 button.#value = false;//报错具体提案:https://github.com/tc39/proposal-private-methods检查私有属性和方法因为新的标准会支持私有属性和方法,当我们访问不存在的私有属性/方法会报错,而在新标准中也考虑了这个情况,提供了in来检查私有属性和方法是否存在class C { #brand; #method() {} get #getter() {} static isC(obj) { return #brand in obj && #method in obj && #getter in obj; } }具体提案:https://github.com/tc39/proposal-private-fields-in-inTop-level await(顶层await)目前,我们使用await必须是在申明async的函数中,本提案,主要是支持在没有async的情况下使用await例如下面几种使用场景:动态引入依赖const strings = await import(`/i18n/${navigator.language}`);这允许模块使用运行时值来确定依赖关系。这对于开发/生产拆分、国际化、环境拆分等非常有用。资源初始化const connection = await dbConnector();这允许模块表示资源,并在模块永远无法使用的情况下产生错误。加载依赖let jQuery; try { jQuery = await import('https://cdn-a.com/jQuery'); } catch { jQuery = await import('https://cdn-b.com/jQuery'); }具体提案:https://github.com/tc39/proposal-top-level-await正则匹配索引该提案提供了一个新的/d,用来获取每个匹配的开始位置和结束位置信息。const str = 'The question is TO BE, or not to be, that is to be.'; const regex = /to be/gd; const matches = [...str.matchAll(regex)]; matches[0];具体提案:https://github.com/tc39/proposal-regexp-match-indicesnew Error()抛出异常的具体原因new Error(),可能大家第一反应是,这不是已经存在的语法嘛,是的,没错!只是新的提案:将错误与原因相关联,,向具有属性的Error() 构造函数添加一个附加选项参数cause,其值将作为属性分配给错误实例。async function doJob() { const rawResource = await fetch('//domain/resource-a') .catch(err => { throw new Error('Download raw resource failed', { cause: err }); }); const jobResult = doComputationalHeavyJob(rawResource); await fetch('//domain/upload', { method: 'POST', body: jobResult }) .catch(err => { throw new Error('Upload job result failed', { cause: err }); }); } try { await doJob(); throw new Error('Upload job result failed', { cause: err }); } catch (e) { console.log(e); console.log('Caused by', e.cause); } // Error: Upload job result failed // Caused by TypeError: Failed to fetch具体提案:https://github.com/tc39/proposal-error-cause类static初始化块本提案针对静态字段和静态私有字段的提供了一种在 ClassDefinitionEvaluation 期间执行类静态端的每个字段初始化的机制-static blocks.例如官方提供的例子:在没有static blocks之前,我们想给静态变量初始化(非直接赋值,可能是表达式赋值)的话,可能是放在外部实现:// without static blocks: class C { static x = ...; static y; static z; } try { const obj = doSomethingWith(C.x); C.y = obj.y C.z = obj.z; } catch { C.y = ...; C.z = ...; }有了static block的情况下:我们可以直接在static blocks中初始化变量:class C { static x = ...; static y; static z; static { try { const obj = doSomethingWith(this.x); this.y = obj.y; this.z = obj.z; } catch { this.y = ...; this.z = ...; } } }
系列文章目录Vue3入门到精通-setupVue3入门到精通–ref以及ref相关函数Vue3入门到精通–reactive以及reactive相关函数创作不易 拒绝白嫖 点个赞呗 关注我,带你走进前端的世界!!!是什么将引用类型数据–>响应式数据 ==> 把值类型的数据包装编程响应式的引用类型的数据object array map set weakmap weakset函数reactive参数必须是对象(json/arr)默认情况下修改对象, 界面不会自动更如果想更新, 可以通过重新赋值的方式本质: 将传入的数据包装成一个Proxy对象用法创建变量案例1import {reactive} from 'vue'; let state = reactive([1, 2, 3]); console.log(state) // Proxy {0: 1, 1: 3, 2: 5} 注意!!!<p>{{state}}</p> <button @click="myFn">按钮</button> let obj = [1, 2, 3]; let state = reactive(obj) console.log(obj); // (3) [1, 2, 3] console.log(state); // Proxy {0: 1, 1: 2, 2: 3} // 页面显示是[1, 2, 3] function myFn() { state[3] = "zs"; console.log(obj); //(4) [1, 2, 3, "zs"] console.log(state); //Proxy {0: 1, 1: 2, 2: 3, 3: "zs"} // 点击按钮后 // 页面显示是[1, 2, 3, "zs"] // 由此-》根据下标修改数据可以触发页面的更新 // 且 state的修改对原数据的修改有影响 } function myFn() { obj[3] = "ls"; console.log(obj); //(4) [1, 2, 3, "ls"] console.log(state); //Proxy {0: 1, 1: 2, 2: 3, 3: "ls"} // 点击按钮后 // 页面显示是[1, 2, 3] // 且 原数据的修改对state的修改有影响 // 但是页面不会触发更新 } function myFn() { state = [4,5,6]; console.log(obj); //(3) [1, 2, 3] console.log(state); //(3) [4, 5, 6] // 点击按钮后 // 页面显示是[1, 2, 3] // 直接对state进行修改不会触发页面的更新,但是上面对下标进行修改可以触发页面更新 // 同时这里直接进行复制,导致state不再是proxy // 这里你可以使用 // Object.assign(state,[4,5,6]) // 这样也可以 触发页面的更新, // 这个方法在ajax请求之后进行赋值,很好用 } 案例2import {reactive} from 'vue'; let state = reactive( { name: "zs", age: 19 }); // 这里不再赘述,效果和上面的Array一致 ref和reactive的区别ref是把值类型添加一层包装,使其变成响应式的引用类型的值。reactive 则是引用类型的值变成响应式的值。所以两者的区别只是在于是否需要添加一层引用包装本质上ref(0) --> reactive( { value:0 })相关APIisReactive作用检查对象是否是 reactive创建的响应式 proxy。其实内部是判断数据对象上是否包含__v_isRef 属性并且其值为 true。用法let state = reactive( { name: "zs", age: 19 }); console.log(isReactive(state)) // true readonly作用声明一个只读的proxy与const的区别const: 赋值保护, 不能给变量重新赋值readonly: 属性保护, 不能给属性重新赋值用法<p>{{state.name}}</p> <p>{{state.attr.age}}</p> <button @click="myFn">按钮</button> let state = readonly({name:'syl', attr:{age:18}}); function myFn() { state.name = 'zs'; state.attr.age = 19; console.log(state); // proxy{name:'syl', attr:{age:18}} console.log(isReadonly(state)); // true // 变量无法更改 // 点击按钮后页面没有变化 } isReadonly作用检查对象是否是由readonly创建的只读代理shallowReactive作用创建一个响应式代理,该代理跟踪其自身 property 的响应性,但不执行嵌套对象的深度响应式转换 (暴露原始值)。官网例子当从合成函数返回响应式对象时,toRefs 非常有用,这样消费组件就可以在不丢失响应性的情况下对返回的对象进行分解/扩散:<p>{{ state.a }}</p> <p>{{ state.attr.b }}</p> <p>{{ state.attr.c.d }}</p> <button @click="myFn">按钮</button> let state = shallowReactive({ a: "a", attr: { b: "b", c: { d: "d", }, }, }); function myFn() { state.attr.c.d='5' console.log(state.attr.c.d); //5 // 点击按钮后页面没有变化 } function myFn() { state.a='5' console.log(state.a); //5 // 点击按钮后页面变化 }shallowReadonly作用用于创建一个只读的数据, 但是不是递归只读的<p>{{state.name}}</p> <p>{{state.attr.age}}</p> <button @click="myFn">按钮</button> let state = shallowReadonly({name:'syl', attr:{age:18}}); function myFn() { state.attr.age = 19; console.log(state.attr.age) // 19 // 点击按钮页面没有变化 } function myFn() { state.name = 'ls'; console.log(state.name) // syl // 数据无法更改 // 点击按钮页面没有变化 } toRaw做用从reactive 得到原始数据用法let obj = {name:'syl', age:18}; /* ref/reactive数据每次修改都会被追踪, 都会更新界面 但是当你不需要更新UI界面, 可以通过toRaw方法拿到它的原始数据, 对原始数据进行修改 这样就不会被追踪不会更新界面, */ let state = reactive(obj); let obj2 = toRaw(state); console.log(obj === obj2); // true function myFn() { obj2.name = 'zs'; console.log(obj2); // {name: "zs", age: 18} console.log(state); // {name: "zs", age: 18} } // 这个例子在上面出现过
系列文章目录Vue3入门到精通-setupVue3入门到精通–ref以及ref相关函数Vue3入门到精通–reactive以及reactive相关函数创作不易 拒绝白嫖 点个赞呗 关注我,带你走进前端的世界!!!是什么将基础数据–>响应式数据 ==> 把值类型的数据包装编程响应式的引用类型的数据函数通过返回值的 value 属性获取响应式的值 ,修改也需要对 .value进行修改。获取元素在Vue2.x通过给元素添加ref=‘xxx’,,然后使用refs.xxx的方式来获取元素在Vue3.x中我们也可以通过ref来获取元素用法创建变量import { ref } from 'vue' const count = ref(0) console.log(count.value) // 0 count.value = 2 console.log(count.value) // 2ref也可以接收复杂的数据类型作为参数,只是建议不使用ref处理复杂类型数据。在单文件组件中,不必写value,因为setup方法会自动解析<template> <div> <span>{{ count }}</span> <button @click="count ++">Increment count</button> </div> </template>获取元素<template> <div ref="refDiv">我是div</div> </template> <script> import {ref, onMounted} from 'vue'; export default { name: 'App', setup() { let refDiv = ref(null); onMounted(()=>{ console.log('onMounted',refDiv.value); // onMounted <div style="color: red;">我是div</div> refDiv.value.style.color="red" // 字体颜色变成红色 }); // setup 生命周期在mounted之前 console.log(box.value); // null return {box}; } } </script>ref和reactive的区别ref是把值类型添加一层包装,使其变成响应式的引用类型的值。reactive 则是引用类型的值变成响应式的值。所以两者的区别只是在于是否需要添加一层引用包装本质上 ref(0) --> reactive( { value:0 })注意点ref 对于 基本类型ref-创建出来的数据和以前无关(复制) 与js中的基本类型表现一致let a = 1; let aRef = ref(a); console.log(a, aRef.value); //1 1 a = 2; console.log(a, aRef.value);// 2 1 aRef.value = 3; console.log(a, aRef.value);// 2 3ref 对于 引用数据类型ref-创建出来的数据和以前相关(引用) 与js中的引用数据类型表现一致let obj = { name: "1" }; let stateRef = ref(obj); console.log("obj", obj.name); console.log("ref", stateRef.value.name); // obj 1 // ref 1 stateRef.value.name = '2'; console.log("obj", obj.name); console.log("ref", stateRef.value.name); // obj 2 // ref 2 obj.name='3' console.log("obj", obj.name); console.log("ref", stateRef.value.name); // obj 3 // ref 3相关APIisRef作用判断是都是ref对象其实内部是判断数据对象上是否包含__v_isRef 属性并且其值为 true。用法const a = ref(a) const b = 'b' cosnole.log(isRef(a)) // true console.log(isRef(b)) // falseunref如果参数为 ref,则返回内部值,否则返回参数本身。这是 val = isRef(val) ? val.value : val。const temp=ref(3) const newTemp = unref(1) // newTemp 确保现在是数字类型 3 const a = unref(1) // a 确保现在是数字类型 1 toRef作用将引用数据类型转换为ref数据类型将reavtive数据类型转换为ref数据类型用法引用数据类型let obj = { name: "syl", age: "123" }; let stateToref = toRef(obj, "name"); // 将name拿出来 stateToref.value = "zs"; console.log("obj", obj.name); console.log("ref", stateToref.value); // obj zs // ref zs obj.name = "ls"; console.log("obj", obj.name); console.log("ref", stateToref.value); // obj ls // ref ls reactive数据类型let obj = reactive({ name: "syl", age: "123" }); let stateToref = toRef(obj, "name"); // 将name拿出来 stateToref.value = "zs"; console.log("obj", obj.name); console.log("ref", stateToref.value); // obj zs // ref zs obj.name = "ls"; console.log("obj", obj.name); console.log("ref", stateToref.value); // obj ls // ref ls注意点数据发生改变, 界面也不会自动更新案例1<p>toref----------{{ stateToref }}</p> // 这里显示的是zs let obj = { name: "syl" }; let stateToref = toRef(obj, "name"); stateToref.value = "zs"; console.log("obj", obj.name); console.log("ref", stateToref.value); // obj zs // ref zs 案例2<p>toref----------{{ stateToref }}</p> <button @click="changeToref">changeToref</button> let obj = { name: "syl" }; let stateToref = toRef(obj, "name"); function changeToref() { stateToref.value = "ls"; console.log("obj", obj.name); console.log("toref", stateToref.value); } // 点击changeToref,页面没有任何变化,仍然显示syl // console的结果是 // obj ls // toref ls一个有意思的例子 <p>toref----------{{ stateToref }}</p> <p>temp----------{{ temp }}</p> <button @click="changeToref">changeToref</button> let obj = { name: "syl" }; let stateToref = toRef(obj, "name"); let temp = ref("我是ref"); function changeToref() { temp.value = "我是ref我改变啦!"; stateToref.value = "ls"; } // 点击按钮,页面的ui从 toref----------syl temp----------我是ref // 变成 oref----------ls temp----------我是ref我改变啦! 这里可以看到ref触发了ui更新,导致toref的值也进行了更新 其实不把这个ref的更新写到这个函数里面,比如新建函数,也会导致这个现象 这个现象对其他函数也出现,例如shallowRef。toRefs作用批量转换。将响应式对象转换为普通对象,会将传入对象的每个属性处理为 ref 的值。官网例子当从合成函数返回响应式对象时,toRefs 非常有用,这样消费组件就可以在不丢失响应性的情况下对返回的对象进行分解/扩散:function useFeatureX() { const state = reactive({ foo: 1, bar: 2 }) // 返回时转换为ref return toRefs(state) } export default { setup() { // 可以在不失去响应性的情况下破坏结构 const { foo, bar } = useFeatureX() return { foo, bar } } }shallowRef 与triggerRef作用shallowRef创建一个 ref,它跟踪自己的 .value 更改,但不会使其值成为响应式的。也就是对value进行更新才会触发页面的更新,但是如果是一个引用数据类型,只对改引用数据进行值的修改,则不会触发更新。案例- 基本数据类型<p>{{ state1 }}</p> <button @click="myFn1">基本数据类型</button> let state1 = shallowRef(1); function myFn1() { state1.value = 2; } // 点击按钮,页面会显2 // 也就是对value进行修改可以触发页面更新 案例- 引用数据类型<p>{{ state.a }}</p> <p>{{ state.b.c }}</p> <button @click="myFn1">引用数据类型-直接修改value</button> <button @click="myFn2">引用数据类型-对数据进行修改</button> let state = shallowRef({ a: "a", b: { c: "c", }, }); function myFn1() { state.value={ a: "a-new", b: { c: "c-new", }, } } // 点击mufun1 页面从 a c // 变成 a-new c-new // 由此可以看出直接对value进行修改可以触发页面更新 function myFn2() { state.value.a = "1"; state.value.b.c = "1"; console.log(state.value.a , state.value.b.c ) } // 点击mufun2 页面仍然显示 a c // console的结果是1 1triggerRef通常与shallowRef 一起使用,主要是主动触发界面更新的参数是ref变量<p>{{ state.a }}</p> <p>{{ state.b.c }}</p> <button @click="myFn2">使用triggerRef</button> let state = shallowRef({ a: "a", b: { c: "c", }, }); function myFn2() { state.value.a = "1"; state.value.b.c = "1"; triggerRef(state); } // 点击mufun2 页面变成 1 1 customRef自定义ref返回一个ref对象,可以显式地控制依赖追踪和触发响应<template> <div> <p>{{age}}</p> <button @click="myFn">按钮</button> </div> </template> import {ref, customRef} from 'vue'; function myRef(value) { return customRef((track, trigger)=>{ return { get(){ track(); // 告诉Vue这个数据是需要追踪变化的 console.log('get', value); return value; }, set(newValue){ console.log('set', newValue); value = "我的年龄==="+newValue; trigger(); // 告诉Vue触发界面更新 } } }); } setup() { // let age = ref(18); // reactive({value: 18}) let age = myRef(18); function myFn() { age.value += 1; } return {age, myFn} } } // 页面显示的是18 // 点击button按钮后,变成了我的年龄===19 // 注意点: // 不能在get方法中发送网络请求
系列文章目录Vue3入门到精通-setupVue3入门到精通–ref以及ref相关函数Vue3入门到精通–reactive以及reactive相关函数创作不易 拒绝白嫖 点个赞呗 关注我,带你走进前端的世界!!!是什么组合(composition)API的入口setup 所处的生命周期beforeCreate -> use setup()created -> use setup()beforeMount -> onBeforeMountmounted -> onMountedbeforeUpdate -> onBeforeUpdateupdated -> onUpdatedbeforeDestroy -> onBeforeUnmountdestroyed -> onUnmountederrorCaptured -> onErrorCaptured参数(props,context)props父组件传递的propsfather<template> <div> <child :dataFromFather="name" > </child> </div> </template> <script > import { ref } from "@vue/runtime-core"; import child from "./child.vue"; export default { components: { child, }, setup() { let name=ref('来自父组件的数据') return {name} }, }; </script> >child props:['dataFromFather'], setup(props, context) { console.log('dataFromFather=',props.dataFromFather) // 输出的是 '来自父组件的数据' }contextattrsslotsfather <child > <template v-slot:slot1> <h1>使用slot1</h1> </template> <template v-slot:slot2> <p>使用slot2</p> </template> </child>child// 定义slot1 和 slot2 <template> <div> <p>slot1</p> <slot name="slot1"></slot> </div> <div> <p>slot2</p> <slot name="slot2"></slot> </div> </template> <script> export default { setup(props, context) { console.log("1=", context.slots); onMounted: { console.log("2=", context.slots); } }, }; // 这里的打印结果 1=和2= 是一致的,打印的都是Proxy:slot1和slot2 !!! 若是father注释slot2的使用,那么只会打印proxy:slot1 </script>emitchild<template> <div> <button @click="show">子组件</button> </div> </template> <script> export default { setup(props, context) { function show(){ context.emit('childShow','来自子组件') } return {show} }, }; </script> father<template> <div> <child @childShow='fatherShow'> </child> </div> </template> <script lang='ts'> import { onMounted } from "@vue/runtime-core"; import child from "./child.vue"; export default { components: { child, }, setup(props, context) { function fatherShow(data:any){ console.log(data) // 这里输出的是 ‘来自子组件 } return {fatherShow} }, }; </script> 使用渲染函数import { h, ref, reactive } from 'vue' export default { setup() { const readersNumber = ref(0) const book = reactive({ title: 'Vue 3 Guide' }) // 请注意,我们需要在这里显式地暴露ref值 return () => h('div', [readersNumber.value, book.title]) } }
描述亚历克斯计划参观博物馆,并在柜台购买相同的通行证。管理员决定不出售团体通行证,一次只提供一张通行证。如果访客需要一张以上的通行证,他/她必须再次重新排队到柜台并购买下一张通行证。亚历克斯想购买许多通行证。访客顺序和每位访客需要的通行证数量是已知的,亚历克斯需要多少时间才能买到所有的通行证?Alex在队列中的位置将被给定,每次交易需要1个时间单位。可以忽略每次转到行后面所需的时间。arr|<=100000 arr[i]<=10000样例样例 1:输入: arr=[1,2,5],k=1 输出: 4 解释: 有3个人 0,1,2 在排队。亚历克斯的编号是1 第一个时间点,队列为0(1)<-1(2)<-2(5),编号0获得门票。 第二个时间点,队列为1(2)<-2(5) 亚克斯获得门票,并返回队伍最末端 第三个时间点,队列为2(5)<-1(1) 编号2获得门票,并返回队伍最末端 第四个时间点,队列为1(1)<-2(4) 亚克斯获得门票,他已经买到了所需要的所有门票样例 2:输入: arr=[3,2,1], k = 0, 输出: 6题解前面的人是 min(A[i], A[k]) 自己是A[k] 后面的人是 min(A[i], A[k]-1)export class Solution { /** * buyPasses * * @param arr: the line * @param k: Alex place * @return: the time when Alex requires to buy all passes */ buyPasses(arr, k) { // Write your code here. let ans = 0; for (let i = 0; i < arr.length; i++) { if (i <= k) ans += Math.min(arr[k], arr[i]); else ans += Math.min(arr[k] - 1, arr[i]); } return ans; } }
描述请编写 SQL 语句,查询课程表 courses 中课程名称为 System Design 的课程信息。表定义:courses(课程表)列名类型注释idint主键namevarchar课程名称student_countint学生总数created_atdate开课时间teacher_idint讲师 id**如果查询不到结果,就什么都不返回。样例样例一:表内容:coursesidnamestudent_countcreated_atteacher_id1Advanced Algorithms8802020-6-142System Design13502020-7-1833Django7802020-2-2934Web3402020-4-2245Big Data7002020-9-1116Artificial Intelligence16602018-5-1337Java P6+7802019-1-1938Data Analysis5002019-7-12110Object Oriented Design3002020-8-8412Dynamic Programming20002018-8-181在运行你的 SQL 语句之后,表应返回:idnamestudent_countcreated_atteacher_id2System Design13502020-7-183样例二:表内容:coursesidnamestudent_countcreated_atteacher_id1Advanced Algorithms8802020-6-142Java P6+13502020-7-1833Django7802020-2-2934Web3402020-4-2245Big Data7002020-9-111在运行你的 SQL 语句之后,表应返回:idnamestudent_countcreated_atteacher_id样例二中没有符合条件的数据,所以输出中只包含表头而没有数据。题解这道题是一道入门级别的数据库查询题,建单的一个select即可成功。 这里有个注意点是:postgresql的查询条件WHERE name =‘System Design’;这里用的是单引号,如果使用双引号会报错。unterminated quoted identifier at or near "“System Design’;” LINE 3: WHERE name ="System Design’;MYSQLSELECT id, name, student_count, created_at, teacher_id FROM courses WHERE name ="System Design"; • 1 • 2 • 3PostgresqlSELECT id, name, student_count, created_at, teacher_id FROM courses WHERE name ='System Design'; • 1 • 2 • 3 • 4
官方简介Koa 是一个新的 web 框架,由 Express 幕后的原班人马打造, 致力于成为 web 应用和 API 开发领域中的一个更小、更富有表现力、更健壮的基石。 通过利用 async 函数,Koa 帮你丢弃回调函数,并有力地增强错误处理。 Koa 并没有捆绑任何中间件, 而是提供了一套优雅的方法,帮助您快速而愉快地编写服务端应用程序。前置知识node http使用http搭建服务step1:引入httpvar http = require('http');step2: createServer方法创建http服务let server=http.createServer(function (request, response) { response.writeHead(200, {'Content-Type': 'text/plain'}); response.end('Hello World'); })step3:监听端口server.listen(8000);koa简单用法const Koa = require('koa'); const app = new Koa(); app.use(async ctx => { ctx.body = 'Hello World'; }); app.listen(3000);核心目录application.js: 入口,导出koa。context.js:上下文request.js:处理请求response.js:处理响应导出koa类上面我们简单介绍了koa的用法,可以看出koa有两个核心的函数,一个use,一个listen。我们先来实现这两个函数。 我们已经预先学习了http的用法,那么事情就很好办了!koa类application.js 先定义一个koa的基本结构。class Application { use() { } listen() { } } module.exports = Applicationapp.listen主要是将http.listen封装一下。class Application { callback = (req, res) => { res.end('Hello World\n'); } listen() { const server = http.createServer(this.callback); console.log(...arguments) server.listen(...arguments) } }测试一下:test.jsconst Koa=require('./application.js') const app=new Koa() app.listen(3000)可以正常访问 app.use在前置知识中我们看到,app.use接收一个回调函数,同时传入一个ctx上下文,这里ctx将request和response封装起来。为了清晰易懂,我们先不进行上下文的封装。app.use(async ctx => { ctx.body = 'Hello World'; });那么use简单的处理如下:class Application { use(fn) { this.fn=fn } } 此时use接收了一个函数,这个函数的执行的时机是在访问网站的时候,那么此时就需要在创建http服务的时候,传入这个函数。最好的方式就是放在listen的callbak中调用。callback = (req, res) => { this.fn(req, res) }最终代码let http = require('http') class Application { use(fn) { this.fn=fn } callback = (req, res) => { this.fn(req, res) } listen() { const server = http.createServer(this.callback); server.listen(...arguments) } } module.exports = Application测试:test.jsconst Koa=require('./application.js') const app=new Koa() app.use((req, res) => { res.end('Hello World\n'); }) app.listen(3000)可以正常访问 封装ctx明确一个事实:每个请求都是独立的,对于原生的http请求来说,每次请求的response和request是不同的。对于koa中的ctx,则表示每次请求的ctx都是一个新的ctx。ctx的结构为了看到ctx的结构,我们先使用源koa打印一下ctx。最终得到的结果如下所示,有了这个结构我们就可以实现一个自己的ctx。下面这个格式是console.dir(ctx)的结果(删掉了一些具体的内容),从下面的内容,我们可以得出ctx的结构。。{ request: { app: Application { }, req: IncomingMessage { }, res: ServerResponse { }, ctx: [Circular], response: { app: [Application], req: [IncomingMessage], res: [ServerResponse], ctx: [Circular], request: [Circular] }, originalUrl: '/' }, response: { app: Application { }, req: IncomingMessage { }, res: ServerResponse { }, ctx: [Circular], request: { app: [Application], req: [IncomingMessage], res: [ServerResponse], ctx: [Circular], response: [Circular], originalUrl: '/' } }, app: Application { }, req: IncomingMessage { }, res: ServerResponse { }, originalUrl: '/', state: {} }context.jscontext.js 主要定义了context的具体结构以及提供的方法。Koa Context 将 node 的 request 和 response 对象封装到单个对象中,为编写 Web 应用程序和 API 提供了许多有用的方法。 这些操作在 HTTP 服务器开发中频繁使用,它们被添加到此级别而不是更高级别的框架,这将强制中间件重新实现此通用功能。request.js和response.js文件在核心目录,我们提到了这两个文件,这两个文件此时就派上了用场。这两个文件具体实现了啥呢?这两个文件定义了ctx.resopnse和ctx.request的结构,也就是上面使用dir输出的结果。在koa中文文档中可以具体的看到结构,可以自行查阅。Koa Request 对象是在 node 的 原生请求对象之上的抽象,提供了诸多对 HTTP 服务器开发有用的功能。Koa Response 对象是在 node 的原生响应对象之上的抽象,提供了诸多对 HTTP 服务器开发有用的功能。实现ctx定义context.jsconst context={ } module.exports=context定义request.jsconst resposne={ } module.exports=response定义response.jsconst resposne={ } module.exports=responseuse中封装ctx我们在上面导出koa章节中可以看到,在app.use的时候,我们传的参数是(request,response),源koa传的的ctx,所以我们就知道了,koa是在app.use的时候创建了一个ctx。在本章开头的时候,我们又提到每次请求的ctx都是全新的ctx。综合以上两点,我们可以基本编写出下面的代码。(为了代码的清晰易读,我们封装了一个createcontext函数来创建上下文。)const Context = require('./context') const Request = require('./request') const Response = require('./response') class Application { constructor(){ this.context = Object.create(Context); this.request = Object.create(Request); this.response = Object.create(Response); } use(fn) { this.fn = fn } createContext = (req, res) => { const ctx = Object.create(this.context); const request = Object.create(this.request); const response = Object.create(this.response); ctx.app = request.app = response.app = this ctx.request = request; ctx.request.req = ctx.req = req; ctx.response = response; ctx.response.res = ctx.res = res; ctx.originalUrl = request.originalUrl = req.url ctx.state = {} return ctx } callback = (req, res) => { let ctx = this.createContext(req, res) this.fn(ctx) } listen() { const server = http.createServer(this.callback); console.log(...arguments) server.listen(...arguments) } }首先我们在constructor中定义了一个context对象,这里会在constructor定义是因为Koa的app上默认导出context属性。app.context 是从其创建 ctx 的原型。您可以通过编辑 app.context 为 ctx 添加其他属性。这对于将 ctx 添加到整个应用程序中使用的属性或方法非常有用,这可能会更加有效(不需要中间件)和/或 更简单(更少的 require()),而更多地依赖于ctx,这可以被认为是一种反模式。 例如,要从 ctx 添加对数据库的引用:app.context.db = db(); app.use(async ctx => { console.log(ctx.db); });然后再callback中,我们针对response和request进行了二次封装。再来看看这段代码:>app.context.db = db(); >app.use(async ctx => { > console.log(ctx.db); >});再使用use之前,通过app.context对context进行了修改。当使用use函数的时候,是不是直接进入了callback函数,此时的this.context已经是修改过的了。测试const Koa=require('./application.js') const app=new Koa() app.use((ctx) => { // 测试1 ctx.response.res.end(" hello my koa") // 测试2 ctx.res.end(" hello my koa") }) app.listen(3000,()=>{ console.log('3000') })正常访问!封装request.js明确一个事实:request类的属性是通过getter和setter设置的。为什么会这样设置?这样设置的好处是可以方便的设置和获取到值。是不是有点懵逼!请听我细细道来。先来看一下Koa中request类所绑定的属性,官方链接。 我这里简单的列举几个:### request.header= 设置请求头对象。 ### request.headers 请求头对象。别名为 `request.header`. ### request.headers= 设置请求头对象。别名为 `request.header=` ### request.url 获取请求 URL. ### request.url= 设置请求 URL, 对 url 重写有用。 ### request.originalUrl 获取请求原始URL。这里对于每个属性都有设置和获取的功能,使用getter和setter可以很好的实现。这里的每个属性是如何获取的呢?还记得我们在request绑定了一个啥?node http原生的request(req)对不对,当我们使用Object.create并ctx.request.req=req之后,对于当前的request对象是不是都有了一个req属性。那么是不是可以通过getter进行获取。 get url () { return this.req.url },这里的每个属性是如何设置的,如果我们对request本身设置有效吗? 例如下面的结构:const request={ url:'', header:{ } } 我们直接request.url=“https://juejin.cn/”, 这样会导致一个bug,是啥呢?还记得 我们的数据是从哪里取得的,req中获取的,如果你set的时候不是对req.url进行设置,你能获取到这个值吗?所以request的结构是这样子的。const request={ set url (val) { this.req.url = val } get url () { return this.req.url }, }request.socket的gettersocket在这里指套接字。套接字的概念这里不赘述! get socket () { return this.req.socket },request.protocol的getter返回请求协议,“https” 或 “http”。当 app.proxy 是 true 时支持 X-Forwarded-Proto。先判断套接字中是否存在encrypted(加密),如果加密,就是https,X-Forwarded-Proto用来确定客户端与代理服务器或者负载均衡服务器之间的连接所采用的传输协议(HTTP 或 HTTPS)X-Forwarded-Proto: https X-Forwarded-Proto: http get protocol () { if (this.socket.encrypted) return 'https' if (!this.app.proxy) return 'http' const proto = this.get('X-Forwarded-Proto') return proto ? proto.split(/\s*,\s*/, 1)[0] : 'http' }, 这里有一个get函数,主要时根据字段,从请求头中获取数据。 get (field) { const req = this.req switch (field = field.toLowerCase()) { case 'referer': case 'referrer': return req.headers.referrer || req.headers.referer || '' default: return req.headers[field] || '' } }, request.host的getter存在时获取主机(hostname:port)。当 app.proxy 是 true 时支持 X-Forwarded-Host,否则使用 Host。get host () { const proxy = this.app.proxy let host = proxy && this.get('X-Forwarded-Host') if (!host) { if (this.req.httpVersionMajor >= 2) host = this.get(':authority') if (!host) host = this.get('Host') } if (!host) return '' return host.split(/\s*,\s*/, 1)[0] }, request.origin的getter获取URL的来源,包括 protocol 和 host。例如我请求:http://localhost:3000/index?a=3,origin返回的是http://localhost:3000get origin () { return `${this.protocol}://${this.host}` },request.href的getter获取完整的请求URL,包括 protocol,host 和 url。href支持解析 GET http://example.com/foo例如我访问http://localhost:3000/index?a=3 href返回http://localhost:3000/index?a=3 get href () { if (/^https?:\/\//i.test(this.originalUrl)) return this.originalUrl return this.origin + this.originalUrl }, 注意:这里的this.originalUrl在封装ctx的时候已经绑定过了 request.header 的getter和setter请求头对象。这与 node http.IncomingMessage 上的 headers 字段相同 get header () { return this.req.headers }, set header (val) { this.req.headers = val },request的属性是很多的,我们就不展开了,反正知道了原理,大家慢慢自己加吧。封装response.js对比request的封装,response的封装稍微有些不同,因为,对于request来说大部分的封装是getter,而response的封装大部分都是setter在request部分我们阐述了三个使用getter和setter的原因。在resposne中最主要的原因我觉得是改变set的对象。其实想一想很简单,例如在网络请求中我们会经常遇到各种状态:404 200等等,这些在node的http模块中,是用resposne.status进行改变的。假设我们在koa的response直接设置,你觉得会有用吗?简单概括一句话:koa的request和respsone是对nodehttp模块的二次封装,并且底层还是对nodehttp模块的操作。response.status的getterh和setter获取响应状态。默认情况下,response.status 设置为 404 而不是像 node 的 res.statusCode 那样默认为 200。默认’404’,这里的默认是在何时默认的时候呢,其实是在接收到请求后就设置为404,也就是说在callback的时候开始设置为404。(注意:http中res.statusCode用来标记状态码,在Koa中这个被封装成status) callback = (req, res) => { let ctx = this.createContext(req, res) const res = ctx.res res.statusCode = 404 this.fn(ctx) }response.status的实现 get status () { return this.res.statusCode }, set status (code) { if (this.headerSent) return assert(Number.isInteger(code), 'status code must be a number') assert(code >= 100 && code <= 999, `invalid status code: ${code}`) this._explicitStatus = true this.res.statusCode = code if (this.req.httpVersionMajor < 2) this.res.statusMessage = statuses[code] if (this.body && statuses.empty[code]) this.body = null }, response.body的getter和setter首先我们要知道body是用来干嘛的。body是用来设置响应主体的,也就是返回响应的内容的。这些内容支持以下格式:string 写入Buffer 写入Stream 管道Object || Array JSON-字符串化null 无内容响应nodehttp中是 res.end(“我是返回内容”) 返回响应内容的。在koa中我们是通过ctx.body="" 来设置响应内容的。这里有人会问了,ctx.body和resopnse.body 有啥关系。其实他们是一个东西,ctx里面封装了response.body。koa中通过设置ctx.body,就能返回内容,其实本质还是使用了res.end(),通过res.end(ctx.body)来返回内容。res.end的调用时机在这里是放在callback中(具体的原因我们后面会说到)const response = { _body: undefined, get body() { return this._body }, set body(originContent) { this.res.statusCode = 200; this._body = originContent; } }; 封装context.js先谈谈Koa用到的delegates。这是一个实现了代理模式的包。对于Koa来说,context就是response和request的代理,通过ctx可以直接拿到request和response的属性和方法。 下面的是Koa主要用到的两个方法。其实最终的效果和封装request和response的效果一致。__defineGetter__ 方法可以将一个函数绑定在当前对象的指定属性上,当那个属性的值被读取时,你所绑定的函数就会被调用。__defineSetter__ 方法可以将一个函数绑定在当前对象的指定属性上,当那个属性被赋值时,你所绑定的函数就会被调用。(这两个方法已废弃: 该特性已经从 Web 标准中删除,虽然一些浏览器目前仍然支持它,但也许会在未来的某个时间停止支持,请尽量不要使用该特性。)Delegator.prototype.setter = function (name) { var proto = this.proto; var target = this.target; this.setters.push(name); proto.__defineSetter__(name, function (val) { return this[target][name] = val; }); return this; };Delegator.prototype.getter = function (name) { var proto = this.proto; var target = this.target; this.getters.push(name); proto.__defineGetter__(name, function () { return this[target][name]; }); return this; }; 这里我们将delegates的核心逻辑抽离,封装context function defineGetter(target, key) { context.__defineGetter__(key, function () { return this[target][key] }) } function defineSetter(target, key) { context.__defineSetter__(key, function (value) { this[target][key] = value }) }const context = {}; defineGetter('request', 'path') defineGetter('response', 'body') ) module.exports = context; 这里我们就列了两个,其他的不再赘述。ctx.body再追述在上面我们谈到了response.body以及ctx通过代理模式,拿到了response.body.在Koa的源码中,针对不同格式的内容进行了不同的处理.大家简单看一下就可以。response = { set body (val) { const original = this._body this._body = val // no content if (val == null) { if (!statuses.empty[this.status]) { if (this.type === 'application/json') { this._body = 'null' return } this.status = 204 } return } // 内容存在(设置了内容),这是状态码为200 if (!this._explicitStatus) this.status = 200 // string 字符串 if (typeof val === 'string') { if (setType) this.type = /^\s*</.test(val) ? 'html' : 'text' this.length = Buffer.byteLength(val) return } // buffer if (Buffer.isBuffer(val)) { if (setType) this.type = 'bin' this.length = val.length return } // stream if (val instanceof Stream) { onFinish(this.res, destroy.bind(null, val)) if (original !== val) { val.once('error', err => this.ctx.onerror(err)) // overwriting if (original != null) this.remove('Content-Length') } if (setType) this.type = 'bin' return } // json this.remove('Content-Length') this.type = 'json' } }, ctx.body最终是在res.end()返回的,这个时机是在callback中调用的。我们通过app.use来传入我们要执行的方法,这个方法里面有ctx.body的赋值。app.use((ctx) => { console.log(ctx.request.href) ctx.body="123" }) 在callback中我们先创建了上下文,然后我们调用了传入的方法。 callback = (req, res) => { let ctx = this.createContext(req, res) this.fn(ctx) } 那么我们是不是应该在fn执行结束之后,调用res.end(),因为这个时候body才被赋值 callback = (req, res) => { let ctx = this.createContext(req, res) this.fn(ctx) let body = ctx.body; if (body) { res.end(body); } else { res.end('Not Found') } }小结至此已经实现了koa的基本内容。 具体来说:response通过getter和setter,封装了nodehttp的resrequest通过getter和setter,封装了nodehttp的reqctx通过代理,拿到了response和request的属性方法
最简单的三角气泡实现思路:使用一个::before和::after,对两个设置边框,最后边框的效果就是三角形,一个三角形的边框颜色div一致,两一个则是白色,整好覆盖在上方。代码 .bubble-box { position: relative; border: 2px solid #409eff; border-radius: 5px; width: 200px; height: 50px; line-height: 50px; text-align: center; } .bubble-box::before { position: absolute; right: 100%; top: 50%; margin: -5px 0 0px; border: 10px solid transparent; border-right-color: #409eff; content: ""; } .bubble-box::after { position: absolute; right: 100%; top: 50%; margin-top: -3px; border: 8px solid transparent; border-right-color: #fff; content: ""; } 斜三角形气泡实现逻辑还是使用::after,使用它制作一个直角三角形然后使用transform进行角度的倾斜达到效果。 .bubble-box { position: relative; border: 2px solid #409eff; border-radius: 5px; width: 200px; height: 50px; line-height: 50px; text-align: center; } .bubble-box::after { content: ""; position: absolute; border:10px solid transparent; border-top-color: #409eff; border-right-color: #409eff; right: 100%; top: 10%; transform: skewY(10deg); }拖尾气泡实现思路仔细观察图片:首先可以看到右下角的拖尾是有弧度的,在CSS中最简单实现弧度的方法:就是对元素的圆角进行操作,只需要对两条边同时操作,即可产生效果。border-bottom-left-radius: 15px 15px;然后的话,拖尾是比较小的,并没有图示的大,这个时候再简单的方法,就是在上面加一层白色的div,覆盖掉其中的一部分。 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> <style> .bubble-box { position: relative; text-align: center; width: 200px; height: 50px; line-height: 50px; background-color: #409eff; border-radius: 25px; } .bubble-box::before { content: ""; position: absolute; z-index: -1; bottom: -2px; right: -8px; height: 20px; border-right: 20px solid #409eff; border-bottom-left-radius: 15px 15px; -webkit-transform: translate(0, -2px); } .bubble-box::after { content: ""; position: absolute; z-index: 1; bottom: -2px; right: -56px; width: 26px; height: 20px; background: white; border-bottom-left-radius: 10px; -webkit-transform: translate(-30px, -2px); } </style> </head> <body style="padding: 100px"> <div class="bubble-box">picker</div> </body> </html>
前言相信大家在使用webpack的时候,总是不知道如何下手,对于不同的场景,总是找不到合适的webpack的插件,本系列按照github的star数量排序,整理了很多插件,建议收藏,以后用得到! 本文先介绍部分高star插件,后面会持续更新。top1:Webpack Bundle Analyzer ⭐14.4K地址使用交互式可缩放树图可视化 webpack 输出文件的大小。top2:HTML Webpack Plugin ⭐11.3k地址简化创建 HTML 文件以服务于您的包的插件top3: prerender-spa-plugin ⭐9.8k地址这个插件的目标是提供一个简单的预渲染解决方案,该解决方案易于扩展并可用于任何站点或使用 webpack 构建的单页应用程序。1 Purgecss ⭐ 6,436链接PugeCSS 是一个删除未使用的 CSS 的工具。它可以是您开发工作流程的一部分。 当你在建一个网站时,你可能会决定使用一个 CSS 框架,比如 TailwindCSS、Bootstrap、MaterializeCSS、Foundation 等等……但是你只会使用一小部分框架,并且会包含很多未使用的 CSS 样式.这就是 PurgeCSS 发挥作用的地方。PurgeCSS 分析您的内容和 CSS 文件。然后它将文件中使用的选择器与内容文件中的选择器相匹配。它从您的 CSS 中删除未使用的选择器,从而生成更小的 CSS 文件。2 Offline Plugin ⭐ 4,427地址该插件旨在为webpack项目提供离线体验。它使用ServiceWorker和AppCache作为引擎盖下的后备。只需将此插件包含在您webpack.config的 .cpp 文件中,并在您的客户端脚本中包含随附的运行时,您的项目将通过缓存所有(或部分)webpack 输出资产来准备离线。3. Mini Css Extract Plugin ⭐ 4,331地址这个插件将 CSS 提取到单独的文件中。它为每个包含 CSS 的 JS 文件创建一个 CSS 文件。它支持按需加载 CSS 和 SourceMaps4 Extract Text Webpack Plugin ⭐ 4,076地址从一个或多个包中提取文本到一个单独的文件中。5 Critters ⭐ 2,754地址 一个 Webpack 插件,用于内联关键 CSS 并延迟加载其余 CSS。6 Copy Webpack Plugin ⭐ 2,654地址将已存在的单个文件或整个目录复制到构建目录。7 Hard Source Webpack Plugin ⭐ 2,589地址HardSourceWebpackPlugin是 webpack 的插件,为模块提供中间缓存步骤。8 React Refresh Webpack Plugin ⭐ 2,287地址用于为 React 组件启用“快速刷新”(也称为热重载)9 Preload Webpack Plugin ⭐ 2,174地址用于使用<link rel='preload'>. 这有助于延迟加载。10 Page Skeleton Webpack Plugin ⭐ 2,153地址Page Skeleton 是一款 webpack 插件,该插件的目的是根据你项目中不同的路由页面生成相应的骨架屏页面,并将骨架屏页面通过 webpack 打包到对应的静态路由页面中。
创作不易 拒绝白嫖 点个赞呗 关注专栏 学透CSS,带你走进CSS的深处!!!前言网页的设置在很多时候并不是正好满足一页,拿我们经常用的掘金来说,因为使用了数据的分页加载,如果你想看更多的文章的话,需要不停的往下滑动,在浏览器的右边会一直存在着一个滚动条,这就是这篇文章想要了解的元素。在网页中当一页无法容纳所有的数据的时候,我们经常使用overflow来进行设定。overflowoverflow 是overflow-x 和overflow-y的简写,用来设定当一块级元素(通常设置了height/max-height)的内容太大而超出范围的时候,元素内容如何加载。当元素的white-space设置为nowrap也满足。语法overflow:属性值; overflow: [overflow-x] [overflow-y];当你设定一个值的话,则同时对x和y轴生效你也可以分别设定x和y轴的值。属性值下面的所有例子都依赖于:div{ height:100px; width: 100px; border: 1px solid #000; }overflow: visible; 默认值。内容不会被修剪,会呈现在元素框之外overflow: hidden; 内容会被修剪,并且其余内容不可见overflow: scroll; 内容会被修剪,浏览器会显示滚动条以便查看其余内容,无论内容是否超出,均会显示滚动条overflow: auto; 浏览器自己决定是否显示滚动条,如果内容没有超出则不会显示滚动条。overflow: inherit; 规定从父元素继承overflow属性的值visible+auto 或者auto+visible的有趣现象当其中一方被设置了auto的话,visible的表现也会是auto举例1:overflow: auto visible; 如图所示,正常来说y轴设置了visible,y轴不应该出现滚动条,内容应该超出元素啊。 举例1:overflow: visible auto ; 这里我们设置了文字不换行。overflow: visible auto; white-space: nowrap; }因为设置了文字不换行,所以x轴的内容应该是超出的,但是却出现了滚动条。 配合text-overflow 文字省略我们还以掘金为例,这是云大佬的一篇文章,大家仔细看一下他的标题,标题的长度已经超出了盒子的宽度,掘金的处理,是使用省略号来表示标题的剩余内容。 那么这种效果是如何是实现的呢?其实很简单,我们上面其实已经大概出现这种效果了。超出文字隐藏:overflow:hidden;文字不换行:text-wrap:nowrap;最后一种省略号,就是使用text-overflow,实现如下:div{ height:100px; width: 300px; border: 1px solid #000; overflow: hidden; white-space: nowrap; text-overflow:ellipsis; } <div> 【利器篇】35+精选chrome插件,含15+前端插件,总有一款值得你停留。 </div>overflow:hidden;清除浮动当父元素没设置高度的时候,子元素float的时候,父元素高度会塌陷,子元素溢出。.parent { border: 5px solid red; width: 300px; } .child { border: 5px solid blue; width:100px; height: 100px; float: left; } <div class="parent"> <div class="child"></div> <div class="child"></div> </div>当你在父元素parent加上,overflow: hidden;就会出现下面的效果。 父元素高度正常。 原理;overflow:hidden;会自动产生一个BFC,浏览器在计算BFC的高度时:BFC浮动元素的高度也要参与计算,即父元素不会忽略自己里面的浮动元素的高度,如果你的父元素的高度设置的auto的话,那么它的高度就会等于浮动元素的高度。overflow:hidden;解决外边距折叠问题折叠的条件:两个元素的 margin 必须是 相邻 的处于非float或者绝对定位的盒子。垂直方向上相邻具体就是下面这种效果:.block1 { width: 50px; height: 50px; background-color: silver; margin: 10px; } .block2 { width: 50px; height: 50px; background-color: silver; margin: 10px; } <div clss="container"> <div class="block1"></div> <div class="block2"></div> </div> 仔细看最后只剩下了一个外边距。 解决办法:<div style=" overflow: hidden;"> <div class="block2"></div> </div>在下面的加上一个父元素div,形成一个BFC。
创作不易,求一个免费的赞,谢谢啦 !!!前言为啥会突然想起写一篇关于console的文章?笔者接触JS也不少时间了,除了用vscode的debuger,其实大部分时间都在使用console.log()方法来输出一些或者调试程序,我相信很多刚开始接触JS的同志,应该也都习惯使用console.log()。但是log的能力是有限的,并不能满足所有的场景。比如我们相用表格数据对象。下面这张图,纯粹是看了扫黑风暴想到的!!!console.log()大家最常用的应该就是这个属性了,不过你有没有使用这个方法输出console对象。console.log(console)语法console.log(常见JS数据)console.log(123) >> 123console.log( %s %d %f %o 等占位符写法(类似C的print))console.log('我是 %s','前端picker') >> 我是 前端pickerconsole.log(ES6 模板字符串)const nickName = "前端picker" console.log(`我是 ${nickName}``) >> 我是 前端picker数组/对象会显示在一行console.log({object: 'object'}, {object: 'object'}); console.log(['array', 'array'], ['array', 'array']);CSS样式美化输出在上面我们介绍了占位符输出,其实还有占位符%c,可以用来接收css样式。console.log('我是红色 %c 文字', 'color: red;');每个%c只负责它之后的文字,知道遇到下一个%c;console.log('This is %cred text %c 我没颜色 %c 我是绿色.', 'color: red;', '', 'color: green;');当然你也可以选择把样式定义成变量。let style="background: white;border: 3px solid red;color: red;font-size: 50px;margin: 40px;padding: 20px;" undefined console.log('%c我是log!', style);console.clear()大部分的浏览器在开发者工具都内置了清除控制条的方法。其实console对象也提供了clear方法来清空控制台。当你执行console.clear()之后cosole.debug()输出“调试”级别的消息,并且在浏览器中只有你配置了debug才可以显示。 例如在火狐浏览器中:当你没有勾选调试的时候:是无法显示debug的信息的。 只有你勾选调试的时候,才会显示。 error()向 Web 控制台输出一条错误消息,并且只有才浏览器配置了errors才可以显示。下图是在火狐浏览器的效果 下图是在chrome的效果两个浏览器都会在error的前面加上一个小图标。info()向web控制台输出一个通知信息,并且只有在浏览器配置info可见的时可以显示。 下图是在火狐浏览器的效果 下图是在chrome的效果 在火狐浏览器中会在前面加上小图标,而chrome没有warn()向 Web 控制台输出一条警告信息,并且只有在浏览器配置warning可见的时可以显示。下图是在火狐浏览器的效果 下图是在chrome的效果 两个浏览器都会在warn的前面加上一个小图标。console.count()输出 count() 被调用的次数。此函数接受一个可选参数 label,如果你不设置参数的话,这个参数默认名叫**“default”**。 用来统计console.count('我是'); console.count('前端picker'); console.count('我是'); console.count('前端picker'); console.count('我是'); console.count('前端picker');通过下图可以看到,针对不同的参数,count()是分别累计的。 console.countReset()用来重启计数器的.同样也接收一个label参数, 如果提供了参数label,此函数会重置与label关联的计数。如果省略了参数label,此函数会重置默认的default计数器。console.dir()在控制台中显示指定JavaScript对象的属性,并通过类似文件树样式的交互列表显示。 也就是语法是:console.dir(object)const auther = { name: '前端picker', age: '18', }; console.log(auther); console.dir(auther);在chrome浏览器中,是支持这个属性的,下图可以看出与log的不同但是在火狐浏览器中,log和dir的输出一致,不同的是火狐会默认展开dir的结果。 当然log和dir在输出dom结构的时候是完全不同的。不过这个我们放在dirxml方法中学习。console.dirxml()显示一个明确的XML/HTML元素的包括所有后代元素的交互树。 如果无法作为一个element被显示,那么会以JavaScript对象的形式作为替代。 它的输出是一个继承的扩展的节点列表,可以让你看到子节点的内容。同时也支持object。在dir中我们把DOM留到了这里。 创建一个DOM对象var childNode = document.createElement('p'); childNode.innerHTML = '<span>这里是提示信息〜〜</span>';使用log/dir/dirxml输出log dir dirxml 可以看出log和dirxml的输出效果是一致的,是以DOM的形式输出的,dir则输出的是属性的值。group()、groupCollapsed() 和 groupEnd()将不同的控制台输出组合在一起以显示它们之间的一种关系形式。通常是组合在一起使用的。group接收一个参数,表示组名,如果不设置的话,在不同的浏览器表现不一致,浏览器默认展开组。groupCollapsed()与group的不同在于groupCollapsed会自动折叠组。groupEnd()表示组的结束。group+groupEndconsole.group(); console.log('name:'); console.log('前端picker'); console.groupEnd(); console.group('参数'); console.log('age'); console.log('18'); console.groupEnd(); • 1 • 2 • 3 • 4 • 5 • 6 • 7 • 8 • 9下面是chrome的效果。不设置组名的话,默认是console.group,同时一组的输出会缩进。 下面是火狐的效果不设置组名的话,默认是<无组标签> groupCollapsed+grounEndconsole.groupCollapsed(); console.log('name:'); console.log('前端picker'); console.groupEnd(); console.group('参数'); console.log('age'); console.log('18'); console.groupEnd('参数');嵌套console.group('下面是作者信息'); console.log('第1项'); console.group('name'); console.log('前端picker'); console.groupEnd(); console.log('第2项'); console.group('age'); console.log('18'); console.groupEnd(); console.groupEnd();CSS样式美化-%cconsole.group('%c下面是作者信息','color:red;'); console.log('第1项'); console.group('name'); console.log('前端picker'); console.groupEnd(); console.log('第2项'); console.group('age'); console.log('18'); console.groupEnd(); console.groupEnd();console.table()这个方法需要一个必须参数,参数 必须是一个数组或者是一个对象;还可以使用一个可选参数 columns。它会参数以表格的形式打印出来。数组中的每一个元素(或对象中可枚举的属性)将会以行的形式显示在表格中。表格的第一列是 index。如果数据 data 是一个数组,那么这一列的单元格的值就是数组的索引。 如果数据是一个对象。数组let ary = [ '1', '2', '3' ]; console.table(ary);object对象let obj = { name: '前端picker', age: '18', }; console.table(obj);对象数组let aryOfObjects = [ { name: '张三', age: '12', }, { name: '李四', age: '18', }, { name: '王五', age: '19', } ]; console.table(aryOfObjects);如图所示,table()为我们提供了一个很好的对象布局,其中重复键作为列标签。,每个对象中的所有键都将表示为一列,无论其他对象中是否有对应的键与数据。如果对象没有键列的数据,则它显示为空。 数组数组let aryOfArray = [ [1,2,3],[3,4,5],[6,7,8] ]; console.table(aryOfArray);数组数组类似于对象数组。它使用内部数组的索引作为列标签,而不是作为列标签的键。因此,如果一个数组的项目数比其他数组多,那么这些列的表中将有空白项目。就像对象数组一样。对象数组数组let aryOfArraysWithObject = [ ['1', '2', { name: '张三', age: '12', },], ['3', '4', { name: '李四', age: '18', },}], ['5', '6', { name: '王五', age: '19', }] ]; console.table(aryOfArraysWithObject);在Chrome中,要查看第三列中这些对象中包含的内容,是无法展开的,也就是无法查看。。 不过在火狐浏览器中,会自动展开,可以清除的看到结果time()、timeLog() 和 timeEnd()time()你可以启动一个计时器来跟踪某一个操作的占用时长。每一个计时器必须拥有唯一的名字,页面中最多能同时运行10,000个计时器。当以此计时器名字为参数调用 console.timeEnd() 时,浏览器将以毫秒为单位,输出对应计时器所经过的时间。console.time(计时器名称)timeEnd()停止一个通过 console.time() 启动的计时器,并并输出结束的时间console.timeEnd(计时器名称)timeLog()在控制台输出计时器的值,该计时器必须已经通过 console.time() 启动。console.timeLog()(计时器名称)使用console.time('this is a timer'); console.timeLog('this is a timer'); console.timeEnd('this is a timer');计算for的时间console.time('this is a timer'); for(let i=0; i<10000000;i++){ } console.timeLog('this is a timer'); console.timeEnd('this is a timer');console.assert()console.assert()命令类似于前面提到的错误命令。不同之处在于断言允许使用布尔条件来确定是否应该将文本输出到控制台。例如:你想测试一个变量的值,并且这个值不等于’前端picker’, 如果变量低于该数字并且条件解析为 true,则 assert 命令不执行任何操作。如果条件解析为 false,则显示输出文本。通过这种方式,你就不需要通过if判断是不是需要输出之后,再使用console.error()输出。let name = '张三'; console.assert(name === '前端picker', '不是是前端picker,无法输出'); let name1 = '前端picker'; console.assert(name1 === '前端picker', '不是前端picker------1,可以输出');在Chrome中, 还可以输出显示断言来自何处。let value = 2; function chackValue() { chackValue3(); } function chackValue2() { chackValue3(); } function chackValue3() { console.assert(value < 1, 'This was false.'); } chackValue();为了方便看,我们使用vscode标注了行数。 通过下图可以看出,Chrome告诉我们断言在9行。 console.trace调用堆栈在学习trace之前我们先来学习什么是调用堆栈!!! 有这样四个函数 function1调用function2 ,function2调用function3,function3调用function4 看这张图,这几个函数呈现出堆栈的特征。最后被调用的函数出现在最上方。因此称呼这种关系为调用堆栈(call stack)。 trace可以干啥用来记录 JavaScript 堆栈跟踪,同时我们还还可以添加参数,用来表示当前跟踪的名册灰姑娘。function f1(){ console.log('f1') f2() } function f2(){ console.log('f2') f3() } function f3(){ console.log('f3') f4() } function f4(){ console.log('f4') console.trace("f4的追踪记录"); }从图中我们可以看到:触发 console.trace 之前调用的最后一个函数是f4。所以这将是调用堆栈的顶部。然后一次是f3,f2 ,f1
Electron如何加载vue页面的呢第一步 createWindow(),创建窗口在src/main/index.js中的createWindow()函数中,Electron-vue已经为我们写好了创建窗口的实例。在这里调用到了BrowserWindow,具体的参数设置以及使用参考官方文档。这里我们先引入BrowserWindow:import { BrowserWindow } from 'electron'然后看一下我们需要的参数,目前我们只需要设置窗口的宽高// 定义一个mainWindow作为主窗口 mainWindow = new BrowserWindow({ height: 310,//窗口的高度 width: 330,//窗口的宽度 })到这里,目前我们就可以创建一个页面了,那么Electron要如何来显示我们vue写好的页面,其实Electron-vue已经为我们做好了。第二步 引入页面// 定义了一个winUrl,存储要加载的页面 const winURL = process.env.NODE_ENV === 'development' ? `http://localhost:9080` : `file://${__dirname}/index.html`在Electron-vue中index.html对应的是index.ejs !!!第三步 加载页面// 用主窗口去加载页面 mainWindow.loadURL(winURL)到此为止,我们已经了解了Electron是如何加载页面的下面的内容,需要了解vue!!!下面我们开始制作登录页面,第一步 创建文件以及文件夹在renderer中创建一个名为layout的文件夹,并在此文件夹中创建login.vue文件.第二步 使用element-ui实现如下页面 可以看到这是一个form表单,需要引入el-form ,然后里面有用户名输入框,密码输入框,自启动radio,已经两个button。<el-form :model="ruleForm" :rules="rules" ref="ruleForm"label-width="80px"label-position="left"> <el-form-item label="用户名" prop="userName"> <el-input v-model="ruleForm.userName" placeholder="请输入用户名" style="width: 180px;"></el-input> </el-form-item> <el-form-item label="密码" prop="password"> <el-input type="password" v-model="ruleForm.password" placeholder="请输入密码"style="width: 180px;"></el-input> </el-form-item> <el-form-item label="开机启动" prop="autoStart"> <el-switch v-model="ruleForm.autoStart"></el-switch> </el-form-item> <el-form-item> <el-button type="primary" @click="submitForm('ruleForm')">提交</el-button> <el-button @click="resetForm('ruleForm')">重置</el-button> </el-form-item> </el-form>确定form中的数据有:userName,password,autoStart,直接使用vue进行的v-model进行绑定。分析:我们需要定义的字段 data() { return { user: [], autoStartLocal:false, // 记录本地存储的自启动,如果本地已经将自启动写入注册表,这个数据和表单里的autoStart进行比较,防止多次写入。 ruleForm: { password: "", // 表单密码 userName: "",//表单 autoStart: false }, rules: { password: [{ required: true, message: "请输入密码", trigger: "blur" }], userName: [{ required: true, message: "请输入用户名", trigger: "blur" }] } }; },什么时候读取本地存储的用户名,密码以及自启动 用户输入完用户名和密码,需要和本地所存储的用户名密码进行比较,所以我们需要将数据取出来,但是你会发现,自启动,我们有可能之前设置过了,所以自启动要在页面加载之后就开始读取,使用monted在DOM加载完成之后就进行读取。 submitForm(formName) { console.log("提交"); this.$refs[formName].validate(valid => { if (valid) { if ( this.ruleForm.userName !== this.user.userName || this.user.password !== this.ruleForm.password ) { this.$message({ message: "用户名或者密码错误", type: "error", center: true, duration: 1000 }); } else { let result = this.$db .get("user") .find({ userName: this.ruleForm.userName }) .assign({ autoStart: this.ruleForm.autoStart }) .write(); if (result) { this.$store.commit("changeLoginState", true); console.log(this.$store.state.login.loginState); this.$router.replace("/"); console.log(this.$router); } } } else { return false; } }); }, resetForm(formName) { this.$refs[formName].resetFields(); } } }; </script>
创作不易 拒绝白嫖 点个赞呗关注专栏 学透CSS,带你走进CSS的深处!!!兼容性box-shadow 基本兼容市面上的大部分浏览器,所以不需要考虑兼容性。是什么box-shadow可以在元素上添加阴影,一个元素可以添加多个阴影。语法box-shadow:offset-x offset-y blur spread color position(可选)offset-x指定阴影的水平偏移量。即在x轴上阴影的位置。正值使阴影出现在元素的右边,而负值使阴影出现在元素的左边。offset-y指定阴影的垂直偏移量。即在y轴上阴影的位置。正值使阴影出现在元素的下边,而负值使阴影出现在元素的上边。blur指定阴影的模糊程度,值越大越模糊。 spred指定阴影的延伸尺寸,值越大,增加的越多。 color指定了阴影的颜色 position指定阴影的位置,可以使用inset变成内部阴影 多重阴影box-shadow 属性能在单个元素上接受多个阴影。每个阴影通过用逗号分隔的 box-shadow 属性列表来加载。box-shadow: 20px 20px 20px 10px blue, -20px -20px 20px 10px black;简单示例单边阴影首先正常效果的话是这样子的 box-shadow: 0 8px 10px 0px black ;会发现如果使用blur效果的话会出现三个方向的阴影 这种情况下我们其实是只想要下面的那一个阴影的,思路:第三参数和第四参数相互抵消,可以让其他边框效果隐藏。圆形阴影box-shadow: 20px 20px 20px 10px blue, border-radius: 50%;层叠效果利用单个元素接收多个阴影效果box-shadow: rgba(240, 46, 170, 0.4) 5px 5px, rgba(240, 46, 170, 0.3) 10px 10px, rgba(240, 46, 170, 0.2) 15px 15px, rgba(240, 46, 170, 0.1) 20px 20px, rgba(240, 46, 170, 0.05) 25px 25px;
创作不易 拒绝白嫖 点个赞呗文章目录前言1. 基本使用1.1 拆分配置和merge初始化package.json1.1.1 安装webpack1.1.2 安装webpack-merge1.1.3 新建build文件夹以及配置文件webpack.common.jswebpack.dev.jswebpack.prod.js1.1.4 Scripts1.1.5 测试1.2 启动本地服务1.2.1 安装webpack-dev-server1.2.2 配置devServer1.2.3 启动1.2.4 测试安装HtmlWebpackPlugin,自动生成html配置HtmlWebpackPlugin1.3 处理es6(配置babel)13.1. 安装babel-loader@babel/core@babel/preset-env1.3.2. 配置.babelrcbuild\webpack.common.js1.4 处理css1.4.1 安装style-loadercss-loaderpostcss-loader + autoprefixer1.4.2 配置1.5 处理图片1.5.1 一般文件中引入图片有三种方式:1.5.2 安装file-loaderurl-loader1.5.3 配置2 高级特性2.1 配置多入口2.1.1 配置entry2.1.2. 配置对应的出口2.1.3 配置对应的模板2.2 抽离css(打包)2.2.1 安装mini-css-extract-plugin2.2.2 配置loaderplugins2.3 压缩css(打包)2.3.1 安装optimize-css-assets-webpack-plugin2.3.2 配置2.4 抽离公共代码2.4.1 公共模块抽离2.4.2 第三方模块抽离3 性能优化3.1 优化babal-loader(缩小构建目标)3.1.1 原因3.1.2 配置3.2 happyPack 多进程打包3.2.1 安装3.2.2 配置3.3 ParallelUglifyPlugin优化压缩3.3.1 安装3.3.2 配置3.4 自动刷新3.4.1 项目中自动刷新的配置:3.4.2 原理3.5 模块热更新3.6 性能分析3.6.1 webpack-bundle-analyzer3.6.2 speed-measure-webpack-plugin后记前言本质上,webpack 是一个用于现代 JavaScript 应用程序的 静态模块打包工具。当 webpack 处理应用程序时,它会在内部从一个或多个入口点构建一个 依赖图(dependency graph),然后将你项目中所需的每一个模块组合成一个或多个 bundles,它们均为静态资源,用于展示你的内容。 主要概念入口(entry)输出(output)loader插件(plugin)模式(mode)1. 基本使用1.1 拆分配置和merge初始化package.jsonnpm init -y1.1.1 安装webpackyarn add -D webpack webpack-cli1.1.2 安装webpack-mergeyarn add -D webpack-merge1.1.3 新建build文件夹以及配置文件build\webpack.common.jsbuild\webpack.dev.jsbuild\webpack.prod.jswebpack.common.js公共配置const path = require('path') module.exports ={ entry:path.join(__dirname, '..', 'src/index') }webpack.dev.js开发时const webpackCommon = require('./webpack.common.js') const { merge } = require('webpack-merge') module.exports = merge(webpackCommon, { mode: 'development' })webpack.prod.js打包时const path = require('path') const webpack = require('webpack') const webpackCommon = require('./webpack.common.js') const { merge } = require('webpack-merge') const { CleanWebpackPlugin } = require('clean-webpack-plugin') module.exports = merge(webpackCommon, { mode: 'production', output: { filename: '[name].[contenthash:8].js', path: path.join(__dirname, '..', 'dist'), }, plugins: [new CleanWebpackPlugin()] })1.1.4 Scripts "scripts": { // 本地服务 "dev": "webpack-dev-server --config build/webpack.dev.js", "build": "webpack --config build/webpack.prod.js" },1.1.5 测试新建src/index 执行 yarn build1.2 启动本地服务1.2.1 安装webpack-dev-serveryarn add -D webpack-dev-server1.2.2 配置devServerwebpack.dev.js devServer: { port: 8080, progress: true, // 显示打包的进度条 contentBase:path.join(__dirname, '..', 'dist'), // 根目录 open: true, // 自动打开浏览器 compress: true, // 启动 gzip 压缩 // 设置代理 proxy: { } }1.2.3 启动yarn dev1.2.4 测试安装HtmlWebpackPlugin,自动生成htmlyarn add -D html-webpack-plugin配置HtmlWebpackPluginwebpack.common.js plugins:[ new HtmlWebpackPlugin({ template: path.join(__dirname, '..', 'src/index.html'), filename: 'index.html' }) ]开发环境,会在内存中生成一个html文件 打包环境,会在dist下生成一个html文件 html文件会自动引入main.js1.3 处理es6(配置babel)13.1. 安装babel-loaderyarn add -D babel-loader@babel/coreyarn add -D @babel/core@babel/preset-envyarn add -D @babel/preset-env1.3.2. 配置.babelrc{ "presets": ["@babel/preset-env"], "plugins": [] }build\webpack.common.js module: { rules: [ { test: /\.js$/, // loader: 'babel-loader', //loader 是单个加载器,use是加载器数组 use: [ 'babel-loader', ], include: path.join(__dirname, '..', 'src'), exclude: /node_modules/ } ] },1.4 处理css1.4.1 安装style-loadercss插入到页面的style标签yarn add -D style-loadercss-loaderyarn add -D css-loaderpostcss-loader + autoprefixer自动添加前缀yarn add -D postcss-loader autoprefixer1.4.2 配置build\webpack.common.js{ test: /\.css$/, // loader 的执行顺序是:从后往前 use: ['style-loader', 'css-loader', 'postcss-loader'] },postcss.config.jsmodule.exports = { plugins: [require('autoprefixer')] }1.5 处理图片1.5.1 一般文件中引入图片有三种方式:js文件中通过 import imgSrc from ‘./photo’; img.src = imgSrc引入 在css文件中作为背景图引入 在html文件中直接引入1.5.2 安装file-loaderyarn add -D file-loaderurl-loaderyarn add -D url-loader1.5.3 配置build-base-conf\webpack.dev.js // 直接引入图片 url { test: /\.(png|jpg|jpeg|gif)$/, use: 'file-loader' }build-base-conf\webpack.prod.js // 图片 - 考虑 base64 编码的情况 { test: /\.(png|jpg|jpeg|gif)$/, use: { loader: 'url-loader', options: { // 小于 5kb 的图片用 base64 格式产出 // 否则,依然延用 file-loader 的形式,产出 url 格式 limit: 5 * 1024, // 打包到 img 目录下 outputPath: '/img1/', // 设置图片的 cdn 地址(也可以统一在外面的 output 中设置,那将作用于所有静态资源) // publicPath: 'http://cdn.abc.com' } } },2 高级特性2.1 配置多入口2.1.1 配置entryentry: { index: path.join(srcPath, 'index.js'), other: path.join(srcPath, 'other.js') },这里的index与other就是chunk名称2.1.2. 配置对应的出口build-base-conf\webpack.prod.js output: { filename: 'bundle.[contentHash:8].js', // 打包代码时,加上 hash 戳 path: distPath, // publicPath: 'http://cdn.abc.com' // 修改所有静态文件 url 的前缀(如 cdn 域名),这里暂时用不到 },注意这里只需要在prod里面加入配置, dev不需要2.1.3 配置对应的模板new HtmlWebpackPlugin({ template: path.join(__dirname, '..', 'src/index.html'), filename: 'index.html', // chunks 表示该页面要引用哪些 chunk (即上面的 index 和 other),默认全部引用 chunks: ['index'] // 只引用 index.js }), // 多入口 - 生成 other.html new HtmlWebpackPlugin({ template: path.join(__dirname, '..', 'src/other.html'), filename: 'other.html', chunks: ['other'] // 只引用 other.js })2.2 抽离css(打包)2.2.1 安装mini-css-extract-pluginyarn add -D mini-css-extract-plugin2.2.2 配置build\webpack.prod.jsloader// 抽离 css { test: /\.css$/, use: [ MiniCssExtractPlugin.loader, // 注意,这里不再用 style-loader 'css-loader', 'postcss-loader' ] },plugins new MiniCssExtractPlugin({ filename: 'css/main.[contenthash:8].css' })2.3 压缩css(打包)2.3.1 安装optimize-css-assets-webpack-pluginyarn add optimize-css-assets-webpack-plugin2.3.2 配置build-min-extract-css\webpack.prod.js optimization: { // 压缩 css minimizer: [ new OptimizeCSSAssetsPlugin({})], }2.4 抽离公共代码抽离公共代码 我们在开发多个页面的项目的时候,有时候会在几个页面中引用某些公共的模块,这些公共模块多次被下载会造成资源浪费,如果把这些公共模块抽离出来只需下载一次之后便缓存起来了,这样就可以避免因重复下载而浪费资源,那么怎么在webpack中抽离出公共部分呢?方法如下:2.4.1 公共模块抽离举例:项目中分别有a.js, b.js, page1.js, page2.js这四个JS文件, page1.js 和 page2.js中同时都引用了a.js, b.js, 这时候想把a.js, b.js抽离出来合并成一个公共的js,然后在page1, page2中自动引入这个公共的js, splitChunks: { cacheGroups: { //公用模块抽离 common: { chunks: 'initial', minSize: 0, //大于0个字节 minChunks: 2 //抽离公共代码时,这个代码块最小被引用的次数 } } }2.4.2 第三方模块抽离页面中有时会引入第三方模块,比如import $ from ‘jquery’; page1中需要引用,page2中也需要引用,这时候就可以用vendor把jquery抽离出来,方法如下: optimization: { // 分割代码块 splitChunks: { chunks: 'all', /** * initial 入口 chunk,对于异步导入的文件不处理 async 异步 chunk,只对异步导入的文件处理 all 全部 chunk */ // 缓存分组 cacheGroups: { // 第三方模块 vendor: { name: 'vendor', // chunk 名称 priority: 1, // 权限更高,优先抽离,重要!!! test: /node_modules/, minSize: 0, // 大小限制 minChunks: 1 // 最少复用过几次 }, // 公共的模块 common: { name: 'common', // chunk 名称 priority: 0, // 优先级 minSize: 0, // 公共模块的大小限制 minChunks: 2 // 公共模块最少复用过几次 } } } }注意:这里需要配置权重 priority,因为抽离的时候会执行第一个common配置,入口处看到jquery也被公用了就一起抽离了,不会再执行wendor的配置了,所以加了权重之后会先抽离第三方模块,然后再抽离公共common的,这样就实现了第三方和公用的都被抽离了。3 性能优化3.1 优化babal-loader(缩小构建目标)3.1.1 原因Loader处理文件的转换操作是很耗时的,所以需要让尽可能少的文件被Loader处理3.1.2 配置{ test: /\.js$/, use: [ 'babel-loader?cacheDirectory',//开启转换结果缓存 ], include: path.resolve(__dirname, 'src'),//只对src目录中文件采用babel-loader exclude: path.resolve(__dirname,' ./node_modules'),//排除node_modules目录下的文件 },3.2 happyPack 多进程打包3.2.1 安装yarn add -D happypack3.2.2 配置Pluginsnew HappyPack({ // 用唯一ID来代表当前HappyPack是用来处理一类特定文件的,与rules中的use对应 id: "babel", loaders: ["babel-loader?cacheDirectory"], //默认设置loader处理 threads: 5, //使用共享池处理 }), new HappyPack({ id: 'styles', loaders: ['css-loader', 'postcss-loader'], threads: 5, //代表开启几个子进程去处理这一类型的文件 verbose: true //是否允许输出日子 }),rules { test: /\.(js|jsx)$/, use: [MiniCssExtractPlugin.loader, "HappyPack/loader?id=babel"], exclude: path.resolve(__dirname, " ./node_modules"), }, { test: /\.css$/, use: 'happypack/loader?id=styles', include: path.join(__dirname, '..', 'src') },3.3 ParallelUglifyPlugin优化压缩webpack默认提供了UglifyJS插件来压缩JS代码,但是它使用的是单线程压缩代码,也就是说多个js文件需要被压缩,它需要一个个文件进行压缩。 所以说在正式环境打包压缩代码速度非常慢(因为压缩JS代码需要先把代码解析成用Object抽象表示的AST语法树,再去应用各种规则分析和处理AST,导致这个过程耗时非常大)。3.3.1 安装yarn add -D webpack-parallel-uglify-plugin3.3.2 配置 new ParallelUglifyPlugin({ // 传递给 UglifyJS的参数如下: uglifyJS: { output: { /* 是否输出可读性较强的代码,即会保留空格和制表符,默认为输出,为了达到更好的压缩效果, 可以设置为false */ beautify: false, /* 是否保留代码中的注释,默认为保留,为了达到更好的压缩效果,可以设置为false */ comments: false }, compress: { /* 是否删除代码中所有的console语句,默认为不删除,开启后,会删除所有的console语句 */ drop_console: true, /* 是否内嵌虽然已经定义了,但是只用到一次的变量,比如将 var x = 1; y = x, 转换成 y = 5, 默认为不 转换,为了达到更好的压缩效果,可以设置为false */ collapse_vars: true, /* 是否提取出现了多次但是没有定义成变量去引用的静态值,比如将 x = 'xxx'; y = 'xxx' 转换成 var a = 'xxxx'; x = a; y = a; 默认为不转换,为了达到更好的压缩效果,可以设置为false */ reduce_vars: true } } } )3.4 自动刷新 借助自动化的手段,在监听到本地源码文件发生变化时,自动重新构建出可运行的代码后再控制浏览器刷新。Webpack将这些功能都内置了,并且提供了多种方案供我们选择。3.4.1 项目中自动刷新的配置:module.export = { watch: true, watchOptions: { // 不监听的文件或文件夹 ignored: /node_modules/, // 监听到变化发生后会等300ms再去执行动作,防止文件更新太快导致重新编译频率太高 aggregateTimeout: 300, // 判断文件是否发生变化是通过不停的去询问系统指定文件有没有变化实现的 poll: 1000 } }3.4.2 原理在 Webpack 中监听一个文件发生变化的原理是定时(可在watchOptions.poll中设置)的去获取这个文件的最后编辑时间,每次都存下最新的最后编辑时间,如果发现当前获取的和最后一次保存的最后编辑时间不一致,就认为该文件发生了变化当发现某个文件发生了变化时,并不会立刻告诉监听者,而是先缓存起来,收集一段时间(可在watchOptions.aggregateTimeout中设置)的变化后,再一次性告诉监听者。防止在编辑代码的过程中可能会高频的输入文字导致文件变化的事件高频的发生3.5 模块热更新_ _DevServer 还支持一种叫做模块热替换( Hot Module Replacement )的技术可在不刷新整个网页的情况下做到超灵敏实时预览。原理是在一个源码发生变化时,只需重新编译发生变化的模块,再用新输出的模块替换掉浏览器中对应的老模块 。模块热替换技术在很大程度上提升了开发效率和体验 。 项目中模块热替换的配置: const HotModuleReplacementPlugin = require('webpack/lib/HotModuleReplacementPlugin'); devServer:{ host:'localhost', port:'8080', open:true//自动拉起浏览器 // 只设置hot只有cssHMR生效 hot:true,//热加载 //hotOnly:true }, plugins:[ //热更新插件 new webpack.HotModuleReplacementPlugin() ] HotModuleReplacementPlugin生成一个mainifest(一个json结构描述了发生变化的modules列表) 和update file(一个js文件包含修改后的代码内容)JS文件中if (module.hot) { module.hot.accept('./print.js', function() { //告诉 webpack 接受热替换的模块 console.log('Accepting the updated printMe module!'); printMe(); }) } // 对Js生效 3.6 性能分析3.6.1 webpack-bundle-analyzer]// config/webpack.common.js const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer'); const commonConfig = { // ... plugins: [ new BundleAnalyzerPlugin({ analyzerPort: 8889, // 指定端口号 openAnalyzer: false, }), ] // ... }3.6.2 speed-measure-webpack-plugin// config/webpack.common.js const SpeedMeasurePlugin = require("speed-measure-webpack-plugin"); const smp = new SpeedMeasurePlugin(); // ... module.exports = (production) => { if (production) { const endProdConfig = merge(commonConfig, prodConfig); return smp.wrap(endProdConfig); } else { const endDevConfig = merge(commonConfig, devConfig); return smp.wrap(endDevConfig); } };后记2020-10-10 webpack 5.0.0 发布了,但这并不意味着它已经完成了,没有 bug,甚至功能完整。 就像 webpack 4 一样,我们通过修复问题以及增加新特性来延续开发。 在接下来的日子里,可能会有很多 bug 修复。新特性可能也会出现。尝试用持久性缓存来提高构建性能。 尝试用更好的算法和默认值来改进长期缓存。 尝试用更好的 Tree Shaking 和代码生成来改善包大小。 尝试改善与网络平台的兼容性。 尝试在不引入任何破坏性变化的情况下,清理那些在实现 v4 功能时处于奇怪状态的内部结构。 试图通过现在引入突破性的变化来为未来的功能做准备,使其能够尽可能长时间地保持在 v5 版本上。 迁移指南
创作不易 拒绝白嫖 点个赞呗文章目录前言1. 基本使用1.1 拆分配置和merge初始化package.json1.1.1 安装webpack1.1.2 安装webpack-merge1.1.3 新建build文件夹以及配置文件webpack.common.jswebpack.dev.jswebpack.prod.js1.1.4 Scripts1.1.5 测试1.2 启动本地服务1.2.1 安装webpack-dev-server1.2.2 配置devServer1.2.3 启动1.2.4 测试安装HtmlWebpackPlugin,自动生成html配置HtmlWebpackPlugin1.3 处理es6(配置babel)13.1. 安装babel-loader@babel/core@babel/preset-env1.3.2. 配置.babelrcbuild\webpack.common.js1.4 处理css1.4.1 安装style-loadercss-loaderpostcss-loader + autoprefixer1.4.2 配置1.5 处理图片1.5.1 一般文件中引入图片有三种方式:1.5.2 安装file-loaderurl-loader1.5.3 配置2 高级特性2.1 配置多入口2.1.1 配置entry2.1.2. 配置对应的出口2.1.3 配置对应的模板2.2 抽离css(打包)2.2.1 安装mini-css-extract-plugin2.2.2 配置loaderplugins2.3 压缩css(打包)2.3.1 安装optimize-css-assets-webpack-plugin2.3.2 配置2.4 抽离公共代码2.4.1 公共模块抽离2.4.2 第三方模块抽离3 性能优化3.1 优化babal-loader(缩小构建目标)3.1.1 原因3.1.2 配置3.2 happyPack 多进程打包3.2.1 安装3.2.2 配置3.3 ParallelUglifyPlugin优化压缩3.3.1 安装3.3.2 配置3.4 自动刷新3.4.1 项目中自动刷新的配置:3.4.2 原理3.5 模块热更新3.6 性能分析3.6.1 webpack-bundle-analyzer3.6.2 speed-measure-webpack-plugin后记前言本质上,webpack 是一个用于现代 JavaScript 应用程序的 静态模块打包工具。当 webpack 处理应用程序时,它会在内部从一个或多个入口点构建一个 依赖图(dependency graph),然后将你项目中所需的每一个模块组合成一个或多个 bundles,它们均为静态资源,用于展示你的内容。 主要概念入口(entry)输出(output)loader插件(plugin)模式(mode)1. 基本使用1.1 拆分配置和merge初始化package.jsonnpm init -y1.1.1 安装webpackyarn add -D webpack webpack-cli1.1.2 安装webpack-mergeyarn add -D webpack-merge1.1.3 新建build文件夹以及配置文件build\webpack.common.jsbuild\webpack.dev.jsbuild\webpack.prod.jswebpack.common.js公共配置const path = require('path') module.exports ={ entry:path.join(__dirname, '..', 'src/index') }webpack.dev.js开发时const webpackCommon = require('./webpack.common.js') const { merge } = require('webpack-merge') module.exports = merge(webpackCommon, { mode: 'development' })webpack.prod.js打包时const path = require('path') const webpack = require('webpack') const webpackCommon = require('./webpack.common.js') const { merge } = require('webpack-merge') const { CleanWebpackPlugin } = require('clean-webpack-plugin') module.exports = merge(webpackCommon, { mode: 'production', output: { filename: '[name].[contenthash:8].js', path: path.join(__dirname, '..', 'dist'), }, plugins: [new CleanWebpackPlugin()] })1.1.4 Scripts "scripts": { // 本地服务 "dev": "webpack-dev-server --config build/webpack.dev.js", "build": "webpack --config build/webpack.prod.js" },1.1.5 测试新建src/index 执行 yarn build1.2 启动本地服务1.2.1 安装webpack-dev-serveryarn add -D webpack-dev-server1.2.2 配置devServerwebpack.dev.js devServer: { port: 8080, progress: true, // 显示打包的进度条 contentBase:path.join(__dirname, '..', 'dist'), // 根目录 open: true, // 自动打开浏览器 compress: true, // 启动 gzip 压缩 // 设置代理 proxy: { } }1.2.3 启动yarn dev1.2.4 测试安装HtmlWebpackPlugin,自动生成htmlyarn add -D html-webpack-plugin配置HtmlWebpackPluginwebpack.common.js plugins:[ new HtmlWebpackPlugin({ template: path.join(__dirname, '..', 'src/index.html'), filename: 'index.html' }) ]开发环境,会在内存中生成一个html文件 打包环境,会在dist下生成一个html文件 html文件会自动引入main.js1.3 处理es6(配置babel)13.1. 安装babel-loaderyarn add -D babel-loader@babel/coreyarn add -D @babel/core@babel/preset-envyarn add -D @babel/preset-env1.3.2. 配置.babelrc{ "presets": ["@babel/preset-env"], "plugins": [] }build\webpack.common.js module: { rules: [ { test: /\.js$/, // loader: 'babel-loader', //loader 是单个加载器,use是加载器数组 use: [ 'babel-loader', ], include: path.join(__dirname, '..', 'src'), exclude: /node_modules/ } ] },1.4 处理css1.4.1 安装style-loadercss插入到页面的style标签yarn add -D style-loadercss-loaderyarn add -D css-loaderpostcss-loader + autoprefixer自动添加前缀yarn add -D postcss-loader autoprefixer1.4.2 配置build\webpack.common.js{ test: /\.css$/, // loader 的执行顺序是:从后往前 use: ['style-loader', 'css-loader', 'postcss-loader'] },postcss.config.jsmodule.exports = { plugins: [require('autoprefixer')] }1.5 处理图片1.5.1 一般文件中引入图片有三种方式:js文件中通过 import imgSrc from ‘./photo’; img.src = imgSrc引入 在css文件中作为背景图引入 在html文件中直接引入1.5.2 安装file-loaderyarn add -D file-loaderurl-loaderyarn add -D url-loader1.5.3 配置build-base-conf\webpack.dev.js // 直接引入图片 url { test: /\.(png|jpg|jpeg|gif)$/, use: 'file-loader' }build-base-conf\webpack.prod.js // 图片 - 考虑 base64 编码的情况 { test: /\.(png|jpg|jpeg|gif)$/, use: { loader: 'url-loader', options: { // 小于 5kb 的图片用 base64 格式产出 // 否则,依然延用 file-loader 的形式,产出 url 格式 limit: 5 * 1024, // 打包到 img 目录下 outputPath: '/img1/', // 设置图片的 cdn 地址(也可以统一在外面的 output 中设置,那将作用于所有静态资源) // publicPath: 'http://cdn.abc.com' } } },2 高级特性2.1 配置多入口2.1.1 配置entryentry: { index: path.join(srcPath, 'index.js'), other: path.join(srcPath, 'other.js') },这里的index与other就是chunk名称2.1.2. 配置对应的出口build-base-conf\webpack.prod.js output: { filename: 'bundle.[contentHash:8].js', // 打包代码时,加上 hash 戳 path: distPath, // publicPath: 'http://cdn.abc.com' // 修改所有静态文件 url 的前缀(如 cdn 域名),这里暂时用不到 },注意这里只需要在prod里面加入配置, dev不需要2.1.3 配置对应的模板new HtmlWebpackPlugin({ template: path.join(__dirname, '..', 'src/index.html'), filename: 'index.html', // chunks 表示该页面要引用哪些 chunk (即上面的 index 和 other),默认全部引用 chunks: ['index'] // 只引用 index.js }), // 多入口 - 生成 other.html new HtmlWebpackPlugin({ template: path.join(__dirname, '..', 'src/other.html'), filename: 'other.html', chunks: ['other'] // 只引用 other.js })2.2 抽离css(打包)2.2.1 安装mini-css-extract-pluginyarn add -D mini-css-extract-plugin2.2.2 配置build\webpack.prod.jsloader// 抽离 css { test: /\.css$/, use: [ MiniCssExtractPlugin.loader, // 注意,这里不再用 style-loader 'css-loader', 'postcss-loader' ] },plugins new MiniCssExtractPlugin({ filename: 'css/main.[contenthash:8].css' })2.3 压缩css(打包)2.3.1 安装optimize-css-assets-webpack-pluginyarn add optimize-css-assets-webpack-plugin2.3.2 配置build-min-extract-css\webpack.prod.js optimization: { // 压缩 css minimizer: [ new OptimizeCSSAssetsPlugin({})], }2.4 抽离公共代码抽离公共代码 我们在开发多个页面的项目的时候,有时候会在几个页面中引用某些公共的模块,这些公共模块多次被下载会造成资源浪费,如果把这些公共模块抽离出来只需下载一次之后便缓存起来了,这样就可以避免因重复下载而浪费资源,那么怎么在webpack中抽离出公共部分呢?方法如下:2.4.1 公共模块抽离举例:项目中分别有a.js, b.js, page1.js, page2.js这四个JS文件, page1.js 和 page2.js中同时都引用了a.js, b.js, 这时候想把a.js, b.js抽离出来合并成一个公共的js,然后在page1, page2中自动引入这个公共的js, splitChunks: { cacheGroups: { //公用模块抽离 common: { chunks: 'initial', minSize: 0, //大于0个字节 minChunks: 2 //抽离公共代码时,这个代码块最小被引用的次数 } } }2.4.2 第三方模块抽离页面中有时会引入第三方模块,比如import $ from ‘jquery’; page1中需要引用,page2中也需要引用,这时候就可以用vendor把jquery抽离出来,方法如下: optimization: { // 分割代码块 splitChunks: { chunks: 'all', /** * initial 入口 chunk,对于异步导入的文件不处理 async 异步 chunk,只对异步导入的文件处理 all 全部 chunk */ // 缓存分组 cacheGroups: { // 第三方模块 vendor: { name: 'vendor', // chunk 名称 priority: 1, // 权限更高,优先抽离,重要!!! test: /node_modules/, minSize: 0, // 大小限制 minChunks: 1 // 最少复用过几次 }, // 公共的模块 common: { name: 'common', // chunk 名称 priority: 0, // 优先级 minSize: 0, // 公共模块的大小限制 minChunks: 2 // 公共模块最少复用过几次 } } } }注意:这里需要配置权重 priority,因为抽离的时候会执行第一个common配置,入口处看到jquery也被公用了就一起抽离了,不会再执行wendor的配置了,所以加了权重之后会先抽离第三方模块,然后再抽离公共common的,这样就实现了第三方和公用的都被抽离了。3 性能优化3.1 优化babal-loader(缩小构建目标)3.1.1 原因Loader处理文件的转换操作是很耗时的,所以需要让尽可能少的文件被Loader处理3.1.2 配置{ test: /\.js$/, use: [ 'babel-loader?cacheDirectory',//开启转换结果缓存 ], include: path.resolve(__dirname, 'src'),//只对src目录中文件采用babel-loader exclude: path.resolve(__dirname,' ./node_modules'),//排除node_modules目录下的文件 },3.2 happyPack 多进程打包3.2.1 安装yarn add -D happypack3.2.2 配置Pluginsnew HappyPack({ // 用唯一ID来代表当前HappyPack是用来处理一类特定文件的,与rules中的use对应 id: "babel", loaders: ["babel-loader?cacheDirectory"], //默认设置loader处理 threads: 5, //使用共享池处理 }), new HappyPack({ id: 'styles', loaders: ['css-loader', 'postcss-loader'], threads: 5, //代表开启几个子进程去处理这一类型的文件 verbose: true //是否允许输出日子 }),rules { test: /\.(js|jsx)$/, use: [MiniCssExtractPlugin.loader, "HappyPack/loader?id=babel"], exclude: path.resolve(__dirname, " ./node_modules"), }, { test: /\.css$/, use: 'happypack/loader?id=styles', include: path.join(__dirname, '..', 'src') },3.3 ParallelUglifyPlugin优化压缩webpack默认提供了UglifyJS插件来压缩JS代码,但是它使用的是单线程压缩代码,也就是说多个js文件需要被压缩,它需要一个个文件进行压缩。 所以说在正式环境打包压缩代码速度非常慢(因为压缩JS代码需要先把代码解析成用Object抽象表示的AST语法树,再去应用各种规则分析和处理AST,导致这个过程耗时非常大)。3.3.1 安装yarn add -D webpack-parallel-uglify-plugin3.3.2 配置 new ParallelUglifyPlugin({ // 传递给 UglifyJS的参数如下: uglifyJS: { output: { /* 是否输出可读性较强的代码,即会保留空格和制表符,默认为输出,为了达到更好的压缩效果, 可以设置为false */ beautify: false, /* 是否保留代码中的注释,默认为保留,为了达到更好的压缩效果,可以设置为false */ comments: false }, compress: { /* 是否删除代码中所有的console语句,默认为不删除,开启后,会删除所有的console语句 */ drop_console: true, /* 是否内嵌虽然已经定义了,但是只用到一次的变量,比如将 var x = 1; y = x, 转换成 y = 5, 默认为不 转换,为了达到更好的压缩效果,可以设置为false */ collapse_vars: true, /* 是否提取出现了多次但是没有定义成变量去引用的静态值,比如将 x = 'xxx'; y = 'xxx' 转换成 var a = 'xxxx'; x = a; y = a; 默认为不转换,为了达到更好的压缩效果,可以设置为false */ reduce_vars: true } } } )3.4 自动刷新 借助自动化的手段,在监听到本地源码文件发生变化时,自动重新构建出可运行的代码后再控制浏览器刷新。Webpack将这些功能都内置了,并且提供了多种方案供我们选择。3.4.1 项目中自动刷新的配置:module.export = { watch: true, watchOptions: { // 不监听的文件或文件夹 ignored: /node_modules/, // 监听到变化发生后会等300ms再去执行动作,防止文件更新太快导致重新编译频率太高 aggregateTimeout: 300, // 判断文件是否发生变化是通过不停的去询问系统指定文件有没有变化实现的 poll: 1000 } }3.4.2 原理在 Webpack 中监听一个文件发生变化的原理是定时(可在watchOptions.poll中设置)的去获取这个文件的最后编辑时间,每次都存下最新的最后编辑时间,如果发现当前获取的和最后一次保存的最后编辑时间不一致,就认为该文件发生了变化当发现某个文件发生了变化时,并不会立刻告诉监听者,而是先缓存起来,收集一段时间(可在watchOptions.aggregateTimeout中设置)的变化后,再一次性告诉监听者。防止在编辑代码的过程中可能会高频的输入文字导致文件变化的事件高频的发生3.5 模块热更新_ _DevServer 还支持一种叫做模块热替换( Hot Module Replacement )的技术可在不刷新整个网页的情况下做到超灵敏实时预览。原理是在一个源码发生变化时,只需重新编译发生变化的模块,再用新输出的模块替换掉浏览器中对应的老模块 。模块热替换技术在很大程度上提升了开发效率和体验 。 项目中模块热替换的配置: const HotModuleReplacementPlugin = require('webpack/lib/HotModuleReplacementPlugin'); devServer:{ host:'localhost', port:'8080', open:true//自动拉起浏览器 // 只设置hot只有cssHMR生效 hot:true,//热加载 //hotOnly:true }, plugins:[ //热更新插件 new webpack.HotModuleReplacementPlugin() ] HotModuleReplacementPlugin生成一个mainifest(一个json结构描述了发生变化的modules列表) 和update file(一个js文件包含修改后的代码内容)JS文件中if (module.hot) { module.hot.accept('./print.js', function() { //告诉 webpack 接受热替换的模块 console.log('Accepting the updated printMe module!'); printMe(); }) } // 对Js生效 3.6 性能分析3.6.1 webpack-bundle-analyzer]// config/webpack.common.js const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer'); const commonConfig = { // ... plugins: [ new BundleAnalyzerPlugin({ analyzerPort: 8889, // 指定端口号 openAnalyzer: false, }), ] // ... }3.6.2 speed-measure-webpack-plugin// config/webpack.common.js const SpeedMeasurePlugin = require("speed-measure-webpack-plugin"); const smp = new SpeedMeasurePlugin(); // ... module.exports = (production) => { if (production) { const endProdConfig = merge(commonConfig, prodConfig); return smp.wrap(endProdConfig); } else { const endDevConfig = merge(commonConfig, devConfig); return smp.wrap(endDevConfig); } };后记2020-10-10 webpack 5.0.0 发布了,但这并不意味着它已经完成了,没有 bug,甚至功能完整。 就像 webpack 4 一样,我们通过修复问题以及增加新特性来延续开发。 在接下来的日子里,可能会有很多 bug 修复。新特性可能也会出现。尝试用持久性缓存来提高构建性能。 尝试用更好的算法和默认值来改进长期缓存。 尝试用更好的 Tree Shaking 和代码生成来改善包大小。 尝试改善与网络平台的兼容性。 尝试在不引入任何破坏性变化的情况下,清理那些在实现 v4 功能时处于奇怪状态的内部结构。 试图通过现在引入突破性的变化来为未来的功能做准备,使其能够尽可能长时间地保持在 v5 版本上。 迁移指南
源代码效果预览先实现一个正方形,然后旋转实现,实现心的下半部分//预设一个div <div class="heart"> </div>.heart { //这里模拟心跳的动画,后面会写 animation: beat 1s infinite; -webkit-animation: beat 1s infinite; //宽为200px width: 200px; //高为200px height: 200px; //背景颜色 background-color: #f00; // 添加阴影 filter:drop-shadow(0px 0px 20px rgb(255,20,20)); //选装45度制作心尖 transform: rotate(45deg); // 往下往左各移动200px position: relative; top: 200px; left: 200px; }在正方形上加圆,实现心//使用::before和::after .heart::before, .heart::after { content: ""; //与正方行为参照。必须写。具体的位置,分开写,见下。 position: absolute; //宽和高都为200px;保证和正方型重叠的部分大小一致。 width: 200px; height: 200px; //设置弧度为100px,实现圆 border-radius: 100px; background-color: #f00; } // 设置位置 .heart:before { left: -100px; } // 设置位置 .heart::after { left: 0px; top: -100px; }添加动画@keyframes beat { 0% { //注意这里一定要加上rotate(45deg),不加的话,会默认不旋转 transform: rotate(45deg) scale(0.8, 0.8); // 设置透明度 opacity: 1; } 25% { transform: rotate(45deg) scale(1, 1); opacity: 0.8; } 100% { transform: rotate(45deg) scale(0.8, 0.8); opacity: 1; } }完结撒花
前言无论是我们个人独立开发项目,还是在公司团队开发项目,如何选用一款合适的模板,对于开发者的体验,开发的效率,公司的效益来说,是极为重要的,现在社会就是一个快餐社会,你比别人慢,你就会被别人干掉!我这里总结了11个不同技术栈的后台管理模板,希望为大家提提速!Vue Element Admin ⭐ 70,089GitHub地址vue-element-admin 是一个后台前端解决方案,它基于 vue 和 element-ui实现。它使用了最新的前端技术栈,内置了 i18n 国际化解决方案,动态路由,权限验证,提炼了典型的业务模型,提供了丰富的功能组件,它可以帮助你快速搭建企业级中后台产品原型。相信不管你的需求是什么,本项目都能帮助到你。Adminlte ⭐ 39,298GitHub地址AdminLTE是一个完全响应的管理模板。基于Bootstrap 4.6框架和 JS/jQuery 插件。高度可定制且易于使用。适合从小型移动设备到大型台式机的多种屏幕分辨率。Tabler ⭐ 23,956GitHub地址Tabler 完全响应并与所有现代浏览器兼容。由于其现代、用户友好的设计,您可以创建用户会喜欢的全功能界面!选择您需要的布局和组件并对其进行自定义,以使您的设计一致且引人注目。每个组件的创建都注重细节,使您的界面美观!Ngx Admin ⭐ 22,930GitHub地址最流行和最受信任的 Angular 开源仪表板模板就在那里。全球数十万开发人员和财富 500 强公司使用*。 超过 40 多个 Angular 组件和 60 多个使用示例。使用 ngx-admin 启动您的项目并节省资金。 已经在使用 ngx-admin 并且愿意切换到 Material 主题?Material 主题向后兼容。查看描述如何做到这一点的文章。 ngx-admin 材质与 Angular Material 和 Nebular 完美配合。两全其美!Gentelella ⭐ 20,260GitHub地址Gentelella Admin 是一个免费使用的** Bootstrap **管理模板。该模板使用默认的 Bootstrap 4 样式以及各种强大的 jQuery 插件和工具来创建用于创建管理面板或后端仪表板的强大框架。主题使用多个库用于图表、日历、表单验证、向导样式界面、画布导航菜单、文本表单、日期范围、上传区域、表单自动完成、范围滑块、进度条、通知等等。React Admin ⭐ 17,613GitHub地址一个前端框架,用于在 REST/GraphQL API 之上构建在浏览器中运行的数据驱动应用程序,使用 ES6、React和Material Design。以前命名为admin-on-rest。Blur Admin ⭐ 11,251GitHub地址Blur admin 是 Angular 前端管理仪表板模板。这意味着您可以在图表上看到的所有数据,图表表格都是用 Javascript 硬编码的。您可以 不受限制地使用任何您想要的后端。D2 Admin ⭐ 10,776GitHub地址D2Admin 是一个基于vue构建完全 开源免费 的企业中后台产品前端集成方案,使用最新的前端技术栈,小于 60kb 的本地首屏 js 加载,已经做好大部分项目前期准备工作,并且带有大量示例代码,助力管理系统敏捷开发。Vue Admin Beautiful Pro ⭐ 10,023GitHub地址 一个充满争议vue后台管理模板!可自行百度!Material Dashboard ⭐ 9,802GitHub地址Material Dashboard是一个免费的 Material Bootstrap Admin,它的设计灵感来自 Google 的 Material Design。我们很高兴通过一组易于使用且美观的组件来介绍我们对材料概念的看法。Material Dashboard 是基于流行的 Bootstrap 框架构建的,它带有几个经过重新设计的第三方插件,以适应其余元素。Material Dashboard 利用光、表面和运动。总体布局就像一张张纸遵循多个不同的层,因此深度和顺序是显而易见的。导航主要位于左侧边栏,内容位于主面板的右侧。Vuestic Admin ⭐ 8,173GitHub地址免费且美观的Vue.js 管理模板,包含 44 多个自定义 UI 组件。 由Epicmax开发 。由Vasili Savitski基于Vuestic UI库设计。
填空: 1.分布式文件系统在物理结构上是由计算机集群中的多个节点构成的,这些节点分为两类:一类叫__________;另一类叫aaS。 5.NoSQL数据库采用的是__非关系数据__模型。6.MapReduce1.0采用__Master/Slave 架构设计,包括一个JobTracker和若干TaskTracker 7.RDD是___弹性分布式____数据集。是分布式内存的一个抽象概念,提供了一种高度受限的共享内存模型。 8.阶段/Stage是作业调度的基本单位。 9.colFamily指的是__列族。 10.与分布式对应的方式是____集中式_.。 11.大规模数据集的处理包括分布式存储和__分布式计算_____两个核心环节。 12.MapReduce的核心思想可以用___分而治之____来描述。 13.写出大数据特征的4个V:数据量大volume,数据类型繁多 variety,处理速度快velocity,价值密度低value 14.NoSQL的四大类型为键值数据库、列族数据库、文档数据库、图数据库 15.在HDFS中,名称节点负责管理分布式文件系统的命名空间,保存了两个核心的数据结构,即_____FsImage_____和EditLog。 16.BigTable是一个分布式存储系统,利用谷歌提出的___MapReduce_______分布式并行计算模型来处理海量数据。 17.Shuffle过程分为_Map___端的操作和Reduce端的操作。 18.数据总体上可以分为___流数据______和____静态数据_____。答案:流数据,静态数据 19.UMP系统功能为_容灾_、读写分离、资源管理、资源调度、资源隔离和数据安全。 20.目前Spark支持三种不同类型的部署方式,包括__standalone____、Spark on Mesos、Spark on YARN。答案:standalone、Spark on Mesos、Spark on YARN。 21.RDS英文全称为__Relational Database Service__。 22.MapReduce的核心函数:Map和___Reduce___。 23.MapReduce整个工作流程的核心环节是__Shuffle__过程。 24.Spark使用____DAG_____执行引擎以支持循环数据流与内存计算. 25.HBase只有一个索引——行键____,通过巧妙的设计,HBase中的所有访问方法,或者通过行健访问,或者通过行健扫描,从而使得整个系统不会慢下来。 26.Scala是一门现代的多范式编程语言,平滑的集成了____面向对象_____和____函数式_____的特性,旨在以简练优雅的方式来表达常用编程模式。 27.RDD中的依赖关系分为____窄依赖_____与___宽依赖______。答案:窄依赖,宽依赖 28.YARN体系结构中包含了三个组件:ResourceManager、___ApplicationMaster ____、NodeManager 29.写出大数据特征的4个V? 数据量大volume,数据类型繁多 variety,处理速度快velocity,价值密度低value30.信息科技为大数据时代提供技术支撑有哪些? 在信息存储方面,来自斯威本科技大学(Swinburne University of Technology)的研究团队,在2013年6月29日刊出的《自然通讯(Nature Communications)》杂志的文章中,描述了一种全新的数据存储方式,可将1PB(1024TB)的数据存储到一张仅DVD大小的聚合物碟片上。 在信息处理方面,CPU处理能力大幅提升; 在信息传输方面,网络带宽不断增加。31.参考下图阐述大数据的特征。 大数据的特征被总结为多个V。该图中给出了4个V,分别是:大数据的量Volume之大,大数据的速度velocity之快,大数据的多样化variety,以及大数据的价值value密度之低。32.图中数字3代表什么意思? 备份冗余数目33.在spark-shell中,输入语句完成如下功能:打开本地文件/usr/local/a.txt,并用a对其引用。val a=sc.textFile(“file:///usr/local/a.txt”)#&&#val a=sc.textFile("/usr/local/a.txt")34.在spark-shell中,写出实现如下功能的语句:打开Hadoop分布式文件/usr/local/a.txt,并保存在word中。 答案:val word=sc.textFile(“hdfs:///usr/local/a.txt”)单选: 1.下述关于hadoop的阐述,正确的是 (D) A. 是一个分布式数据库与并行计算系统 B. 是一个分布式存储系统与分布式数据库 C. 是一个集中式存储与分布式并行运算系统 D. 是一个分布式存储与分布式并行运算系统2.当一个客户端从Zookeeper服务器上拿到-ROOT-表的地址以后,就可以通过 © 找到用户数据表所在的Region服务器,并直接访问该Region服务器获得数据。 A. A.一级寻址 B. B.二级寻址 C. C.三级寻址 D. D.四级寻址3.(A)是HBase中最核心的模块,负责维护分配给自己的Region,并响应用户的读写请求。 A. Region服务器 B. Store C. MemStore缓存 D. StoreFile文件4.下列选项中_B_不是NoSQL数据库的特点。 A. 灵活的可扩展性 B. 动态的数据迁移 C. 灵活的数据模型 D. 与云计算紧密结合 5.下列关于云数据库的特点,错误的是_A_ A. 灵活的关系数据模型 B. 较低的使用代价 C. 高性能 D. 动态可扩展性6.MapReduce是____C____编程框架。 A. 分布式并发 B. 非分布式并行 C. 分布式并行 D. 非分布式并发7.JobTracker的三大功能不包括(D) A. 资源管理 B. 任务调度 C. 任务监控 D. 调度Map/Reduce任务的执行8.“用户原创内容”的数据产生方式对应于下面哪个阶段?(B) A. web1.0 B. web2.0 C. 互联网 D. 物联网9.以下不属于Action API的是(B)。 A. count() B. map(func) C. first() D. reduce(func)10.scala>valwordCounts=textFile.flatMap(line=>line.split("")).map(word=>(word,1)).reduceByKey((a,b) => a + b) scala > wordCounts.collect() 在上面的代码中属于“行动”类型的操作的是(D)。 A. flatMap() B. Map() C. reduceByKey() D. collect()11.Map任务的输入文件、Reduce任务的处理结果都是保存在(B)的。 A. 本地存储 B. 分布式文件系统 C. 硬盘 D. 主存12.以下哪项不是MapReduce体系结构的主要组成部分(D) A. Client B. TaskTracker C. JobTracker D. TaskScheduler13.下列选项中(C)不是文档数据库的优点 A. 性能好 B. 复杂性低 C. 统一的查询语法 D. 数据结构灵活14.HBase是针对谷歌BigTable的开源实现,是一个高可靠、B_、面向列、可伸缩的分布式数据库,主要用来存储非结构化和半结构化的松散数据。 A. A.高功能 B. B.高性能 C. C.低效率 D. D.高质量15.UMP系统借助于__C___来实现集群内部的负载均衡。 A. 主从库实现用户调度 B. 主从库实现用户代理服务器 C. 利用主从库实现用户操作的分离 D. 主从库实现用户日志管理16.Spark的主要编程语言是:(B)。 A. Java B. Scala C. Python D. R17.以下属于商业级流计算的是:(A) A. IBM InfoSphere Streams B. Twitter Storm C. Yahoo! S4 D. FaceBook Puma18.下列选项不属于Zookeeper主要发挥的作用的是__D A. 提供分布式锁 B. 监控所有MySQL实例 C. 作为全局的配置服务器 D. 支持透明的数据分片作用19.以下哪项步骤不包含在溢写过程中(B) A. 分区 B. 文件归并 C. 排序 D. 合并20.下列哪个不是连接RDS for MySQL数据库的方法(C) A. 使用客户端MySQL-Front访问 B. 使用数据库管理工具Navicat_MySQL C. Shell命令 D. 使用MySQL命令登录21.MapReduce的处理单位是(B) A. block B. split C. Map D. RR22.以下不属于hadoop存在的缺点的是:(B) A. 表达能力有限 B. 编程模式灵活 C. 磁盘IO开销大 D. 延迟高23.谷歌的GFS和MapReduce等大数据技术受到追捧,Hadoop平台开始大行其道是在大数据发展的那个时期(B ) A. 第一阶段 B. 第二阶段 C. 第三阶段 D. 第四阶段24.每个Map任务分配一个缓存,MapReduce默认缓存是(A) A. 100MB B. 80MB C. 120MB D. 200MB多选: 1.MapReduce执行的全过程包括以下几个主要阶段(ABCD) A. 从分布式文件系统读入数据 B. 执行Map任务输出中间结果 C. 通过Shuffle阶段把中间结果分区排序整理后发送给Reduce任务 D. 执行Reduce任务得到最终结果并写入分布式系统文件2.HDFS特殊的设计,在实现上述优良特性的同时,也使得自身具有一些应用局限性,主要包括以下几个方面 (AB) A. A.不适合低延迟数据访问 B. B.无法高效存储大量小文件 C. C.不支持单用户写入及任意修改文件 D. D.硬件设备昂贵3.最终一致性根据更新数据后各进程访问到数据的时间和方式的不同,可以进行区别。下列说法正确的是 ABCD A. 因果一致性 B. 读己之所写一致性 C. 单调读一致性$会话一致性 D. 单调写一致性4.Reduce端的Shuffle过程包括(ABD) A. “领取”数据 B. 归并数据 C. 溢写 D. 把数据输入到Reduce任务5.采用HDFS联邦的设计方式,可解决单名称节点以下问题(ABD) A. HDFS集群可扩展性 B. 性能更高效 C. 单点故障问题 D. 良好的隔离性6.MapReduce1.0架构设计具有一些很难克服的缺陷,包括(ABCD) A. 存在单点故障 B. JobTracker“大包大揽”导致任务过重 C. 容易出现内存溢出 D. 资源划分不合理7.三次信息化浪潮的标志有哪些(ABC) A. 个人计算机 B. 互联网 C. 物联网,云计算和大数据 D. 人工智能8.信息科技需要解决的核心问题包括:(ACD) A. 信息存储 B. 信息可视 C. 信息传输 D. 信息处理9.以下属于批处理大数据计算的产品有:(AC) A. MapReduce B. Storm C. Spark D. Pregel10.以下属于图计算的产品有:(ABCD) A. Pregel B. GraphX C. Giraph D. PowerGraph11.访问HBase表中的行有哪几种方式(ABD) A. 通过单个行键 B. 行键的区间 C. 列族 D. 全表扫描12.大数据对科学研究有哪些影响(ABCD) A. 第一范式:实验科学 B. 第二范式:理论科学 C. 第三范式:计算科学 D. 第四范式:数据密集型科学13.关系数据库无法满足Web2.0的需求主要表现在哪几个方面(ACD) A. 无法满足海量数据的管理需求 B. 无法满足数据完整性 C. 无法满足数据高并发的需求 D. 无法满足高可扩展性和高可用性的需求14.人类科学研究范式包括:(ABCD) A. 实验 B. 理论 C. 计算 D. 数据15.下面关于MapReduce工作流程说法正确的是(ABD) A. 不同的Map任务之间不会进行通信。 B. 不同的Reduce任务之间也不会发生任何信息交换。 C. 用户能显式的从一台机器向另一台机器发送信息 D. 所有的数据交换都是通过MapReduce框架自身去实现的16.与传统并行计算框架相比,以下哪些是MapReduce的优势(ABC) A. 非共享式,容错性好 B. 普通PC机,便宜,扩展性好 C. 编程/学习难度较简单 D. 适用场景为实时、细粒度计算、计算密集型17.Hadoop1.0的核心组件主要存在以下不足(ABCD) A. 难以看到程序整体逻辑 B. 开发者自己管理作业之间的依赖关系 C. 执行迭代操作效率低 D. 资源浪费18.NoSQL数据库的明显优势在于(BCD) A. 数据的完整性 B. 可以支持超大规模数据存储 C. 灵活的数据模型 D. 强大的横向扩展能力19.HDFS在设计上采取了多种机制保证在硬件出错的环境中实现数据的完整性。总体而言,HDFS要实现以下目标: (1)兼容廉价的硬件设备 (2)流数据读写 (3)大数据集 (4)复杂的文件模型 (5)强大的跨平台兼容性 (D) A. A.(1)(2)(3)(4) B. B.(1)(2)(4)(5) C. C.(2)(3)(4)(5) D. D.(1)(2)(3)(5)20.Map端的Shuffle过程包括以下哪几个步骤。(ABCD) A. 输入数据和执行Map任务 B. 写入缓存 C. 溢写(分区、排序、合并) D. 文件归并21.MapReduce的广泛应用包括(ABCD) A. 关系代数运算 B. 分组与聚合运算 C. 矩阵乘法 D. 矩阵-向量乘法22.大数据处理主要包括三个类型,分别是:(ABC)。 A. 复杂的批量数据处理 B. 基于历史数据的交互式查询 C. 基于实时数据流的数据处理 D. 集成数据23.UMP系统采用哪两种资源隔离方式(AB) A. 用Cgroup限制MySQL进程资源 B. 在Proxy服务器端限制QPS C. 通过MySQL实例的迁移 D. 采用资源池机制管理数据库服务器资源24.MapReduce执行的全过程包括以下几个主要阶段(ABCD) A. 从分布式文件系统读入数据 B. 执行Map任务输出中间结果 C. 通过Shuffle阶段把中间结果分区排序整理后发送给Reduce任务 D. 执行Reduce任务得到最终结果并写入分布式系统文件25.以下(ACD)产品使Hadoop功能更加完善. A. Pig B. QJM C. Tez D. Oozie26.以下属于流计算的产品有:(ABCD) A. Storm B. S4 C. Flume D. Puma27.基于MapReduce模型的关系上的标准运算,包括(ABCD) A. 选择运算 B. 并、交、差运算 C. 投影运算 D. 自然连接运算28.不同的计算框架统一运行在YARN中,可以带来如下好处:(ACD) A. 计算资源按需伸缩 B. 计算资源平均分配 C. 不用负载应用混搭,集群利用率高 D. 共享底层存储,避免数据跨集群迁移29.数据采集系统的基本架构一般有以下三个部分:(ABD) A. Agent B. Collector C. Calculate D. Store30.以下属于Spark的主要特点的是:(ABCD)。 A. 运行速度快 B. 容易使用 C. 通用性 D. 运行模式多样31.Spark采用RDD以后能够实现高效计算的原因主要在于:(ABD) A. 高效的容错性 B. 中间结果持久化到内存 C. 两种依赖方式 D. 存放的数据可以是Java对象32.下列为UMP系统架构设计遵循的原则的是(ABCD) A. 保持单一的系统对外入口,并且为系统内部维护单一的资源池 B. 消除单点故障,保证服务的高可用性 C. 保证系统具有良好的可伸缩性,能动态地增加、删减计算与存储节点 D. 保证分配给用户的资源也是弹性可伸缩的,资源之间相互隔离,确保应用和数据的安全33.信息科技为大数据时代提供的支撑(BCD) A. 计算机设备廉价 B. 存储设备容量不断增加 C. CPU处理能力大幅度提升 D. 网络带宽不断增加34.为了保证系统的容错性和可用性,HDFS采用了多副本方式对数据进行冗余存储,这种多副本方式具有以下几个优点:(BCD) A. A.容易修改数据问题 B. B.加快数据传输速度 C. C.保证数据的可靠性 D. D.容易检查数据错误35.UMP系统是如何保障数据安全的(ABCD) A. SSL数据库连接 B. 数据访问IP白名单 C. 记录用户操作日志 D. SQL拦截36.HBase的实现包括3个主要的功能组件:(ABD) A. A.库函数 B. B.一个Master主服务器 C. C.一个Region服务器 D. D.许多个Region服务器判断: 1.分布式文件系统在物理结构上是由计算机集群中的多个节点构成的,这些节点分为两类:一类叫主节点,另一类叫从节点。(√) 2.MapReduce框架采用了Master/Slave架构,包括一个Master和若干个Slave。Master上运行JobTracker,Slave上运行TaskTracker . (√) 3.HDFS采用块的概念,默认的一个块大小是64MB。 (√) 4.HDFS采用抽象的块概念可以简化系统设计,适合数据备份,但不可以支持大规模文件 存储。(×) 5.在HDFS的设计中,第二名称节点起到了名称节点的“检查点”和“热备份”的作用,因 为有了第二名称节点的存在,当名称节点发生故障时,系统就不会丢失元数据信息。(×) 6.在HBase中执行更新操作时,会在生成一个新版本之前删除数据旧的版本。(×) 7.HBase的系统架构中的客户端是指用户。(×) 8.CAP中的C与CAID中的C的含义一样。 (×) 9.NoSQL的英文全称为 No Structual Query Language。( ×) 10.云计算八大优势为按需服务、随时服务、通用性、高可靠性、极其廉价、超大规模、 虚拟化、高扩展性。(√) 11.云计算可同时为众多用户提供服务。(√) 12.云数据库有专属与自己的数据模型。( ×) 13.MapReduce是Hadoop MapReduce的开源实现.(×) 14.MapReduce运行在分布式文件系统GFS上。 (√) 15.HDFS联邦是真正的分布式设计。 (×) 16.MapReduce1.0中资源被强制等量划分为多个“槽”,槽又被进一步划分为Map槽和 Reduce槽,分别供Map任务和Reduce任务使用,彼此之间能使用分配给对方的槽。(×) 17.一个作业包含多个RDD及作用于相应RDD上的各种操作。(√) 18.RDD提供了一组丰富的操作以支持常见的数据运算,分为“行动”(Action)和“转换” Transformation。 ( √) 19.RDD本质上是一个支持读写的分区记录集合,可以直接修改。 ( ×) 20.RDD采用了惰性调用,即在RDD执行过程中,真正的计算发生在RDD的“行动”操作, 对于“行动”之前的所有“转换”操作,Spark只是记录下“转换”操作应用的一些基础数 据集以及RDD生成的轨迹,不会触发真正的计算。(√) 21.人类社会的数据产生大致经历了3个阶段:运营式系统阶段,用户原创内容阶段和感知 式系统阶段。( √) 22.大数据具有的三大特征:全样而非抽样,效率而非精确,相关而非因果。(√) 23.云计算3中典型的服务模式:IaaS(基础设施即服务),PaaS(平台即服务),SaaS(软件 即服务)。( √) 24.web2.0特征之一就是物联网原创内容。( ×) 25.1PB(1024TB)的数据能够存储到一张仅DVD大小的聚合物碟片上。(√) 26.NewSQL这类数据库不仅具有NoSQL对海量数据的存储管理能力,还保持了传统数据库 支持ACID和SQL等特性。( √) 27.HBase采用行键、列族、列限定符、时间戳来定位一个单元格。(√) 28.行键是按照字典序存储。( √) 29.每个Application都有自己专属的Executor进程,并且该进程在Application运行期间一直 驻留。Executor进程以多线程的方式运行Task。 (√) 30.Spark可以部署在资源管理器YARN之上,提供一站式的大数据解决方案。(√) 31.Hadoop属于开发运行环境中的运行环境。 (√) 32.为保证一致性,关系数据库遵守ACID模型,NoSQL数据库遵守BASE模型。(√) 33.HDFS采用抽象的块概念可以简化系统设计,适合数据备份,但不可以支持大规模文件存储。(×) 34.相对于之前的HDFS10而言,HDFS2.0增加了HDFS HA和HDFS联邦等新特性。(√) 35.HDFS把硬件出错看成一种常态,设计了错误恢复机制。 (√) 36.UMP系统是低成本和高性能的MySQL数据库方案,关键模块采用Erlang语言实现。 (√) 37.Mnesia是一个集中式数据库管理系统。 (×) 38.UMP系统只为一个用户创建一个MySQL实例。 (×) 39.RDS实例或简称“实例”,是用户购买RDS服务的基本单位。 (√) 40.Map函数和Reduce函数都是以key,value作为输入。 (√) 41.MapReduce程序一定要用java来写。(×) 42.词频计算是典型的分组聚合运算。 (√) 43.Tez支持DAG作业的计算框架,对作业的操作进行重新分解和组合,解决了不同的MapReduce任务之间存在重复操作,降低效率的问题。(√) 44.流计算秉承一个基本理念,即数据的价值随着时间的流逝而降低,如用户点击流。(√) 45.分布式数据库HBase的数据类型只有字符串。(√) 46.新建RDS账号,MySQL实例支持最多创建20个账号,SQL Server实例支持最多创建50个账号。(×) 47.HDFS HA提供两个名称节点,很好的解决了可扩展性、系统性能和隔离性三个方面的问题。(×) 48.Spark Streaming的原理是将数据分解成一系列短小的批处理作业。(√) 49.Hadoop擅长批处理,不适合流计算。(√) 50.Shuffle过程是指对Map输出结果进行分区、排序、合并等处理并交给Reduce的过程。(√) 51.HDFS HA本质上不是单名称节点。(×) 52.Spark可以部署在资源管理器YARN之上,提供一站式的大数据解决方案。(√) 53.RDD在Spark架构中运行第一步是创建RDD对象。(√) 54.UMP系统是低成本和高性能的MySQL数据库方案,关键模块采用Erlang语言实现。(√) 55.BigTable是一个分布式存储系统,使用谷歌分布式文件系统MapReduce作为底层数据存储。(×) 56.在用户购买RDS实例时,所选择的内存大小已经决定了该实例的最大连接数。(√) 57.MapReduce设计的一个理念是“计算向数据靠拢”,而不是“数据向计算靠拢” (√) 58.HBase操作不存在复杂的表与表之间的关系,只有简单的插入、查询、删除、清空等。(√) 59.资源池是为MySQL实例分配资源的基本单位。(√) 60.split 是一个逻辑概念,它只包含一些元数据信息,比如数据起始位置、数据长度、数据所在节点等。它的划分方法完全由用户自己决定。 (√)补充: Web2.0网站系统通常要求严格的数据库事务。(×) YARN架构设计基本思路就是“放权” (√)Reduce从©读取数据。 A.本地存储 B.磁盘 C.硬盘 D.主存“软状态”是指(状态可以有一段时间不同步,具有一定的滞后性)。5.Map端的所有Shuffle过程结束后,所有Map输出结果都保存在Map机器的本地磁盘上 (√) P138 16.在许多企业实际应用中,Hadoop和Spark的统一部署是一种比较现实合理的选择。()。 √ 23.在流处理流程中,实时查询服务可以不断更新结果,并将用户所需的结果实时推送给用户。() √ 24.Spark的设计遵循“一个软件栈满足不同应用场景”的理念,逐渐形成了一套完整的生态系统。() √ 26.DAG:是Directed Acyclic Graph(有向无环图)的简称,反映RDD之间的依赖关系。() √ 27.Spark运行架构包括集群资源管理器(Cluster Manager)、运行作业任务的工作节点(Worker Node)、每个应用的任务控制节点(Driver)和每个工作节点上负责具体任务的执行进程(Executor)。() √ 28.一个Application由一个Driver和若干个Job构成,一个Job由多个Stage构成,一个Stage由多个没有Shuffle关系的Task组成。() √ 29.Stage的类型包括两种:和。 ShuffleMapStage,ResultStage 30.Spark用Scala语言实现了RDD的API,程序员可以通过调用API实现对RDD的各种操作。() √分布式文件系统在物理结构上是由计算机集群中的多个节点构成的,这些节点分为两类:一类叫__________;另一类叫__________。(P43)主节点/名称节点,从节点/数据节点 HDFS采用抽象的块概念可以简化系统设计,适合数据备份,但不可以支持大规模文件存储。 错误 P46 在HDFS中,名称节点负责管理分布式文件系统的命名空间,保存了两个核心的数据结构,即__________和__________。(P46)FsImage,EditLog 分布式文件系统在物理结构上是由计算机集群中的多个节点构成的,这些节点分为两类:一类叫主节点,另一类叫从节点。HDFS在设计上采取了多种机制保证在硬件出错的环境中实现数据的完整性。总体而言,HDFS要实现以下目标:__________。(P45) D (1)兼容廉价的硬件设备 (2)流数据读写 (3)大数据集 4)复杂的文件模型 5)强大的跨平台兼容性 A. (1)(2)(3)(4) B. 1)(2)(4)(5) C. 2)(3)(4)(5) D. 1)(2)(3)(5)HDFS特殊的设计,在实现上述优良特性的同时,也使得自身具有一些应用局限性,主要包括以下几个方面:。(P45) AB 不适合低延迟数据访问 无法高效存储大量小文件 不支持单用户写入及任意修改文件 硬件设备昂贵 为了保证系统的容错性和可用性,HDFS采用了多副本方式对数据进行冗余存储,这种多副本方式具有以下几个优点:。(P50)BCD 容易修改数据问题 加快数据传输速度 保证数据的可靠性 容易检查数据错误1.HDFS采用块的概念,默认的一个块大小是64MB。 ( ) (P46) √ 2.在HDFS的设计中,第二名称节点起到了名称节点的“检查点”和“热备份”的作用,因为有了第二名称节点的存在,当名称节点发生故障时,系统就不会丢失元数据信息。 ( ) (P48)× HDFS把硬件出错看成一种常态,设计了错误恢复机制。 P60 对第四章 填空 1.HBase是针对谷歌BigTable的开源实现,是一个高可靠、高性能、面向列、可伸缩的分布式数据库,主要用来存储非结构化和半结构化的松散数据。 P63 选择 2.BigTable是一个分布式存储系统,利用谷歌提出的__________分布式并行计算模型来处理海量数据。 P63 MapReduce 3.HBase只有一个索引——__________,通过巧妙的设计,HBase中的所有访问方法,或者通过行健访问,或者通过行健扫描,从而使得整个系统不会慢下来。 P65 行健 4.__________是HBase中最核心的模块,负责维护分配给自己的Region,并响应用户的读写请求。 选择 P75 Region服务器判断 1.BigTable是一个分布式存储系统,使用谷歌分布式文件系统MapReduce作为底层数据存储。 错 P63 2.分布式数据库HBase的数据类型只有字符串。 对 P64 3.HBase操作不存在复杂的表与表之间的关系,只有简单的插入、查询、删除、清空等。 对 P64 4.在HBase中执行更新操作时,会在生成一个新版本之前删除数据旧的版本。 P65 错 5.HBase的系统架构中的客户端是指用户。 P74 错单选 1.当一个客户端从Zookeeper服务器上拿到-ROOT-表的地址以后,就可以通过________找到用户数据表所在的Region服务器,并直接访问该Region服务器获得数据。 A.一级寻址 B.二级寻址 C.三级寻址 D.四级寻址 P74 C多选 1.HBase的实现包括3个主要的功能组件:__________。 A.库函数 B.一个Master主服务器 C.一个Region服务器 D.许多个Region服务器 ABD P71第五六章 下列选项中(B)不是NoSQL数据库的特点。 灵活的可扩展性 B.动态的数据迁移 C.与云计算紧密融合 D.灵活的数据模型 NoSQL的英文全称(Not only Structual Query Language)。 NoSQL的英文全称为 No Structual Query Language。× 关系数据库无法满足Web2.0的需求主要表现在哪几个方面(ACD) 无法满足海量数据的管理需求 无法满足数据完整性的需求 无法满足数据高并发性的需求 无法满足高可扩展性和高可用性的需求 与分布式对应的方式是(集中式) Hadoop属于开发运行环境中的运行环境。√ 为保证一致性,关系数据库遵守ACID模型,NoSQL数据库遵守BASE模型。√ NoSQL数据库的明显优势在于(BCD)。 实现数据完整性 支持超大规模数据存储 灵活的数据模型可以很好的支持Web2.0应用 具有强大的横向扩展能力 Web2.0网站系统通常要求严格的数据库事务。× NoSQL的四大类型为键值数据库、(列族数据库)、文档数据库、图数据库 下列选项中(C)不是文档数据库的优点。 性能好 B.灵活性高 C.统一的查询语法 D.数据结构灵活 NoSQL的三大基石包括(CAP、BASE、最终一致性)。 CAP中的C与CAID中的C的含义一样。× NewSQL这类数据库不仅具有NoSQL对海量数据的存储管理能力,还保持了传统数据库支持ACID和SQL等特性。√ 最终一致性根据更新数据后各进程访问到数据的时间和方式的不同,可以进行区别。下列说法正确的是(ABCD)。 因果一致性 “读己之所写”一致性 会话一致性 单调一致性 “软状态”是指(状态可以有一段时间不同步,具有一定的滞后性)。 云计算八大优势为按需服务、随时服务、通用性、(高可靠性)、极其廉价、超大规模、(虚拟化)、高扩展性。 云计算主要包括3种类型,即(IaaS、PaaS、SaaS)。 云计算可同时为众多用户提供服务。√ 下列关于云数据库的特点,错误的是(A)。 高可靠性 B.高可扩展性 C.采用多租形式 D.支持资源有效分布 关系数据库采用(关系数据)模型,NoSQL数据库采用(非关系数据)模型。 云数据库有专属与自己的数据模型。× UMP系统是低成本和高性能的MySQL数据库方案,关键模块采用Erlang语言实现。√ 下列为UMP系统架构设计遵循的原则的是(ABCD)。 保持单一的系统对外入口,并且为系统内部维护单一的资源池 保持单一故障,保证服务的高可用性 保证系统具有良好的可伸缩性,能够动态地增加、删减计算与存储节点 保证分配给用户的资源是弹性可伸缩的,资源之间相互隔离,保证应用和数据的安全 Mnesia是一个集中式数据库管理系统。× 下列选项不属于Zookeeper主要发挥的作用的是(D)。 作为全局的配置服务器 提供分布式锁 监视所有MySQL实例 支持透明的数据分片 UMP系统借助于()来实现集群内部的负载均衡。 Mnesia B.Zookeeper C.LVS D.Controller服务器 UMP系统功能为(容灾)、读写分离、资源管理、资源调度、(资源隔离)和数据安全。 UMP系统只为一个用户创建一个MySQL实例。× 资源池是为MySQL实例分配资源的基本单位。√ UMP系统采用哪两种资源隔离方式(AB)。 用Cgroup限制MySQL进程资源 在Proxy服务器限制QPS 通过MySQL实例的迁移 采用资源池机制管理数据库服务器资源 UMP系统是如何保障数据安全的(ABCD)。 SQL拦截 记录用户操作日志 数据访问IP白名单 SSL数据库连接 RDS英文全称为(Relational Database Service)。 RDS实例或简称“实例”,是用户购买RDS服务的基本单位。√ 在用户购买RDS实例时,所选择的内存大小已经决定了该实例的最大连接数。√ 新建RDS账号,MySQL实例支持最多创建20个账号,SQL Server实例支持最多创建50个账号。× 下列哪个不是连接RDS for MySQL数据库的方法(C)。 使用客户端MySQL-Front访问 使用数据库管理工具Navicat MySQL 使用Shell命令登录 使用阿里云控制台iDB Cloud访问 HBase采用“四维坐标”定位一个单元格。√ 行键是按照字典序存储。√ 访问HBase表中的行有哪几种方式(ABD)。 通过单个行键访问 通过一个行键的区间来访问 直接读取 全表扫描 41.colFamily指的是(列族)。第七章 填空: 1.MapReduce的核心函数:_______ _______ 答案:P132 Map Reduce 2.MapReduce的核心思想可以用_______来描述。 答案:P134 分而治之 3.MapReduce整个工作流程的核心环节是____过程。 答案:P136 Shuffle 4.Shuffle过程分为____端的操作和____端的操作。 答案:P136 Map Reduce 5.MapReduce是________编程框架。 答案:P131 分布式并行 6.MapReduce的处理单位是______ 答案:P课件15 split 7.大规模数据集的处理包括_________和________两个核心环节。 答案:P134 分布式存储 分布式计算单选: 1.Hadoop框架是用©实现的。 P133 A.C B.C++ C.java D.VB 2.以下哪项不是MapReduce体系结构的主要组成部分(D) P课件9 A.Client B.JobTracker C.TaskTracker D.TaskScheduler 3.每个Map任务分配一个缓存,MapReduce默认缓存是(A) P137 A.100MB B.80MB C.120MB D.200MB 4.以下哪项不属于步骤不包含在溢写过程中(B) P137 A.分区 B.归并 C.排序 D.合并 5.Reduce从©读取数据。 P135 A.本地存储 B.磁盘 C.硬盘 D.主存 6.Map任务的输入文件、Reduce任务的处理结果都是保存在(A)的。P135 A.分布式文件系统 B.本地存储 C.硬盘 D.主存多选: 1.下面关于MapReduce工作流程说法正确的是(ABD) P135 A.不同的Map任务之间不会进行通信。 B.不同的Reduce任务之间也不会发生任何信息交换。 C.用户能显式的从一台机器向另一台机器发送信息 D.所有的数据交换都是通过MapReduce框架自身去实现的。 2.Map端的Shuffle过程包括以下哪几个步骤。(ABCD) P136 A.输入数据和执行Map任务 B.写入缓存 C.溢写(分区、排序、合并) D.文件归并 3.Reduce端的Shuffle过程包括(ABD) P138 A.“领取”数据 B.归并数据 C.溢写 D.把数据输入到Reduce任务 4.基于MapReduce模型的关系上的标准运算,包括(ABCD) P142 A.选择运算 B.投影运算 C.并、交、差运算 D.自然连接运算 5.MapReduce执行的全过程包括以下几个主要阶段(ABCD) P151 A.从分布式文件系统读入数据 B.执行Map任务输出中间结果 C.通过Shuffle阶段把中间结果分区排序整理后发送给Reduce任务 D.执行Reduce任务得到最终结果并写入分布式系统文件 6.MapReduce的广泛应用包括(ABCD) P151 A.关系代数运算 B.分组与聚合运算 C.矩阵-向量乘法 D.矩阵乘法 7.与传统并行计算框架相比,以下哪些是MapReduce的优势(ABC) P课件6 A.非共享式,容错性好 B.普通PC机,便宜,扩展性好 C.编程/学习难度较简单 D.实时、细粒度计算、计算密集型判断: 1.MapReduce设计的一个理念是“计算向数据靠拢”,而不是“数据向计算靠拢” (√) P133 2.MapReduce程序一定要用java来写。 (×) P133 3.Map函数和Reduce函数都是以<key,value>作为输入(√) P133 4.Shuffle过程是指对Map输出结果进行分区、排序、合并等处理并交给Reduce的过程。 (√) P136 5.Map端的所有Shuffle过程结束后,所有Map输出结果都保存在Map机器的本地磁盘上 (√) P138 6.词频计算是典型的分组聚合运算。 (√) P144 7.MapReduce运行在分布式文件系统GFS上。 (√) P132 8.MapReduce是Hadoop MapReduce的开源实现。 (×) P132 9.MapReduce框架采用了Master/Slave架构,包括一个Master和若干个Slave。Master上运行JobTracker,Slave上运行TaskTracker . (√) P课件7 split 是一个逻辑概念,它只包含一些元数据信息,比如数据起始位置、数据长度、数据所在节点等。它的划分方法完全由用户自己决定。 (√) P课件15第八章 单选 1.JobTracker的三大功能不包括(D) P160 A.资源管理 B.任务调度 C.任务监控 D.调度Map/Reduce任务的执行多选 1.Hadoop1.0的核心组件主要存在以下不足(ABCD)P155 A.难以看到程序整体逻辑 B.开发者自己管理作业之间的依赖关系 C.执行迭代操作效率低 D.资源浪费 2.以下(ACD)产品使Hadoop功能更加完善. P156 A.Pig B.QJM C.Tez D.Oozie 3.采用HDFS联邦的设计方式,可解决单名称节点以下问题(ABD) P159 A.HDFS集群可扩展性 B.性能更高效 C.单点故障问题 D.良好的隔离性 4.MapReduce1.0架构设计具有一些很难克服的缺陷,包括(ABCD) P160 A.存在单点故障 B.JobTracker“大包大揽”导致任务过重 C.容易出现内存溢出 D.资源划分不合理 填空 1.MapReduce1.0采用________架构设计,包括一个__JobTracker___和若干个____TaskTracker___ 答案:Master/Slave P159 2.YARN体系结构中包含了三个组件:__ResourceManager 、___、 NodeManager ______ 答案: ApplicationMaster P161判断 1.Tez支持DAG作业的计算框架,对作业的操作进行重新分解和组合,解决了不同的MapReduce任务之间存在重复操作,降低效率的问题。 (√) P156 2.相对于之前的HDFS10而言,HDFS2.0增加了HDFS HA和HDFS联邦等新特性。 (√) P156 3.HDFS HA提供两个名称节点,很好的解决了可扩展性、系统性能和隔离性三个方面的问题。(×) P158 4.HDFS联邦是真正的分布式设计。(×) P158 5.HDFS HA本质上不是单名称节点。 (×) P158 6.MapReduce1.0中资源被强制等量划分为多个“槽”,槽又被进一步划分为Map槽和Reduce槽,分别供Map任务和Reduce任务使用,彼此之间能使用分配给对方的槽。 (×) P160 YARN架构设计基本思路就是“放权” (√) P160第九十章 1.以下属于Spark的主要特点的是:()。 A.运行速度快 B.容易使用 C.通用性 D.运行模式多样 ABCD 2.Spark使用_________执行引擎。 DAG 3.Scala是一门现代的多范式编程语言,平滑的集成了_________和_________的特性,旨在以简练优雅的方式来表达常用编程模式。 面向对象,函数式 4.Spark的主要编程语言是:()。 A.Java B.Scala C.Python D.R B 5.大数据处理主要包括三个类型,分别是:()。 A.复杂的批量数据处理 B.基于历史数据的交互式查询 C.基于实时数据流的数据处理 D.集成数据 ABC 6.RDD是_________数据集。是分布式内存的一个抽象概念,提供了一种高度受限的共享内存模型。 弹性分布式 7.是作业调度的基本单位。 阶段 8.一个作业包含多个RDD及作用于相应RDD上的各种操作()。 √ 9.以下不属于hadoop存在的缺点的是:()。 A.表达能力有限 B.编程模式灵活 C.磁盘IO开销大 D.延迟高 ACD 10.RDD提供了一组丰富的操作以支持常见的数据运算,分为“行动”(Action)和“转换”(Translation)()。 √ 11.Spark并不能完全替代Hadoop,主要用于替代Hadoop中的MapReduce计算模型()。 √ 12.Spark可以部署在资源管理器YARN之上,提供一站式的大数据解决方案()。 √ 13.RDD本质上是一个支持读写的分区记录集合,可以直接修改()。 × 14.RDD采用了惰性调用,即在RDD执行过程中,真正的计算发生在RDD的“行动”操作,对于“行动”之前的所有“转换”操作,Spark只是记录下“转换”操作应用的一些基础数据集以及RDD生成的轨迹,不会触发真正的计算。()。 √ 15.目前Spark支持三种不同类型的部署方式,包括、、_。 standalone、Spark on Mesos、Spark on YARN。 16.在许多企业实际应用中,Hadoop和Spark的统一部署是一种比较现实合理的选择。()。 √ 17.以下不属于Action API的是()。 A.count() B.map(func) C.first() D.reduce(func) B 18.scala >val wordCounts=textFile.flatMap(line=>line.split("")).map(word=>(word,1)).reduceByKey((a,b) => a + b) scala > wordCounts.collect() 在上面的代码中属于“行动”类型的操作的是()。 A.flatMap() B.map() C.reduceByKey() D.collect() D 19.流计算秉承一个基本理念,即数据的价值随着时间的流逝而降低,如用户点击流。() √ 20.以下属于商业级流计算的是:()。 A.IBM InfoSphere Streams B.Twitter Storm C.Yahoo! S4 D.FaceBook Puma A 21.Hadoop擅长批处理,不适合流计算。() √ 22.数据采集系统的基本架构一般有以下三个部分:()。 A.Agent B.Collector C.Calculate D.Store C 23.在流处理流程中,实时查询服务可以不断更新结果,并将用户所需的结果实时推送给用户。() √ 24.Spark的设计遵循“一个软件栈满足不同应用场景”的理念,逐渐形成了一套完整的生态系统。() √ 25.Spark可以部署在资源管理器YARN之上,提供一站式的大数据解决方案。() √ 26.DAG:是Directed Acyclic Graph(有向无环图)的简称,反映RDD之间的依赖关系。() √ 27.Spark运行架构包括集群资源管理器(Cluster Manager)、运行作业任务的工作节点(Worker Node)、每个应用的任务控制节点(Driver)和每个工作节点上负责具体任务的执行进程(Executor)。() √ 28.一个Application由一个Driver和若干个Job构成,一个Job由多个Stage构成,一个Stage由多个没有Shuffle关系的Task组成。() √ 29.Stage的类型包括两种:和。 ShuffleMapStage,ResultStage 30.Spark用Scala语言实现了RDD的API,程序员可以通过调用API实现对RDD的各种操作。() √
请先阅读前两篇Docker安装Jenkins并配置GitHubJenkins+GitHub报错hudson.plugins.git.GitException: Failed to fetch from GitHub 443前提-Jenkins配置node环境1.配置node插件系统配置-插件管理-可选插件,搜索nodejs,直接安装2. 配置node版本General可以直接全部选择不填,但是建议勾选丢弃旧的构建这里丢弃旧的构建是指 丢弃之前的构建记录。如下图,这是Jenkins的构建记录,可以选择保留的天数以及保留的条数。源码管理这里为了解决GitHub使用https,经常报443的问题,使用ssh方式,进行代码的管理。点击 添加按钮,添加私钥,具体请查看另一篇文章。如果你不希望使用ssh,那么请直接选择用户名密码凭证直接选择GitHub hook trigger for GITScm polling构建环境构建选择执行shell,这里请安装cnpm,构建速度快,且容易报错。echo $PATH node -v npm -v npm install -g cnpm --registry=https://registry.npm.taobao.org cnpm install npm run build # 如果部署到服务器的话,建议打包 cd dist tar -zcvf dist.tar.gz *构建后步骤,发布到远程服务器这里我们时使用docker安装的Jenkins, 如果你部署的服务器就是jenkins服务器,那可以直接通过宿主机-容器共享卷的方式部署。因为比较简单,这里简单的说一下:找到jenkins构建后的目录做一个共享卷的操作,是的构建结束之后,宿主机直接拥有打包后的文件,所以最好的方式可以把宿主机的目录设置为nginx的web目录但是,会存在发布到远程服务器的情况,下面着重介绍一下:1、安装Publish Over SSH插件首页 -> 点击系统管理 -> 管理插件 ->可选插件 -> 过滤:ssh -> 选择Publish Over SSH插件,点击直接安装2、配置SSH系统管理 -> 系统设置 -> 下拉,找到Publish over SSH下面有一个test configuration 按钮,点击测试,sussess表示连接成功。构建后步骤1. cd /home/share/blog/www 2. tar -zxvf dist.tar.gz 3. rm -f dist.tar.gz远程服务器配置的nginx进行访问1、下载镜像docker pull nginx2、启动nginx容器docker run -d -p 9999:80 --name nginx nginx # 这里将容器的80端口映射到9999端口,访问ip:9999 即可 # -d 后台运行3、找到容器中nginx的位置3、在宿主机和nginx容器之间建立数据卷nginx.conf 配置文件logs 日志文件www 源代码部署文件!!! 如果直接执行下面的命令的话,可能会报错,Are you trying to mount a directory onto a file or vice-versa,因为不能挂载文件,只能挂载文件夹,所以先在容器中复制一份配置文件。第一步已经启动了一个nginx,所以可以直接拷贝mkdir -p /home/share/blog/conf /home/share/blog/logs 拷贝配置文件到工作目录 docker cp -a nginx:/etc/nginx/nginx.conf /home/share/blog/conf宿主机(自己决定)容器(容器启动后自动生成的)/home/share/blog/www/usr/share/nginx/html/home/share/blog/conf/nginx.conf/etc/nginx/nginx.conf/home/share/blog/logs/var/log/nginx首先停止之前的容器并删除 1. docker stop nginx 2. docker rm nginx重新启动容器并挂载工作目录docker run -d --restart always -p 9999:80 -v /home/share/blog/www:/usr/share/nginx/html -v /home/share/blog/conf/nginx.conf:/etc/nginx/nginx.conf -v /home/share/blog/logs:/var/log/nginx --name nginx nginx // --restart always // 表示docker重启时会自动重启该容器访问-成功
Jenkins官方https://www.jenkins.io/zh/doc/book/installing/执行下面的命令,这里我将Jenkins容器的访问端口映射到了服务器的8686端口,这样就可以通过8686访问jenkins。docker run -u root --rm -d -p 8686:8080 -p 50000:50000 -v jenkins-data:/var/jenkins_home -v /var/run/docker.sock:/var/run/docker.sock jenkinsci/blueoceanJenkins基础配置经过上面的配置,你可以访问你的Jenkins了,在浏览器中输入:http://ip:8686/注意:有的小伙伴可能打不开,此时要检查服务器是否开放了8686端口,如果没有,则需要配置安全组(阿里云/腾讯云),具体配置如下:如果配置没问题:会出现下面的界面,首先提示你登录的密码的位置:按照提示我们执行cat /var/lib/jenkins/secrets/initialAdminPassword得到密码,注意:这里我们使用的是docker安装的镜像,这个密码的位置是在镜像里面的,此时我们需要进入到容器中执行上面的cat命令:输入后点击Continue,如下:选择install suggested plugins,等待安装完毕,如果有安装失败的可以跳过,之后可以手动根据需求安装。设置初始账户和密码设置完成后进入:github生成token生成tokensettings -> Developer settings -> Personal access tokens 点击 Generate new tokengithub配置Jenkins添加webhook仓库 --> setting -->Webhooks --> Add webhook --> 输入刚刚部署Jenkins的服务器的IPIP地址后加上/github-webhook/Jenkins配置github(中文版Jenkins)安装GitHub plugin(直接搜索此名称) 系统管理-->插件管理-->可选插件直接安装Github Plugin, jenkins会自动帮你解决其他插件的依赖,直接安装该插件Jenkins会自动帮你安装plain-credentials 、Git 、 credentials 、 github-api配置GitHub Plugin 系统管理 --> 系统设置 --> GitHub --> GitHub服务器添加github生成的token点击jenkins按钮,弹出画面,输入信息,点击添加。选择添加的凭证,进行测试链接
偶然?总是?在配置 源码管理的时候使用https 进行代码的下载配置的是用户名和密码但是在执行构建的时候,总是会报错 443,但是偶尔也会有几次成功下载的,所以就很奇怪!!!!!!!!!!fatal: unable to access 'https://github.com/xxx': OpenSSL SSL_connect: SSL_ERROR_SYSCALL in connection to github.com:443永久解决:配置SSH使用Docker安装的Jenkins!!! 非docker安装的,忽略 第一步:进入容器1. 进入容器[root@iZ2zeblcb2evknzc1xbhunZ ~]# docker exec -it 容器ID /bin/bash2. 生成密钥bash-5.1# ssh-keygen -t rsa -b 4096 -C "GitHub邮箱"3. 查看公钥并配置GitHub查看cat /root/.ssh/id_rsa.pubGitHub配置https://github.com/settings/ssh/new查看私钥并配置项目查看私钥bash-5.1# cat /root/.ssh/id_rsa使用git@git.com 进行管理添加私钥凭证
系列文章Promise源码解密-PromisesA+标准Promise源码解密-同步版Promise源码解密-异步版Promise源码解密-then的链式调用Promise源码解密-catch/resolve/reject/race创作不易 拒绝白嫖 点个赞呗 关注专栏 Promise源码解密,带你走进Promise的深处!!!catch - 特殊的then方法,只有onRejectd使用let t = new MyPromise(function (resolve, reject) { console.log(somedata); //此处的somedata未定义 }); t.catch(function (reason) { console.log('rejected'); console.log(reason); }); let t = new MyPromise(function (resolve, reject) { //做一些异步操作 reject("2"); //此处的somedata未定义 }) t.catch(function (reason) { console.log('rejected'); console.log(reason); }); 实现catch(fn){ return this.then(null,fn) }resolve -返回一个成功的promise挂载在类本身,静态方法,由类直接调用MyPromise.resolve = (param) => { // 如果是promise的话直接返回 if (param instanceof MyPromise) { return param; } // 否则 return new MyPromise((resolve, reject) => { // 如果是一个then函数的话直接 if (param && typeof param === 'object' && typeof param.then === 'function') { setTimeout(() => { param.then(resolve, reject); }); } else { // 普通值直接resolve resolve(param); } }); }reject 返回一个失败的promise挂载在类本身,静态方法,由类直接调用MyPromise.reject = reason => new Promise((resolve,reject)=> reject(reason))race 执行多个操作Promise.race([p1, p2, p3])里面哪个结果获得的快,就返回那个结果,不管结果本身是成功状态还是失败状态 。MyPromise.race = promises => new Promise((resolve, reject) => promises.forEach(pro => pro.then(resolve, reject)) )all 执行所有,最终返回一个promise,全部成功返回成功的数组,一个失败就返回失败的结果,MyPromise.all = (promises) => { return new MyPromise((resolve, reject) => { let result = [] // 用来计数,确定执行了几个 let index = 0 // 如果没有,直接返回空数据 if (promises.length === 0) { resolve(result); return ; } for (let i = 0; i < promises.length; i++) { MyPromise.resolve(promises[i]).then(res=>{ result[i] = res index++ // 全部执行返回结果 if (index === promises.length) { resolve(result) } },error=>{ reject(error) }) } }) }race 执行全部,和all不同的是,返回第一个成功的结果,否则返回第一个失败的结果MyPromise.race = function (promises) { return new Promise((resolve, reject) => { if (promises.length === 0) { return; } else { for (let i = 0; i < promises.length; i++) { Promise.resolve(promises[i]).then((data) => { resolve(data); return; }, (err) => { reject(err); return; }); } } }); }
系列文章Promise源码解密-PromisesA+标准Promise源码解密-同步版Promise源码解密-异步版Promise源码解密-then的链式调用Promise源码解密-catch/resolve/reject/race创作不易 拒绝白嫖 点个赞呗 关注专栏 Promise源码解密,带你走进Promise的深处!!!then的用法通过return 给下一个then传值,成功/失败的返回值,最后都是传到下一个then的成功会回调let t = new Promise((resolve, reject) => { console.log(a) // 执行console会报错,最终只会执行reject }) t.then((res)=>{ return res },error=>{ return error }).then( (res) => { console.log(res.toString(),'res===='); // ReferenceError: a is not defined res==== }, (error) => { console.log(error); } );then中的onFulfilled/onReject 是可选的, 下面的例子,第一个then没有return值,但是第二个then也可以接受到值,最终输出 then 回调可选。let t = new Promise((resolve, reject) => { resolve('then 回调可选') }) t.then().then( (res) => { console.log(res); }, (error) => { console.log(error); } );实例不可 循环引用,报错 : Chaining cycle detected for promise #let p = new Promise((resolve, reject) => { resolve('不可循环引用') }) var p2=p.then(()=>{ return p2 // 返回的值还是p2 })完整代码// 定义状态常量 const STATUS_PENDING = "pending"; const STATUS_FULFILLED = "fulfilled"; const STATUS_REJECTED = "rejected"; function resolvePromise(promise2, x, resolve, reject) { // 用来保存是否已经reject或者resolve过 let called if (promise2 === x) { throw new TypeError('Chaining cycle detected for promise') } // 如果是函数或者object的话先默认是promise if (x != null && (typeof x === 'object' || typeof x === 'function')) { try { let then = x.then // 如果then是函数的话 if (typeof then === 'function') { // 为啥不直接x.then() // 因为then已经判断过是不是function,但是x.then没有判断过 // 就让then执行 第一个参数是this 后面是成功的回调 和 失败的回调 // 这里的y是啥,如果x是promsie的话,那么y就是x中的resolve/reject的值 then.call(x, y => { // 成功和失败只能调用一个 if (called) return; called = true; console.log(y, 'yyyyyyyyyyyy') // resolve的结果依旧是promise 那就继续解析 resolvePromise(promise2, y, resolve, reject); }, err => { // 成功和失败只能调用一个 if (called) return; called = true; reject(err); }) } else { resolve(x); // 如果不是函数,那就直接返回结果 } } catch (error) { // 成功和失败只能调用一个 if (called) return; called = true; // 没有then 不是函数也不是普通值 reject(error) } } else { // x 是一个普通值 resolve(x) } } class MyPromise { // 接收一个 执行器 // new Promise的时候,执行器立即执行, // 执行的时候根据指定函数执行 // 并且程序报错的情况下 constructor(executor) { this.status = STATUS_PENDING; this.value = undefined; this.reason = undefined; // 这里的两个数据,相当于订阅者的篮子,then相当于订阅者,接收到发布者的函数,保存在篮子里 this.onFulfilledCallBacks = []; this.onRejectCallBacks = []; try { // 这里将传入的resolve和reject变为类中的调用的话。 // (resolve, reject) => { // resolve("then链式调用");=>this.resolve(then链式调用) // } executor(this.resolve, this.reject); } catch (error) { // 报错的话直接将错误原因作为reason this.reject(error); } } // 这里为啥使用箭头函数而不是resolve(){} // 这是因为上面的executor调用的时候,resolve中的this其实是undefined // executor单独调用了resolve/reject 这时,这两个方法存在于执行是的环境,this不再指向实例 // 箭头函数内部的this总是指向定义时所在的对象 resolve = (value) => { // 判断状态是不是 if (this.status === STATUS_PENDING) { console.log("执行resolve"); // 这里接收传进来的结果 this.value = value; this.status = STATUS_FULFILLED; this.onFulfilledCallBacks.forEach((fn) => { fn(); }); } }; reject = (reason) => { if (this.status === STATUS_PENDING) { console.log("执行reject"); // 这里接收传进来的错误的结果 this.reason = reason; this.status = STATUS_REJECTED; // 这里相当于发布的动作 this.onRejectCallBacks.forEach((fn) => { fn(); }); } }; then(onFulfilled, onReject) { onFulfilled = typeof onFulfilled === "function" ? onFulfilled : (value) => value; onReject = typeof onReject === "function" ? onReject : (reason) => reason; console.log("执行then时的状态: ", this.status); let promise2 = new MyPromise((resolve, reject) => { if (this.status === STATUS_FULFILLED) { // 这个地方使用settimeout的目的是获取到promise2。因为setTimeout是异步的, // 会等到赋值给promise2结束后才执行, // 这里的resolvePromise的作用是为了区分x是普通值还是新的promise还是函数 // 如果直接resolve(x)的话会导致,输出的是[object Object] res====,并不是想要的值 setTimeout(() => { // 这里try进行了捕获异常,在最外面的executor不是进行了捕获了? // 这是因为异步里面的方法不会被最外层的那个捕获到 try { console.log("执行 onFulfilled"); // 这里的x是啥? 是then中回调的return的返回值 let x = onFulfilled(this.value); resolvePromise(promise2, x, resolve, reject); } catch (e) { reject(e); } }, 0); } if (this.status === STATUS_REJECTED) { setTimeout(() => { try { console.log("执行 onReject"); let x = onReject(this.reason); resolvePromise(promise2, x, resolve, reject); } catch (e) { reject(e); } }, 0); } if (this.status === STATUS_PENDING) { this.onFulfilledCallBacks.push(() => setTimeout(() => { try { let x = onFulfilled(this.value); resolvePromise(promise2, x, resolve, reject); } catch (e) { reject(e); } }, 0) ); this.onRejectCallBacks.push(() => setTimeout(() => { try { let x = onRejected(this.reason); resolvePromise(promise2, x, resolve, reject); } catch (e) { reject(e); } }, 0) ); } }); return promise2; } } // 下面的函数相当于发布者 let t = new MyPromise((resolve, reject) => { // 指定执行哪个,resolve和reject最终只会执行一个 // console.log(a) // 执行console会报错,最终只会执行reject // // resolve("res") // reject('reject') // setTimeout(() => { resolve("then链式调用"); // }, 1000) }); t.then(() => { return new MyPromise((resolve) => { console.log(2); setTimeout(() => { resolve(3); }, 3000); }); }).then( (res) => { console.log(res.toString(), "res===="); }, (error) => { console.log(error); } );
创作不易 拒绝白嫖 点个赞呗router设置为下,即可mode: ‘hash’,
是什么?git 地址: vue-grid-layout官方 demo代码在线演示常用参数解析GridLayout参数含义数据类型colNum将一行分为多少块数字 默认 12rowHeight行高数字 默认是单位是 pxisDraggable是否可以拖拽booleanisResizable是否可以改变大小booleanresponsive是否是响应式的booleanGridItem参数含义类型iid类型不限x第几列数字y第几行数字w占几块数字h高度 ,最后算出的元素高度是 h*rowHeight数字主要代码定义一个默认的布局var testLayout = [ {x: 0,y: 0,w: 6,h: 5,i: "0",component: "test1"},//0列0行 宽为5块,高为5*rowHeight {x: 6, y: 0, w: 6, h: 5, i: "1", component: "test2" },// 列为6(因为上一块的宽度是6) {x: 0,y: 5,w: 12,h: 10,i: "2",component: "test3"},//自己算一算吧 {x: 0,y: 15,w: 12,h: 10,i: "3",component: "test4"} ];生成布局// 最外大的grid,绑定了testLayout的值,这样testLayout 会随着用户的拖拽放大缩小改变 // 可以参考官方的实例 <grid-layout :layout.sync="testLayout" :col-num="12" :row-height="55" :is-draggable="draggable" :is-resizable="resizable" :auto-size="true" :responsive="responsive" > // 遍历testLayout生成item <grid-item v-for="item in testLayout" :x="item.x" :y="item.y" :w="item.w" :h="item.h" :i="item.i" :key="item.key" > <div class="assistor"> // 定义一个关闭按钮实现删除当前的 <div class="close-icon" @click="deleteComponent(item.i)"> <i class="el-icon-close"></i> </div> <h4 style="margin-bottom:10px">{{item.title}}</h4> // 这里使用component来显示组件。 <component :is="item.component" style="padding-bottom:20px"></component> </div> </grid-item> </grid-layout>css 样式定义整个布局的背景颜色.vue-grid-layout { position: relative; background: #fff; }定义每一个 item 的样式.vue-grid-item{ } GridItem 内部元素的样式 这里在 grid-item 内部加入一个 assistor,是因为如果 grid-item 内部元素的大小过大会出现滚动条 这里将 border 加在 assistor 上, 当然你也可以加在.vue-grid-item 上,但是如果你需要动态的增加组件的话,在增加的时候 boder 会加不上。.assistor { height: 100%; overflow-y: scroll; padding: 10px; border: 1px solid rgb(224, 219, 219); }增加一个关闭的按钮.assistor { height: 100%; overflow-y: scroll; padding: 10px; border: 1px solid rgb(224, 219, 219); }动态增减的实现思路其实就是对 layout 进行操作 最简单的加法,直接占满第一行this.testLayout.push({ x: 0, y: 0, w: 12, h: 5, i: this.layout.length, name: "test5" });减法的话,直接根据传进来的 id 删除即可deleteComponent(id){ this.testLayout = this.testLayout.filter( item =>item.id===id ); } 数据库直接将 testLayout 存入数据库即可。
<div> <div v-for="(item,index) in levelList" :key="item.path" style="display:inline"> // 如果是最后一个的话 <span v-if="index==levelList.length-1">{{ item.meta.title}}</span> // 如果不是最后一个的话 <a v-else style="color:black" @click.prevent="handleLink(item)">{{ item.meta.title }}></a> </div> </div> methods: { getBreadcrumb() { // 这里做一个筛选,如果有title,则进行显示 let matched = this.$route.matched.filter( item => item.meta && item.meta.title ); // 这里是为了将首页插入到面包屑中 const first = matched[0]; if (!this.isindex(first)) { matched = [{ path: "/admin/index", meta: { title: "首页" } }].concat( matched ); } // 这里把路由信息加入到数组中 this.levelList = matched.filter( item => item.meta && item.meta.title && item.meta.breadcrumb !== false ); }, isindex(route) { const name = route && route.name; if (!name) { return false; } return name.trim() === "index"; },
是什么ES5提供的数组的方法。 reduce() 方法接收一个函数作为回调函数(accumulator),数组中的每个值(从左到右)开始缩减(其实就是从左往右开始对每个数执行回调函数),最终为一个值。PS: 回调函数的返回结果类型和传入的初始值相同语法以及参数arr.reduce( callback(accumulator, currentValue,index ,array ) ,initialValue )initialValue 可选如果有的话则作为,第一次调用 callback函数时的第一个参数的值。 如果没有提供初始值,callback则使用数组的第一个元素,作为第一次调用的初始值。 在没有初始值的空数组上调用 reduce 将报错。accumulator默认传入上一次调用回调函数的的返回值。 初始值: initialValue存在的话,则是initialValue 若没有则是数组的第一个元素currentValue数组中正在处理的元素。index 可选数组中正在处理的当前元素的索引。 如果提供了initialValue,则起始索引号为0,否则从索引1起始。array可选调用reduce()的数组一个小小的例子例1 无initialValuevar arr = [1, 2, 3, 4, 5]; sum = arr.reduce(function(result, cur, index, arr) { console.log(result, cur, index,arr); return result+ cur; }) console.log(sum) // 最后的结果是15resultcurindexarr第1次121[1, 2, 3, 4, 5]第2次332[1, 2, 3, 4, 5]第3次643[1, 2, 3, 4, 5]第4次1054[1, 2, 3, 4, 5]例2 有initialValue 传入10var arr = [1, 2, 3, 4, 5]; sum = arr.reduce(function(result, cur, index, arr) { console.log(result, cur, index,arr); return result+ cur; },10) console.log(sum) // 最后的结果是25resultcurindexarr第1次1010[1, 2, 3, 4, 5]第2次1121[1, 2, 3, 4, 5]第3次1332[1, 2, 3, 4, 5]第4次1643[1, 2, 3, 4, 5]第5次2054[1, 2, 3, 4, 5]回调函数的返回值上面的例子返回的都是一个整型数字,如果希望返回其他类型的数据呢?这个就跟accumulator的初始值有关系了。 下面的例子我们传入的是一个object {sum: 0}var items = [0,1,2,3,4]; var reducer = function add(sumT, item) { console.log(sumT) sumT.sum = sumT.sum + item; return sumT; }; var total = items.reduce(reducer, {sum: 0}); console.log(total); // {sum:1130}运行结果 {sum: 0} {sum: 1} {sum: 3} {sum: 6} {sum: 10}reduce()的应用1. 数组扁平化递归+reducelet arr = [1, 2, '3js', [4, 5, [6], [7, 8, [9, 10, 11], null, 'abc'], {age: 12}, [13, 14]], '[]']; function flatten(arr) { if(Array.isArray(arr)) { return arr.reduce((prev, cur) => { // 如果遍历的当前项是数组,递归调用flatten return Array.isArray(cur) ? prev.concat(flatten(cur)) : prev.concat(cur) }, []) } else { throw new Error(' 当前参数不是数组') } } console.log(flatten(arr));PS:这里的throw new Error只是用来判断一开始的arr,这是因为在递归只传入数组。
module是什么store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割:新建目录以及文件在store目录下新建文件夹,modules文件夹(名字随意)在modules文件夹下新建module1.js以及module2.jsmodules1.jsconst module1 = { state: { moudle1Value: 'module1-value', }, mutations: { changeModule1(state, newValue) { state.moudle1 = newValue }, }, getters: { getModules1(state) { return state.moudle1 } }, actions: { useActionChangeModule1({ commit }, newValue) { commit('changeModule1', newValue) }, } } export default module1modules2.jsconst state = { moudle2Value: 'module2-value', } const mutations = { changeModule2(state, newValue) { state.moudle2 = newValue }, } const getters = { getModule2(state) { return state.moudle2 } } const actions = { useActionChangeModule2({ commit }, newValue) { commit('changeModule2', newValue) }, } export default { state, mutations, actions, getters }index.jsimport Vue from "vue" import Vuex from "vuex" import module1 from "./modules/module1" import module2 from "./modules/module2" Vue.use(Vuex) const store = new Vuex.Store({ modules: { module1, module2 }, }) export default store;使用获取state computed: { ...mapState({ module1: state => state.module1.moudle1Value, module2: state => state.module2.moudle2Value, }), },获取gettercomputed: { getModules1() { return this.$store.getters.getModules1; }. ...mapGetters(["getModules1"]) },commit调用 changeModule1() { this.$store.commit("changeModule1", "new module 1"); }, ...mapMutations(["changeModule1"])命名空间为什么要有命名空间vuex允许不同模块有重名的函数, 比如: this.$store.commit(“changeModule1”, “new module 1”);如果这这里的modules1和modules2模块都 有changeModule1这个函数,那么在commit的时候会导致,两个模块的这个重名函数都会调用。 所以都会命名空间来解决重名函数。 写法如下const module1 ={ namespaced: true, ...... }获取getter...mapGetters("module1", ["getModules1"]) // 映射为 `this.$store.getters.common.getToken` // // 方式2 getModules1() { return this.$store.getters.module1.getModules1; }commit调用changeModule1() { this.$store.commit("module1/changeModule1", "new module 1"); }, ...mapMutations("module1", [ "changeModule1" // 将 `this.getTokenData()` 映射为 `this.$store.dispatch('common/getTokenData')` ])dispath调用changeModule1() { this.$store.commit("module1/useActionChangeModule1", "new module 1"); }, ...mapActions("module1", [ "useActionChangeModule1" ]) }
Action是什么Action 提交的是 mutation,而不是直接变更状态。当然Action也获取state,getterAction 可以包含任意异步操作。Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,因此你可以调用 context.commit 提交一个 mutation,或者通过 context.state 和 context.getters 来获取 state 和 getters。const store = new Vuex.Store({ state: { name: "old name", age: 18, sex: "女", }, mutations: { changName(state) { state.name = "newName" }, addAge(state, num) { state.age += num }, changSex(state) { state.sex = state.age + "男" } }, actions: { useActionToChangName(context) { // 这里的context也可以写成{commit,state} context.commit('changName') context.commit('addAge',10) } } })使用Dispatch来触发事件methods: { changeNameAndAge() { this.$store.dispatch({ type: "useActionToChangName" }); }, 或者 changeNameAndAge() { this.$store.dispatch ("useActionToChangName" ); }, }mapActions引入import { mapActions } from 'vuex'使用 methods: { ...mapActions([ 'useActionToChangName', // 将 `this.useActionToChangName()` 映射为 `this.$store.dispatch('useActionToChangName')` // `mapActions` 也支持载荷: 'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.dispatch('incrementBy', amount)` ]), ...mapActions({ add: 'useActionToChangName' // 将 `this.add()` 映射为 `this.$store.dispatch('useActionToChangName')` }) }
!!! 这个例子可以先忽略mutations初始化一个stateconst store = new Vuex.Store({ state: { name: "old name", age: 18, sex: "女", }, mutations: { changName(state) { state.name = "newName" }, addAge(state) { state.age += 1 }, changSex(state) { state.sex = state.age + "男" } } })在组件中使用直接赋值给data中的变量这种情况会导致name直接仅仅接受了一个值,即使点击了我要改名,name也不会改变。2 使用computed进行接收computed会进行监听,所以只要this.$store.state.age改变,age就会改变。这也是官方推荐的写法直接在页面调用显示因为一个store是一个vue实例,所以数据变了,页面数据也会跟着变<template> <div> <button @click="changeName">我要改名</button> <button @click="addAge">我长大啦</button> <button @click="changeName">我要改名</button> <p>{{this.$store.state.sex}}</p> <p>{{name}}</p> <p>{{age}}</p> </div> </template> <script> export default { name: "Home", data() { return { name: this.$store.state.name }; }, computed: { age() { return this.$store.state.age; } }, methods: { changeName() { this.$store.commit("changName"); }, addAge() { this.$store.commit("addAge"); }, changSex() { this.$store.commit("changSex"); } } }; </script>mapState 辅助函数在上面,我们推荐把值放在computed中,这样会导致一个问题,我们这里有三个变量,如果都按照上面的写法,会显得代码特别繁杂。 所以vuex提供了一个辅助函数mapState.这个函数会返回一个对象先在组件中引入mapstateimport { mapState } from 'vuex'具体的写法 三种写法请参考代码computed: mapState({ // 箭头函数可使代码更简练 name: state => state.name, // 传字符串参数 'age' 等同于 `state => state.age` age: 'age', // 为了能够使用 `this` 获取局部状态,必须使用常规函数 countPlusLocalState (state) { return state.name+ data中定义的变量 } })注意当映射的计算属性的名称与 state 的子节点名称相同时,我们也可以给 mapState 传一个字符串数组。 注意这里方括号,最外层的{}可以省略computed: {mapState([ // 映射 this.count 为 store.state.count "name", "age", "sex" ]),}因为mapState返回一个对象,所以可以使用展开运算符 computed: { ...mapState({ name: "name", age: "age", sex: "sex" }) },
使用computed接收state的值computed: { getCount() { return this.$store.state.count; } }使用watch监听computedwatch: { getCount(val) { this.count= val; } }
是什么网页的一个页面占据一屏的宽高,多个页面上下或者左右拼接在一起。当滑动鼠标滚轮,或点击导航按钮时,可以平滑到对应的页面。此次只实现鼠标滚动实现原理使用mousewheel , DOMMouseScroll(火狐用)监听鼠标滚动事件,当鼠标上下的滚动的时候,当前的页面transformY(屏高)或者transformX(屏宽)代码实现HTML<template> <div class="fullPage" ref="fullPage"> <div class="fullPageContainer" ref="fullPageContainer" @mousewheel="mouseWheelHandle" //监听鼠标事件 @DOMMouseScroll="mouseWheelHandle" // 监听鼠标事件 > <div class="section section1">1</div> <div class="section section2">2</div> <div class="section section3">3</div> <div class="section section4">4</div> </div> </div> </template>JS<script> export default { name: "Home", data() { return { fullpage: { current: 1, // 当前的页面编号 isScrolling: false, // 是否在滚动,是为了防止滚动多页,需要通过一个变量来控制是否滚动 deltaY: 0 // 返回鼠标滚轮的垂直滚动量,保存的鼠标滚动事件的deleteY,用来判断是往下还是往上滚 } }; }, methods: { next() { // 往下切换 let len = 4; // 页面的个数 if (this.fullpage.current + 1 <= len) { // 如果当前页面编号+1 小于总个数,则可以执行向下滑动 this.fullpage.current += 1; // 页面+1 this.move(this.fullpage.current); // 执行切换 } }, pre() {// 往上切换 if (this.fullpage.current - 1 > 0) { // 如果当前页面编号-1 大于0,则可以执行向下滑动 this.fullpage.current -= 1;// 页面+1 this.move(this.fullpage.current);// 执行切换 } }, move(index) { this.fullpage.isScrolling = true; // 为了防止滚动多页,需要通过一个变量来控制是否滚动 this.directToMove(index); //执行滚动 setTimeout(() => { //这里的动画是1s执行完,使用setTimeout延迟1s后解锁 this.fullpage.isScrolling = false; }, 1010); }, directToMove(index) { let height = this.$refs["fullPage"].clientHeight; //获取屏幕的宽度 let scrollPage = this.$refs["fullPageContainer"]; // 获取执行tarnsform的元素 let scrollHeight; // 计算滚动的告诉,是往上滚还往下滚 scrollHeight= -(index - 1) * height + "px"; scrollPage.style.transform = `translateY(${scrollHeight})`; this.fullpage.current = index; }, mouseWheelHandle(event) { // 监听鼠标监听 // 添加冒泡阻止 let evt = event || window.event; if (evt.stopPropagation) { evt.stopPropagation(); } else { evt.returnValue = false; } if (this.fullpage.isScrolling) { // 判断是否可以滚动 return false; } let e = event.originalEvent || event; this.fullpage.deltaY = e.deltaY || e.detail; // Firefox使用detail if (this.fullpage.deltaY > 0) { this.next(); } else if (this.fullpage.deltaY < 0) { this.pre(); } } } }; </script>CSS<style scoped> .fullPage{ height: 100%;//一定要设置,保证占满 overflow: hidden;//一定要设置,多余的先隐藏 background-color: rgb(189, 211, 186); } .fullPageContainer{ width: 100%; height: 100%; transition: all linear 0.5s; } .section { width: 100%; height: 100%; background-position: center center; background-repeat: no-repeat; } .section1 { background-color: rgb(189, 211, 186); background: url("./assets/intro-bg.jpg"); } .section1 .secction1-content { color: #fff; text-align: center; position: absolute; top: 40%; right: 0; left: 0; } .secction1-content h1 { font-size: 40px; padding-bottom: 30px; } .secction1-content p { font-size: 20px; } .section2 { background-color: rgb(44, 48, 43); } .section3 { background-color: rgb(116, 104, 109); } .section4 { background-color: rgb(201, 202, 157); } </style>
项目地址,欢迎批评指正,随手Star哟Electron-vue实战-每日清单—01Electron-vue的使用Electron-vue实战-每日清单—02Electron-vue的目录详解Electron-vue实战-每日清单—03功能介绍与环境搭建是什么每日清单其实就是一个to-do-list功能(包括已完成) 登录 我的清单添加待作删除待作修改待作 已完成 垃圾箱 数据统计 系统设置开机自启动系统通知修改用户名密码技术支持前端element-ui本地数据持久化存储lowdb 数据库 node 数据读写环境搭建Electron-vue安装使用Element-ui 详见官方网站lowdbnpm install lowdb官方文档中推荐 lodash-id ,这个东西其实就是为每一个新增 的数 据自动加上一个唯一表示的id字段,和mysql等数据库的自增主键类似。npm install lodash-idfs-extra lowdb本质上就是通过fs来读写JSON文件实现的,node也内置了fs模块进行文件读写,但是为了读写更方便,使用fs-extranpm install fs-extra
项目地址,欢迎批评指正,随手Star哟Electron-vue实战-每日清单—01Electron-vue的使用Electron-vue实战-每日清单—02Electron-vue的目录详解Electron-vue实战-每日清单—03功能介绍与环境搭建my-project├─ .electron-vue│ └─ build.js打包时调用,在package.json中的script里的build命令“build”: “node .electron-vue/build.js && electron-builder”,│ └─ dev-client.js│ └─ dev-runner.js运行时的配置│ └─ webpack.main.config.js针对 electron 的 main 进程│ └─ webpack.renderer.config.js针对 electron 的 renderer 进程│ └─ webpack.web.config.js针对为浏览器构建你的 renderer 进程的源代码│ └─ icons/├─ dist打包之后的目录│ ├─ electron/│ └─ web/├─ node_modules/项目所需的依赖├─ src│ ├─ main主进程目录│ │ ├─ index.dev.js会安装加载vue-devtools│ │ └─ index.jsmain进程的主要方法都在这里写│ ├─ renderer渲染进程,也就是vue所在│ │ ├─ components/定义vue组件│ │ ├─ router/vue-router的路由│ │ ├─ store/vuex│ │ ├─ App.vue│ │ └─ main.jsvue中的main.js│ └─ index.ejs相当于index.html ,因为webpack会将他打包成index.html├─ static/静态资源├─ test│ ├─ e2e│ │ ├─ specs/│ │ ├─ index.js│ │ └─ utils.js│ ├─ unit│ │ ├─ specs/│ │ ├─ index.js│ │ └─ karma.config.js│ └─ .eslintrc├─ .babelrc├─ .eslintignore├─ .eslintrc.jseslint的配置文件,如果你使用eslint的会自动生成他├─ .gitignore配置上传git忽略的文件├─ package.json定义了这个项目所需要的各种模块,以及项目的配置信息(比如名称、版本、许可证等元数据)└─ README.md执行npm run dev或 yarn dev 会现在package.json中找到“dev”: “node .electron-vue/dev-runner.js”,执行命令会先找到 .electron-vue/dev-runner.js 这个js中 的 startMain()函数会找到…/src/main/index.dev.js,而在这个js中会require(’./index’),会找到同级目录下的jndex.js 从而创建窗口
使用electron自带的自启动方法主进程// 获取可执行文件位置 const ex=process.execPath; // 定义事件,渲染进程中直接使用 // 开启 开机自启动 ipcMain.on('openAutoStart',()=>{ console.log('updateExe',ex) app.setLoginItemSettings({ openAtLogin: true, path: ex, args: [] }); }); // 关闭 开机自启动 ipcMain.on('closeAutoStart',()=>{ app.setLoginItemSettings({ openAtLogin: false, path: ex, args: [] }); })渲染进程ipcRenderer.send('openAutoStart') ipcRenderer.send('closeAutoStart')
约定:本地图片放在assets目录下具体如下:----assets -----------img/*.png ----layouts -----------test.vue情况1. data中定义了图片的地址注意点:使用v-bind绑定必须使用require引入图片路径<ul> <li v-for="(item,index) in data.imgList" :key="index"> <img :src="item.src" /> </li> </ul> data(){ return { imgList:[ { src: require('../assets/img/1.png') }, ] } } 情况2. 在img标签的src属性中动态拼接图片地址注意点:必须使用require引入图片路径这个是动态拼接地址,可以实现随机图片<ul> <li v-for="(item,index) in 10 " :key="index"> <img :src="require('../assets/img/' + (index+1) + '.png')" /> </li> </ul>
1. 是什么parseInt(string, radix) 函数解析一个字符串,返回一个10进制的整数或者NaN1.1 参数string是一个字符串,例如”123“,‘0xF’,radix介于2-36之间的数,表示string字符串的进制进制,如10进制。 其中radix可以省略,默认为10进制。1.2 举例parseInt('11',2) //"11"这个字符串是2进制的返回3 parseInt('11',10) //"11"这个字符串是10进制的返回11 parseInt('0xF',16) //"0xF"这个字符串是16进制的返回152 注意事项2.1 如果第一个字符不能被转换成数字,parseInt返回NaN。parseInt("syl", 8); // 根本就不是数值,输出NaN parseInt("5", 2); // 除了“0、1”外,其它数字都不是有效二进制数字,输出NaN2.2 在基数为 undefined,或者基数为 0 或者没有指定的情况下,JavaScript 作如下处理:1. 如果字符串 string 以"0x"或者"0X"开头, 则基数是16 (16进制). 2. 如果字符串 string 以"0"开头, 基数是8(八进制)或者10(十进制), 那么具体是哪个基数由实现环境决定。 ECMAScript 5 规定使用10,但是并不是所有的浏览器都遵循这个规定。 因此,永远都要明确给出radix参数的值。 3. 如果字符串 string 以其它任何值开头,则基数是10 (十进制)。2.3 如果字符串中间不属于radix参数所指定的基数中的字符那么该字符和其后的字符都将被忽略。开头和结尾的空白符允许存在parseInt("22 3 2019") //出现空格,忽略,输出22 parseInt(“2.366”)= 2 //出现.,忽略,输出22.4 带有e的字符串请谨慎处理parseInt("6.022e23", 10); // 返回 6 parseInt(6.022e2, 10); // 返回 602
一:清空表数据并重置id:truncate table table_name;注意:truncate 一次性地从表中删除所有的数据且删除行是不能恢复的。并且在删除的过程中不会激活与表有关的删除触发器。执行速度快。二:delete from table_name; alter table table_name auto_increment= 1;
1. 回调函数是什么回调函数就是函数A执行完之后,有一个函数B用来做其他的事情。 一般是将函数B,作为参数,传入到函数A中。2.实现方法2.1 使用命名函数function A(callback){ console.log("A执行") callback(); } function B(){ //B是回调函数 console.log("B执行"); } // 使用 A(B); //这里的B没有括号。 // 输出 A执行 B执行2.2 匿名回调函数function A(num1, num2, callback){ var sum = num1 + num2; callback(sum); } // 使用 A(1, 2, function(sum){ console.log(sum); }); // 输出 33.使用含有this对象的回调函数var obj={ name:"", setName:function(name){ this.name=name; } } function A(name,callback){ callback(name); } //调用 A('syl',obj.setName); //检测 window.name; 输出:"syl" //检测 obj.name; 输出:""本来我们是希望obj的name是“syl”,但是却没有,这是因为A函数属于全局环境,导致name属性的也属于全局环境。所以我们需改变name的环境,即改变this的环境。var obj={ name:"", setName:function(name){ this.name=name; } } function A(name,callback,obj){ callback.call(obj,name); } //调用 A('syl',obj.setName,obj); //检测 window.name; 输出:"" //检测 obj.name; 输出:"syl"一个很好的例子:比如爬楼梯,你要成功爬上1楼,才能爬2楼,然后三楼function floors(isSuccess,callback ){ if (isSuccess) { // 如果成功就执行回调函数 callback(); } } function pa1() { // 爬一楼 //todo: ... console.log('爬一楼'); return true; } function pa2() { //todo: ... console.log('爬二楼'); return true; } floors(pa1(),function() { floors(pa2(), function(){ floors(3, function(){ console.log('ok') }) }) }) 原文:https://blog.csdn.net/wangweiscsdn/article/details/84000826 半夏话前端 微信公众号 帮助更多人成长! 已关注
两者都是用来异步加载js文件,提高网页性能。1. async1.2 使用场景主要是不涉及操作DOM的事件,比如使用百度分析的脚本1.1 与html解析、DOMContentLoaded的关系情况1:HTML 还没有被解析完的时候,async脚本已经加载完了,那么 HTML 停止解析,去执行脚本,脚本执行完毕后触发DOMContentLoaded事件。情况2: HTML 解析完了之后,async脚本才加载完,然后再执行脚本,那么在HTML解析完毕、async脚本还没加载完的时候就触发DOMContentLoaded事件。1.3 综述无论html是否解析完成,立即执行脚本;无论有使用多少个async加载脚本,只要脚本下载完成,立即执行脚本。与<script>标签的顺序无关。2. defer2.1 使用场景操作DOM的脚本,为防止元素尚未加载完成,脚本找不到元素报错。2.2 html解析、DOMContentLoaded的关系情况1:HTML还没解析完成时,defer脚本已经加载完毕,那么defer脚本将等待HTML解析完成后再执行。defer脚本执行完毕后触发DOMContentLoaded事件。情况2: HTML解析完成时,defer脚本还没加载完毕,那么defer脚本继续加载,加载完成后直接执行,执行完毕后触发DOMContentLoaded事件。2.3 综述无论js文件是否下载完成,只有html解析完毕,才可以执行脚本;脚本执行的顺序与下载的完成时间无关,按照<script>脚本的位置,顺序执行。注: 图片来源网络。
1. DOM事件级别1.1. DOM0<button id="btn" type="button"></button> <script> var btn = document.getElementById('btn'); //添加事件 btn.onclick = function() { console.log(this.id)); //这里的this代表DOM对象 } //清理dom0 事件时,只需给该事件赋值为 null input.onclick = null </script>特点:DOM0级事件无法给一个事件添加多个处理函数1.2. DOM2 var dom = document.getElementById("id"); dom.addEventListener('click', a, false); function a() { alert(this.id);//id // this代表的是dom对象 } //移除事件 //传入的三个参数与添加事件完全相同。 dom.removeEventListener(('click', a, false)).参数说明:第一个参数是事件名,就是事件属性去掉on,第二个参数是事件处理函数,第三个参数是是否在事件捕获阶段执行。特点同一个事件处理函数可以绑定2次,一次用于事件捕获,一次用于事件冒泡。 var dom = document.getElementById("outestA"); dom.addEventListener('click', a, false); dom.addEventListener('click', a, true); function a() { alert(this.id);//outestA }如果绑定的是同一个事件处理函数,并且都是事件冒泡类型或者事件捕获类型,那么只能绑定一次,多次绑定仅调用一次。可以绑定多个不同的事件处理函数旧版本IE浏览器(IE8及一下) 需要使用attachEvent和detachEvent来添加和移除事件,传入两个参数第一个是事件属性(包含on),第二个是处理函数,不支持事件捕获所以没有第三个参数。 var dom = document.getElementById("id"); dom.attachEvent('onclick',a); function a() { alert(this.id);/**/undefined** // 这里的this是window对象 }1.3. Dom3DOM3级事件就是在DOM2基础上增加了更多的事件类型UI事件,当用户与页面上的元素交互时触发,如:load、scroll焦点事件,当元素获得或失去焦点时触发,如:blur、focus鼠标事件,当用户通过鼠标在页面执行操作时触发如:dbclick、mouseup滚轮事件,当使用鼠标滚轮或类似设备时触发,如:mousewheel文本事件,当在文档中输入文本时触发,如:textInput键盘事件,当用户通过键盘在页面上执行操作时触发,如:keydown、keypress合成事件,当为IME(输入法编辑器)输入字符时触发,如:compositionstart变动事件,当底层DOM结构发生变化时触发,如:DOMsubtreeModified注:DOM1标准中并没有定义事件相关的内容*2. DOM事件模型事件冒泡事件捕获3. DOM事件流有以下HTML结构<html> <body> <div> <span> 我是目标内容 </span> </div> </body> </html>事件捕获:window -> document -> html -> body -> div -> span -> 目标 事件冒泡:目标 -> span -> div -> body -> html -> document -> window3.1 冒泡实例: <div id="parent" class="parent"> <div id="child" class="child"> this is child </div> </div> (function(){ var child = document.getElementById('child'); child.addEventListener('click', function(click){ console.log('child'); } ,flase);//false或者不写,都是冒泡。 var parent = document.getElementById('parent'); parent.addEventListener('click', function(click){ console.log('parent'); } ,false); }()); 出现的情况:点击child元素,先打印child后打印parent;点击parent元素,只打印parent。3.1 捕获实例: <div id="parent" class="parent"> <div id="child" class="child"> this is child </div> </div> (function(){ var child = document.getElementById('child'); child.addEventListener('click', function(click){ console.log('child'); } ,true); var parent = document.getElementById('parent'); parent.addEventListener('click', function(click){ console.log('parent'); } ,true); }()); 出现的情况:点击child元素,先打印parent后打印child。点击parent元素,只打印parent。注:事件默认的处理阶段为冒泡阶段,可以把addEventListener第三个参数设置为true来让时间在捕获阶段被处理,4. event对象事件处理函数会回调一个参数event,代表当前事件对象。 event中常用的方法和属性:preventDefault 阻止默认行为,比如当点击submit按钮时候,可以采用此方法阻止表单提交。stopPropagation 停止事件冒泡,需要防止事件冒泡带来的负面影响的时候就要使用该方法。stopImmediatePropagation 阻止后续事件,该方法除了阻止事件冒泡外在当前事件被绑定多个处理程序的时候,后续的处理程序也会被阻止。currentTarget 此属性返回当前事件所绑定的对象。target 此属性返回当前触发事件的对象,注意target是触发事件的对象,是真正的事件源,同样以上面的HTML为例,给div绑定一个事件,点击带文字的span后,target是span,而currentTarget是div。应用:事件冒泡和target属性能做很多事情,比如事件委托<ul id="click"> <li>1</li> <li>2</li> <li>3</li> <li>4</li> </ul>如果想要实现点击每个li标签就能打印出文本内容,我们可以不用给每个li绑定事件,只需要利用事件冒泡即可var click = document.getElementById('click'); click.addEventListener('click', log, false); function log(e) { console.log(e.target.innerText); }5. 自定义事件除了系统内置的事件外,我们还可以自定义事件,由于平时使用的不多可能感觉会很高端,其实自定义事件并不复杂var myEvent = new Event('myEvent'); document.addEventListener('myEvent', log, false); function log() { console.log('hello event'); } document.dispatchEvent(myEvent);通过创建Event对象来创建事件,通过dispatchEvent函数派发事件。自定义事件可以绑定到任意DOM元素上,此处选择document只是为了演示方便。
一、classList的add()和remove()方法css样式 .new{ color: #FFD113; }html标签 <span class="old">首页</span>js代码 var arr = document.getElementsByTagName("span"); arr[i].classList.add("new"); /*添加样式*/ arr[j].classList.remove("new");/*删除样式*/二、字符串拼接 className var old= element.className; /*加上空格, 不然想查询"old",若原本有"older"的类名的就会有问题*/ old = " " + old + " "; /*查询类名中是否含有某个class*/ old.indexOf(" ClassName ") === -1 ? false : true;//同样的查询时也要带上空格*2 /*增加*/ 1. new=old+" new";//注意空格*1 2. new = old.concat(" ClassName");//注意空格*1 element.setAttribute("class", new); /*删除*/ new = old.replace(" ClassName "," ");//注意空格*3 element.setAttribute("class",new); /*修改*/ new = old.replace(" targetClassName "," yourClassName ");//注意空格*4 element.setAttribute("class",new );
原因js文件在head标签里产生的加载顺序问题导致的解决办法:1.可以body标签下引入js文件2.<script type=“text/javascript”>里面加个defer=true属性 注:defer 属性规定是否对脚本执行进行延迟,直到页面加载为止。
用法var sTop=document.body.scrollTop+document.documentElement.scrollTop; 或var heightTop = document.documentElement.scrollTop || document.body.scrollTop;完美的获取scrollTop 赋值短语 : var scrollTop = document.documentElement.scrollTop || window.pageYOffset || document.body.scrollTop;区别document.documentElement是整个文档节点树的根节点,在网页中即html标签;document.body是整个文档DOM节点树里的body节点,网页中即为body标签元素。 这两个值总会有一个恒为0浏览器支持IE6/7/8: document.documentElement.scrollTop; IE9及以上:document.documentElement.scrollTop; Safari: document.body.scrollTop; Firefox:者 document.documentElement.scrollTop ; Chrome:只有document.body.scrollTop;
是什么web服务器存储在你本地磁盘的一个小的文本文件cookie记录了你的用户名,密码,浏览的网页等属性Expires ,Max Age:都用来指定cookie的过期时间; 2. Expires在HTTP/1.0中定义。max-age在HTTP/1.1中才有定义; 3. Expires指定一个绝对的过期时间(GMT格式)。max-age 指定的是从文档被访问后的存活时间,这个时间是个相对值(比如:3600s),相对的是文档第一次被请求时服务器记录的Request_time(请求时间),Domain和PathDomain是域名,Path是路径,两者加起来就构成了 URL,Domain和Path一起来限制 cookie 能被哪些 URL 访问。sizecookie的大小SecureSecure选项用来设置cookie只在确保安全的请求中才会发送。当请求是HTTPS或者其他安全协议时,包含 Secure选项的 cookie 才能被发送至服务器。httpOnly设置cookie是否能通过 js 去访问客户端设置cookie方法:document.cookie=“name=123”;注意:document.cookie="name=syl; age=18"这样的话只有name生效,即每次只能设置一个。因此需要封装或者多次调用。 封装://设置cookies function setCookie(name,value,MyDay){ var ExDate = new Date(); ExDate.setDate(ExDate.getDate() + MyDay);//如果需要时间的话以这样获取。 document.cookie = name + "=" + value + ";expires=" + ExDate; } //获取cookies function getCookie(name){ //例如cookie是"username=abc; password=123" var arr = document.cookie.split('; ');//用“;”和空格来划分cookie for(var i = 0 ;i < arr.length ; i++){ var arr2 = arr[i].split("="); if(arr2[0] == name){ return arr2[1]; } } return "";//整个遍历完没找到,就返回空值 } //删除cookies function removeCookie(name){ setCookie(name, "1", -1)//第二个value值随便设个值,第三个值设为-1表示:已经过期。 }缺点每个特定域名下的cookie数量有限,E6或更低版本最多20个cookie,IE7及之后可以有50个cookie,firefox最多50个cookie;存储量太小,只有4KB;每次HTTP请求都会发送到服务端,影响获取资源的效率;安全性问题。如果cookie被人拦截了,那人就可以取得所有的session信息。即使加密也与事无补,因为拦截者并不需要知道cookie的意义,他只要原样转发cookie就可以达到目的了。;
解决方案安装mysqlclientpip install mysqlclient这是使用Mamp的解决方案 将host定位到mamp下的sock DATABASES = { ‘default’: { ‘ENGINE’: ‘django.db.backends.mysql’, ‘NAME’: ‘test’, ‘USER’: ‘test’, ‘PASSWORD’: ‘test’, ‘HOST’: ‘/Applications/MAMP/tmp/mysql/mysql.sock’, ‘PORT’: ‘’, }, }
Django 配置MySQL数据库在settings.py中配置 复制代码DATABASES = { ‘default’: { ‘ENGINE’: ‘django.db.backends.mysql’, # 数据库引擎 ‘NAME’: ‘database_name’, # 你要存储数据的库名,事先要创建之 ‘USER’: ‘root’, # 数据库用户名 ‘PASSWORD’: ‘1234’, # 密码 ‘HOST’: ‘localhost’, # 主机 ‘PORT’: ‘3306’, # 数据库使用的端口 } }Python3不支持MySQLdb,可用pymysql代替。 在项目文件夹下的_init_.py添加如下代码即可。import pymysql pymysql.install_as_MySQLdb()在Terminal中执行数据库迁移命令:python manage.py makemigrations python manage.py migrate
第三章分布式文件系统在物理结构上是由计算机集群中的多个节点构成的,这些节点分为两类:一类叫_;另一类叫_。(P43)主节点/名称节点,从节点/数据节点 HDFS采用抽象的块概念可以简化系统设计,适合数据备份,但不可以支持大规模文件存储。 错误 P46 在HDFS中,名称节点负责管理分布式文件系统的命名空间,保存了两个核心的数据结构,即_和_。(P46)FsImage,EditLog 分布式文件系统在物理结构上是由计算机集群中的多个节点构成的,这些节点分为两类:一类叫主节点,另一类叫从节点。HDFS在设计上采取了多种机制保证在硬件出错的环境中实现数据的完整性。总体而言,HDFS要实现以下目标:____。(P45) D (1)兼容廉价的硬件设备 (2)流数据读写 (3)大数据集 4)复杂的文件模型 5)强大的跨平台兼容性 A. (1)(2)(3)(4) B. 1)(2)(4)(5) C. 2)(3)(4)(5) D. 1)(2)(3)(5)HDFS特殊的设计,在实现上述优良特性的同时,也使得自身具有一些应用局限性,主要包括以下几个方面:_。(P45) AB 不适合低延迟数据访问 无法高效存储大量小文件 不支持单用户写入及任意修改文件 硬件设备昂贵 为了保证系统的容错性和可用性,HDFS采用了多副本方式对数据进行冗余存储,这种多副本方式具有以下几个优点:_。(P50)BCD 容易修改数据问题 加快数据传输速度 保证数据的可靠性 容易检查数据错误1.HDFS采用块的概念,默认的一个块大小是64MB。 ( ) (P46) √ 2.在HDFS的设计中,第二名称节点起到了名称节点的“检查点”和“热备份”的作用,因为有了第二名称节点的存在,当名称节点发生故障时,系统就不会丢失元数据信息。 ( ) (P48)× HDFS把硬件出错看成一种常态,设计了错误恢复机制。 P60 对第四章 填空 1.HBase是针对谷歌BigTable的开源实现,是一个高可靠、高性能、面向列、可伸缩的分布式数据库,主要用来存储非结构化和半结构化的松散数据。 P63 选择 2.BigTable是一个分布式存储系统,利用谷歌提出的_分布式并行计算模型来处理海量数据。 P63 MapReduce 3.HBase只有一个索引——_,通过巧妙的设计,HBase中的所有访问方法,或者通过行健访问,或者通过行健扫描,从而使得整个系统不会慢下来。 P65 行健 4.____是HBase中最核心的模块,负责维护分配给自己的Region,并响应用户的读写请求。 选择 P75 Region服务器判断 1.BigTable是一个分布式存储系统,使用谷歌分布式文件系统MapReduce作为底层数据存储。 错 P63 2.分布式数据库HBase的数据类型只有字符串。 对 P64 3.HBase操作不存在复杂的表与表之间的关系,只有简单的插入、查询、删除、清空等。 对 P64 4.在HBase中执行更新操作时,会在生成一个新版本之前删除数据旧的版本。 P65 错 5.HBase的系统架构中的客户端是指用户。 P74 错单选 1.当一个客户端从Zookeeper服务器上拿到-ROOT-表的地址以后,就可以通过__找到用户数据表所在的Region服务器,并直接访问该Region服务器获得数据。 A.一级寻址 B.二级寻址 C.三级寻址 D.四级寻址 P74 C多选 1.HBase的实现包括3个主要的功能组件:____。 A.库函数 B.一个Master主服务器 C.一个Region服务器 D.许多个Region服务器 ABD P71第五六章 下列选项中(B)不是NoSQL数据库的特点。 灵活的可扩展性 B.动态的数据迁移 C.与云计算紧密融合 D.灵活的数据模型 NoSQL的英文全称(Not only Structual Query Language)。 NoSQL的英文全称为 No Structual Query Language。× 关系数据库无法满足Web2.0的需求主要表现在哪几个方面(ACD) 无法满足海量数据的管理需求 无法满足数据完整性的需求 无法满足数据高并发性的需求 无法满足高可扩展性和高可用性的需求 与分布式对应的方式是(集中式) Hadoop属于开发运行环境中的运行环境。√ 为保证一致性,关系数据库遵守ACID模型,NoSQL数据库遵守BASE模型。√ NoSQL数据库的明显优势在于(BCD)。 实现数据完整性 支持超大规模数据存储 灵活的数据模型可以很好的支持Web2.0应用 具有强大的横向扩展能力 Web2.0网站系统通常要求严格的数据库事务。× NoSQL的四大类型为键值数据库、(列族数据库)、文档数据库、图数据库 下列选项中(C)不是文档数据库的优点。 性能好 B.灵活性高 C.统一的查询语法 D.数据结构灵活 NoSQL的三大基石包括(CAP、BASE、最终一致性)。 CAP中的C与CAID中的C的含义一样。× NewSQL这类数据库不仅具有NoSQL对海量数据的存储管理能力,还保持了传统数据库支持ACID和SQL等特性。√ 最终一致性根据更新数据后各进程访问到数据的时间和方式的不同,可以进行区别。下列说法正确的是(ABCD)。 因果一致性 “读己之所写”一致性 会话一致性 单调一致性 “软状态”是指(状态可以有一段时间不同步,具有一定的滞后性)。 云计算八大优势为按需服务、随时服务、通用性、(高可靠性)、极其廉价、超大规模、(虚拟化)、高扩展性。 云计算主要包括3种类型,即(IaaS、PaaS、SaaS)。 云计算可同时为众多用户提供服务。√ 下列关于云数据库的特点,错误的是(A)。 高可靠性 B.高可扩展性 C.采用多租形式 D.支持资源有效分布 关系数据库采用(关系数据)模型,NoSQL数据库采用(非关系数据)模型。 云数据库有专属与自己的数据模型。× UMP系统是低成本和高性能的MySQL数据库方案,关键模块采用Erlang语言实现。√ 下列为UMP系统架构设计遵循的原则的是(ABCD)。 保持单一的系统对外入口,并且为系统内部维护单一的资源池 保持单一故障,保证服务的高可用性 保证系统具有良好的可伸缩性,能够动态地增加、删减计算与存储节点 保证分配给用户的资源是弹性可伸缩的,资源之间相互隔离,保证应用和数据的安全 Mnesia是一个集中式数据库管理系统。× 下列选项不属于Zookeeper主要发挥的作用的是(D)。 作为全局的配置服务器 提供分布式锁 监视所有MySQL实例 支持透明的数据分片 UMP系统借助于()来实现集群内部的负载均衡。 Mnesia B.Zookeeper C.LVS D.Controller服务器 UMP系统功能为(容灾)、读写分离、资源管理、资源调度、(资源隔离)和数据安全。 UMP系统只为一个用户创建一个MySQL实例。× 资源池是为MySQL实例分配资源的基本单位。√ UMP系统采用哪两种资源隔离方式(AB)。 用Cgroup限制MySQL进程资源 在Proxy服务器限制QPS 通过MySQL实例的迁移 采用资源池机制管理数据库服务器资源 UMP系统是如何保障数据安全的(ABCD)。 SQL拦截 记录用户操作日志 数据访问IP白名单 SSL数据库连接 RDS英文全称为(Relational Database Service)。 RDS实例或简称“实例”,是用户购买RDS服务的基本单位。√ 在用户购买RDS实例时,所选择的内存大小已经决定了该实例的最大连接数。√ 新建RDS账号,MySQL实例支持最多创建20个账号,SQL Server实例支持最多创建50个账号。× 下列哪个不是连接RDS for MySQL数据库的方法(C)。 使用客户端MySQL-Front访问 使用数据库管理工具Navicat MySQL 使用Shell命令登录 使用阿里云控制台iDB Cloud访问 HBase采用“四维坐标”定位一个单元格。√ 行键是按照字典序存储。√ 访问HBase表中的行有哪几种方式(ABD)。 通过单个行键访问 通过一个行键的区间来访问 直接读取 全表扫描 41.colFamily指的是(列族)。第七章 填空: 1.MapReduce的核心函数:_ _ 答案:P132 Map Reduce 2.MapReduce的核心思想可以用_来描述。 答案:P134 分而治之 3.MapReduce整个工作流程的核心环节是_过程。 答案:P136 Shuffle 4.Shuffle过程分为_端的操作和_端的操作。 答案:P136 Map Reduce 5.MapReduce是_编程框架。 答案:P131 分布式并行 6.MapReduce的处理单位是_ 答案:P课件15 split 7.大规模数据集的处理包括__和______两个核心环节。 答案:P134 分布式存储 分布式计算单选: 1.Hadoop框架是用(C)实现的。 P133 A.C B.C++ C.java D.VB 2.以下哪项不是MapReduce体系结构的主要组成部分(D) P课件9 A.Client B.JobTracker C.TaskTracker D.TaskScheduler 3.每个Map任务分配一个缓存,MapReduce默认缓存是(A) P137 A.100MB B.80MB C.120MB D.200MB 4.以下哪项不属于步骤不包含在溢写过程中(B) P137 A.分区 B.归并 C.排序 D.合并 5.Reduce从(C)读取数据。 P135 A.本地存储 B.磁盘 C.硬盘 D.主存 6.Map任务的输入文件、Reduce任务的处理结果都是保存在(A)的。P135 A.分布式文件系统 B.本地存储 C.硬盘 D.主存 多选: 1.下面关于MapReduce工作流程说法正确的是(ABD) P135 A.不同的Map任务之间不会进行通信。 B.不同的Reduce任务之间也不会发生任何信息交换。 C.用户能显式的从一台机器向另一台机器发送信息 D.所有的数据交换都是通过MapReduce框架自身去实现的。 2.Map端的Shuffle过程包括以下哪几个步骤。(ABCD) P136 A.输入数据和执行Map任务 B.写入缓存 C.溢写(分区、排序、合并) D.文件归并 3.Reduce端的Shuffle过程包括(ABD) P138 A.“领取”数据 B.归并数据 C.溢写 D.把数据输入到Reduce任务 4.基于MapReduce模型的关系上的标准运算,包括(ABCD) P142 A.选择运算 B.投影运算 C.并、交、差运算 D.自然连接运算 5.MapReduce执行的全过程包括以下几个主要阶段(ABCD) P151 A.从分布式文件系统读入数据 B.执行Map任务输出中间结果 C.通过Shuffle阶段把中间结果分区排序整理后发送给Reduce任务 D.执行Reduce任务得到最终结果并写入分布式系统文件 6.MapReduce的广泛应用包括(ABCD) P151 A.关系代数运算 B.分组与聚合运算 C.矩阵-向量乘法 D.矩阵乘法 7.与传统并行计算框架相比,以下哪些是MapReduce的优势(ABC) P课件6 A.非共享式,容错性好 B.普通PC机,便宜,扩展性好 C.编程/学习难度较简单 D.实时、细粒度计算、计算密集型判断: 1.MapReduce设计的一个理念是“计算向数据靠拢”,而不是“数据向计算靠拢” (√) P133 2.MapReduce程序一定要用java来写。 (×) P133 3.Map函数和Reduce函数都是以作为输入(√) P133 4.Shuffle过程是指对Map输出结果进行分区、排序、合并等处理并交给Reduce的过程。 (√) P136 5.Map端的所有Shuffle过程结束后,所有Map输出结果都保存在Map机器的本地磁盘上 (√) P138 6.词频计算是典型的分组聚合运算。 (√) P144 7.MapReduce运行在分布式文件系统GFS上。 (√) P132 8.MapReduce是Hadoop MapReduce的开源实现。 (×) P132 9.MapReduce框架采用了Master/Slave架构,包括一个Master和若干个Slave。Master上运行JobTracker,Slave上运行TaskTracker . (√) P课件7 split 是一个逻辑概念,它只包含一些元数据信息,比如数据起始位置、数据长度、数据所在节点等。它的划分方法完全由用户自己决定。 (√) P课件15第八章 单选 1.JobTracker的三大功能不包括(D) P160 A.资源管理 B.任务调度 C.任务监控 D.调度Map/Reduce任务的执行多选 1.Hadoop1.0的核心组件主要存在以下不足(ABCD)P155 A.难以看到程序整体逻辑 B.开发者自己管理作业之间的依赖关系 C.执行迭代操作效率低 D.资源浪费 2.以下(ACD)产品使Hadoop功能更加完善. P156 A.Pig B.QJM C.Tez D.Oozie 3.采用HDFS联邦的设计方式,可解决单名称节点以下问题(ABD) P159 A.HDFS集群可扩展性 B.性能更高效 C.单点故障问题 D.良好的隔离性 4.MapReduce1.0架构设计具有一些很难克服的缺陷,包括(ABCD) P160 A.存在单点故障 B.JobTracker“大包大揽”导致任务过重 C.容易出现内存溢出 D.资源划分不合理 填空 1.MapReduce1.0采用_架构设计,包括一个__JobTracker___和若干个____TaskTracker___ 答案:Master/Slave P159 2.YARN体系结构中包含了三个组件:__ResourceManager ___、_______、 NodeManager ______ 答案: ApplicationMaster P161判断 1.Tez支持DAG作业的计算框架,对作业的操作进行重新分解和组合,解决了不同的MapReduce任务之间存在重复操作,降低效率的问题。 (√) P156 2.相对于之前的HDFS10而言,HDFS2.0增加了HDFS HA和HDFS联邦等新特性。 (√) P156 3.HDFS HA提供两个名称节点,很好的解决了可扩展性、系统性能和隔离性三个方面的问题。(×) P158 4.HDFS联邦是真正的分布式设计。(×) P158 5.HDFS HA本质上不是单名称节点。 (×) P158 6.MapReduce1.0中资源被强制等量划分为多个“槽”,槽又被进一步划分为Map槽和Reduce槽,分别供Map任务和Reduce任务使用,彼此之间能使用分配给对方的槽。 (×) P160 YARN架构设计基本思路就是“放权” (√) P160第九十章 1.以下属于Spark的主要特点的是:()。 A.运行速度快 B.容易使用 C.通用性 D.运行模式多样 ABCD 2.Spark使用_执行引擎。 DAG 3.Scala是一门现代的多范式编程语言,平滑的集成了___和___的特性,旨在以简练优雅的方式来表达常用编程模式。 面向对象,函数式 4.Spark的主要编程语言是:()。 A.Java B.Scala C.Python D.R B 5.大数据处理主要包括三个类型,分别是:()。 A.复杂的批量数据处理 B.基于历史数据的交互式查询 C.基于实时数据流的数据处理 D.集成数据 ABC 6.RDD是___数据集。是分布式内存的一个抽象概念,提供了一种高度受限的共享内存模型。 弹性分布式 7.___是作业调度的基本单位。 阶段 8.一个作业包含多个RDD及作用于相应RDD上的各种操作()。 √ 9.以下不属于hadoop存在的缺点的是:()。 A.表达能力有限 B.编程模式灵活 C.磁盘IO开销大 D.延迟高 ACD 10.RDD提供了一组丰富的操作以支持常见的数据运算,分为“行动”(Action)和“转换”(Translation)()。 √ 11.Spark并不能完全替代Hadoop,主要用于替代Hadoop中的MapReduce计算模型()。 √ 12.Spark可以部署在资源管理器YARN之上,提供一站式的大数据解决方案()。 √ 13.RDD本质上是一个支持读写的分区记录集合,可以直接修改()。 × 14.RDD采用了惰性调用,即在RDD执行过程中,真正的计算发生在RDD的“行动”操作,对于“行动”之前的所有“转换”操作,Spark只是记录下“转换”操作应用的一些基础数据集以及RDD生成的轨迹,不会触发真正的计算。()。 √ 15.目前Spark支持三种不同类型的部署方式,包括_、__、_。 standalone、Spark on Mesos、Spark on YARN。 16.在许多企业实际应用中,Hadoop和Spark的统一部署是一种比较现实合理的选择。()。 √ 17.以下不属于Action API的是()。 A.count() B.map(func) C.first() D.reduce(func) B 18.scala >val wordCounts=textFile.flatMap(line=>line.split("")).map(word=>(word,1)).reduceByKey((a,b) => a + b) scala > wordCounts.collect() 在上面的代码中属于“行动”类型的操作的是()。 A.flatMap() B.map() C.reduceByKey() D.collect() D 19.流计算秉承一个基本理念,即数据的价值随着时间的流逝而降低,如用户点击流。() √ 20.以下属于商业级流计算的是:()。 A.IBM InfoSphere Streams B.Twitter Storm C.Yahoo! S4 D.FaceBook Puma A 21.Hadoop擅长批处理,不适合流计算。() √ 22.数据采集系统的基本架构一般有以下三个部分:()。 A.Agent B.Collector C.Calculate D.Store C 23.在流处理流程中,实时查询服务可以不断更新结果,并将用户所需的结果实时推送给用户。() √ 24.Spark的设计遵循“一个软件栈满足不同应用场景”的理念,逐渐形成了一套完整的生态系统。() √ 25.Spark可以部署在资源管理器YARN之上,提供一站式的大数据解决方案。() √ 26.DAG:是Directed Acyclic Graph(有向无环图)的简称,反映RDD之间的依赖关系。() √ 27.Spark运行架构包括集群资源管理器(Cluster Manager)、运行作业任务的工作节点(Worker Node)、每个应用的任务控制节点(Driver)和每个工作节点上负责具体任务的执行进程(Executor)。() √ 28.一个Application由一个Driver和若干个Job构成,一个Job由多个Stage构成,一个Stage由多个没有Shuffle关系的Task组成。() √ 29.Stage的类型包括两种:___和_。 ShuffleMapStage,ResultStage 30.Spark用Scala语言实现了RDD的API,程序员可以通过调用API实现对RDD的各种操作。() √
填空: 1.分布式文件系统在物理结构上是由计算机集群中的多个节点构成的,这些节点分为两类:一类叫_;另一类叫aaS。 5.NoSQL数据库采用的是_非关系数据模型。6.MapReduce1.0采用__Master/Slave __架构设计,包括一个JobTracker和若干TaskTracker 7.RDD是弹性分布式____数据集。是分布式内存的一个抽象概念,提供了一种高度受限的共享内存模型。 8.阶段/Stage是作业调度的基本单位。 9.colFamily指的是__列族__。 10.与分布式对应的方式是____集中式_____.。 11.大规模数据集的处理包括分布式存储和__分布式计算_____两个核心环节。 12.MapReduce的核心思想可以用___分而治之____来描述。 13.写出大数据特征的4个V:数据量大volume,数据类型繁多 variety,处理速度快velocity,价值密度低value 14.NoSQL的四大类型为键值数据库、_列族数据库、文档数据库、图数据库 15.在HDFS中,名称节点负责管理分布式文件系统的命名空间,保存了两个核心的数据结构,即_FsImage和EditLog。 16.BigTable是一个分布式存储系统,利用谷歌提出的MapReduce_分布式并行计算模型来处理海量数据。 17.Shuffle过程分为_Map端的操作和Reduce端的操作。 18.数据总体上可以分为流数据__和静态数据_____。答案:流数据,静态数据 19.UMP系统功能为_容灾_、读写分离、资源管理、资源调度、资源隔离和数据安全。 20.目前Spark支持三种不同类型的部署方式,包括__standalone____、___Spark on Mesos___、____Spark on YARN____。答案:standalone、Spark on Mesos、Spark on YARN。 21.RDS英文全称为__Relational Database Service。 22.MapReduce的核心函数:Map和Reduce。 23.MapReduce整个工作流程的核心环节是__Shuffle__过程。 24.Spark使用_DAG执行引擎以支持循环数据流与内存计算. 25.HBase只有一个索引——行键_,通过巧妙的设计,HBase中的所有访问方法,或者通过行健访问,或者通过行健扫描,从而使得整个系统不会慢下来。 26.Scala是一门现代的多范式编程语言,平滑的集成了面向对象_和函数式_的特性,旨在以简练优雅的方式来表达常用编程模式。 27.RDD中的依赖关系分为__窄依赖_与宽依赖。答案:窄依赖,宽依赖 28.YARN体系结构中包含了三个组件:ResourceManager、ApplicationMaster _、NodeManager29.写出大数据特征的4个V? 数据量大volume,数据类型繁多 variety,处理速度快velocity,价值密度低value30.信息科技为大数据时代提供技术支撑有哪些? 在信息存储方面,来自斯威本科技大学(Swinburne University of Technology)的研究团队,在2013年6月29日刊出的《自然通讯(Nature Communications)》杂志的文章中,描述了一种全新的数据存储方式,可将1PB(1024TB)的数据存储到一张仅DVD大小的聚合物碟片上。 在信息处理方面,CPU处理能力大幅提升; 在信息传输方面,网络带宽不断增加。31.参考下图阐述大数据的特征。 大数据的特征被总结为多个V。该图中给出了4个V,分别是:大数据的量Volume之大,大数据的速度velocity之快,大数据的多样化variety,以及大数据的价值value密度之低。32.图中数字3代表什么意思? 备份冗余数目33.在spark-shell中,输入语句完成如下功能:打开本地文件/usr/local/a.txt,并用a对其引用。val a=sc.textFile("file:///usr/local/a.txt")#&val a=sc.textFile("/usr/local/a.txt")34.在spark-shell中,写出实现如下功能的语句:打开Hadoop分布式文件/usr/local/a.txt,并保存在word中。 答案:val word=sc.textFile("hdfs:///usr/local/a.txt")单选: 1.下述关于hadoop的阐述,正确的是 (D) A. 是一个分布式数据库与并行计算系统 B. 是一个分布式存储系统与分布式数据库 C. 是一个集中式存储与分布式并行运算系统 D. 是一个分布式存储与分布式并行运算系统2.当一个客户端从Zookeeper服务器上拿到-ROOT-表的地址以后,就可以通过 (C) 找到用户数据表所在的Region服务器,并直接访问该Region服务器获得数据。 A. A.一级寻址 B. B.二级寻址 C. C.三级寻址 D. D.四级寻址3.(A)是HBase中最核心的模块,负责维护分配给自己的Region,并响应用户的读写请求。 A. Region服务器 B. Store C. MemStore缓存 D. StoreFile文件4.下列选项中_B_不是NoSQL数据库的特点。 A. 灵活的可扩展性 B. 动态的数据迁移 C. 灵活的数据模型 D. 与云计算紧密结合 5.下列关于云数据库的特点,错误的是_A_ A. 灵活的关系数据模型 B. 较低的使用代价 C. 高性能 D. 动态可扩展性6.MapReduce是_C_编程框架。 A. 分布式并发 B. 非分布式并行 C. 分布式并行 D. 非分布式并发7.JobTracker的三大功能不包括(D) A. 资源管理 B. 任务调度 C. 任务监控 D. 调度Map/Reduce任务的执行8.“用户原创内容”的数据产生方式对应于下面哪个阶段?(B) A. web1.0 B. web2.0 C. 互联网 D. 物联网9.以下不属于Action API的是(B)。 A. count() B. map(func) C. first() D. reduce(func)10.scala>valwordCounts=textFile.flatMap(line=>line.split("")).map(word=>(word,1)).reduceByKey((a,b) => a + b) scala > wordCounts.collect() 在上面的代码中属于“行动”类型的操作的是(D)。 A. flatMap() B. Map() C. reduceByKey() D. collect()11.Map任务的输入文件、Reduce任务的处理结果都是保存在(B)的。 A. 本地存储 B. 分布式文件系统 C. 硬盘 D. 主存 12.以下哪项不是MapReduce体系结构的主要组成部分(D) A. Client B. TaskTracker C. JobTracker D. TaskScheduler13.下列选项中(C)不是文档数据库的优点 A. 性能好 B. 复杂性低 C. 统一的查询语法 D. 数据结构灵活14.HBase是针对谷歌BigTable的开源实现,是一个高可靠、__B___、面向列、可伸缩的分布式数据库,主要用来存储非结构化和半结构化的松散数据。 A. A.高功能 B. B.高性能 C. C.低效率 D. D.高质量15.UMP系统借助于__C___来实现集群内部的负载均衡。 A. 主从库实现用户调度 B. 主从库实现用户代理服务器 C. 利用主从库实现用户操作的分离 D. 主从库实现用户日志管理16.Spark的主要编程语言是:(B)。 A. Java B. Scala C. Python D. R17.以下属于商业级流计算的是:(A) A. IBM InfoSphere Streams B. Twitter Storm C. Yahoo! S4 D. FaceBook Puma18.下列选项不属于Zookeeper主要发挥的作用的是__D A. 提供分布式锁 B. 监控所有MySQL实例 C. 作为全局的配置服务器 D. 支持透明的数据分片作用19.以下哪项步骤不包含在溢写过程中(B) A. 分区 B. 文件归并 C. 排序 D. 合并20.下列哪个不是连接RDS for MySQL数据库的方法(C) A. 使用客户端MySQL-Front访问 B. 使用数据库管理工具Navicat_MySQL C. Shell命令 D. 使用MySQL命令登录21.MapReduce的处理单位是(B) A. block B. split C. Map D. RR22.以下不属于hadoop存在的缺点的是:(B) A. 表达能力有限 B. 编程模式灵活 C. 磁盘IO开销大 D. 延迟高23.谷歌的GFS和MapReduce等大数据技术受到追捧,Hadoop平台开始大行其道是在大数据发展的那个时期(B ) A. 第一阶段 B. 第二阶段 C. 第三阶段 D. 第四阶段24.每个Map任务分配一个缓存,MapReduce默认缓存是(A) A. 100MB B. 80MB C. 120MB D. 200MB多选: 1.MapReduce执行的全过程包括以下几个主要阶段(ABCD) A. 从分布式文件系统读入数据 B. 执行Map任务输出中间结果 C. 通过Shuffle阶段把中间结果分区排序整理后发送给Reduce任务 D. 执行Reduce任务得到最终结果并写入分布式系统文件2.HDFS特殊的设计,在实现上述优良特性的同时,也使得自身具有一些应用局限性,主要包括以下几个方面 (AB) A. A.不适合低延迟数据访问 B. B.无法高效存储大量小文件 C. C.不支持单用户写入及任意修改文件 D. D.硬件设备昂贵3.最终一致性根据更新数据后各进程访问到数据的时间和方式的不同,可以进行区别。下列说法正确的是 ABCD A. 因果一致性 B. 读己之所写一致性 C. 单调读一致性$会话一致性 D. 单调写一致性4.Reduce端的Shuffle过程包括(ABD) A. “领取”数据 B. 归并数据 C. 溢写 D. 把数据输入到Reduce任务5.采用HDFS联邦的设计方式,可解决单名称节点以下问题(ABD) A. HDFS集群可扩展性 B. 性能更高效 C. 单点故障问题 D. 良好的隔离性6.MapReduce1.0架构设计具有一些很难克服的缺陷,包括(ABCD) A. 存在单点故障 B. JobTracker“大包大揽”导致任务过重 C. 容易出现内存溢出 D. 资源划分不合理7.三次信息化浪潮的标志有哪些(ABC) A. 个人计算机 B. 互联网 C. 物联网,云计算和大数据 D. 人工智能8.信息科技需要解决的核心问题包括:(ACD) A. 信息存储 B. 信息可视 C. 信息传输 D. 信息处理9.以下属于批处理大数据计算的产品有:(AC) A. MapReduce B. Storm C. Spark D. Pregel10.以下属于图计算的产品有:(ABCD) A. Pregel B. GraphX C. Giraph D. PowerGraph11.访问HBase表中的行有哪几种方式(ABD) A. 通过单个行键 B. 行键的区间 C. 列族 D. 全表扫描12.大数据对科学研究有哪些影响(ABCD) A. 第一范式:实验科学 B. 第二范式:理论科学 C. 第三范式:计算科学 D. 第四范式:数据密集型科学13.关系数据库无法满足Web2.0的需求主要表现在哪几个方面(ACD) A. 无法满足海量数据的管理需求 B. 无法满足数据完整性 C. 无法满足数据高并发的需求 D. 无法满足高可扩展性和高可用性的需求14.人类科学研究范式包括:(ABCD) A. 实验 B. 理论 C. 计算 D. 数据15.下面关于MapReduce工作流程说法正确的是(ABD) A. 不同的Map任务之间不会进行通信。 B. 不同的Reduce任务之间也不会发生任何信息交换。 C. 用户能显式的从一台机器向另一台机器发送信息 D. 所有的数据交换都是通过MapReduce框架自身去实现的16.与传统并行计算框架相比,以下哪些是MapReduce的优势(ABC) A. 非共享式,容错性好 B. 普通PC机,便宜,扩展性好 C. 编程/学习难度较简单 D. 适用场景为实时、细粒度计算、计算密集型17.Hadoop1.0的核心组件主要存在以下不足(ABCD) A. 难以看到程序整体逻辑 B. 开发者自己管理作业之间的依赖关系 C. 执行迭代操作效率低 D. 资源浪费18.NoSQL数据库的明显优势在于(BCD) A. 数据的完整性 B. 可以支持超大规模数据存储 C. 灵活的数据模型 D. 强大的横向扩展能力19.HDFS在设计上采取了多种机制保证在硬件出错的环境中实现数据的完整性。总体而言,HDFS要实现以下目标: (1)兼容廉价的硬件设备 (2)流数据读写 (3)大数据集 (4)复杂的文件模型 (5)强大的跨平台兼容性 (D) A. A.(1)(2)(3)(4) B. B.(1)(2)(4)(5) C. C.(2)(3)(4)(5) D. D.(1)(2)(3)(5)20.Map端的Shuffle过程包括以下哪几个步骤。(ABCD) A. 输入数据和执行Map任务 B. 写入缓存 C. 溢写(分区、排序、合并) D. 文件归并21.MapReduce的广泛应用包括(ABCD) A. 关系代数运算 B. 分组与聚合运算 C. 矩阵乘法 D. 矩阵-向量乘法 22.大数据处理主要包括三个类型,分别是:(ABC)。 A. 复杂的批量数据处理 B. 基于历史数据的交互式查询 C. 基于实时数据流的数据处理 D. 集成数据23.UMP系统采用哪两种资源隔离方式(AB) A. 用Cgroup限制MySQL进程资源 B. 在Proxy服务器端限制QPS C. 通过MySQL实例的迁移 D. 采用资源池机制管理数据库服务器资源24.MapReduce执行的全过程包括以下几个主要阶段(ABCD) A. 从分布式文件系统读入数据 B. 执行Map任务输出中间结果 C. 通过Shuffle阶段把中间结果分区排序整理后发送给Reduce任务 D. 执行Reduce任务得到最终结果并写入分布式系统文件25.以下(ACD)产品使Hadoop功能更加完善. A. Pig B. QJM C. Tez D. Oozie26.以下属于流计算的产品有:(ABCD) A. Storm B. S4 C. Flume D. Puma27.基于MapReduce模型的关系上的标准运算,包括(ABCD) A. 选择运算 B. 并、交、差运算 C. 投影运算 D. 自然连接运算28.不同的计算框架统一运行在YARN中,可以带来如下好处:(ACD) A. 计算资源按需伸缩 B. 计算资源平均分配 C. 不用负载应用混搭,集群利用率高 D. 共享底层存储,避免数据跨集群迁移29.数据采集系统的基本架构一般有以下三个部分:(ABD) A. Agent B. Collector C. Calculate D. Store30.以下属于Spark的主要特点的是:(ABCD)。 A. 运行速度快 B. 容易使用 C. 通用性 D. 运行模式多样31.Spark采用RDD以后能够实现高效计算的原因主要在于:(ABD) A. 高效的容错性 B. 中间结果持久化到内存 C. 两种依赖方式 D. 存放的数据可以是Java对象32.下列为UMP系统架构设计遵循的原则的是(ABCD) A. 保持单一的系统对外入口,并且为系统内部维护单一的资源池 B. 消除单点故障,保证服务的高可用性 C. 保证系统具有良好的可伸缩性,能动态地增加、删减计算与存储节点 D. 保证分配给用户的资源也是弹性可伸缩的,资源之间相互隔离,确保应用和数据的安全33.信息科技为大数据时代提供的支撑(BCD) A. 计算机设备廉价 B. 存储设备容量不断增加 C. CPU处理能力大幅度提升 D. 网络带宽不断增加34.为了保证系统的容错性和可用性,HDFS采用了多副本方式对数据进行冗余存储,这种多副本方式具有以下几个优点:(BCD) A. A.容易修改数据问题 B. B.加快数据传输速度 C. C.保证数据的可靠性 D. D.容易检查数据错误35.UMP系统是如何保障数据安全的(ABCD) A. SSL数据库连接 B. 数据访问IP白名单 C. 记录用户操作日志 D. SQL拦截36.HBase的实现包括3个主要的功能组件:(ABD) A. A.库函数 B. B.一个Master主服务器 C. C.一个Region服务器 D. D.许多个Region服务器判断: 1.分布式文件系统在物理结构上是由计算机集群中的多个节点构成的,这些节点分为两类:一类叫主节点,另一类叫从节点。(√) 2.MapReduce框架采用了Master/Slave架构,包括一个Master和若干个Slave。Master上运行JobTracker,Slave上运行TaskTracker . (√) 3.HDFS采用块的概念,默认的一个块大小是64MB。 (√) 4.HDFS采用抽象的块概念可以简化系统设计,适合数据备份,但不可以支持大规模文件 存储。(×) 5.在HDFS的设计中,第二名称节点起到了名称节点的“检查点”和“热备份”的作用,因 为有了第二名称节点的存在,当名称节点发生故障时,系统就不会丢失元数据信息。(×) 6.在HBase中执行更新操作时,会在生成一个新版本之前删除数据旧的版本。(×) 7.HBase的系统架构中的客户端是指用户。(×) 8.CAP中的C与CAID中的C的含义一样。 (×) 9.NoSQL的英文全称为 No Structual Query Language。( ×) 10.云计算八大优势为按需服务、随时服务、通用性、高可靠性、极其廉价、超大规模、 虚拟化、高扩展性。(√) 11.云计算可同时为众多用户提供服务。(√) 12.云数据库有专属与自己的数据模型。( ×) 13.MapReduce是Hadoop MapReduce的开源实现.(×) 14.MapReduce运行在分布式文件系统GFS上。 (√) 15.HDFS联邦是真正的分布式设计。 (×) 16.MapReduce1.0中资源被强制等量划分为多个“槽”,槽又被进一步划分为Map槽和 Reduce槽,分别供Map任务和Reduce任务使用,彼此之间能使用分配给对方的槽。(×) 17.一个作业包含多个RDD及作用于相应RDD上的各种操作。(√) 18.RDD提供了一组丰富的操作以支持常见的数据运算,分为“行动”(Action)和“转换” Transformation。 ( √) 19.RDD本质上是一个支持读写的分区记录集合,可以直接修改。 ( ×) 20.RDD采用了惰性调用,即在RDD执行过程中,真正的计算发生在RDD的“行动”操作, 对于“行动”之前的所有“转换”操作,Spark只是记录下“转换”操作应用的一些基础数 据集以及RDD生成的轨迹,不会触发真正的计算。(√) 21.人类社会的数据产生大致经历了3个阶段:运营式系统阶段,用户原创内容阶段和感知 式系统阶段。( √) 22.大数据具有的三大特征:全样而非抽样,效率而非精确,相关而非因果。(√) 23.云计算3中典型的服务模式:IaaS(基础设施即服务),PaaS(平台即服务),SaaS(软件 即服务)。( √) 24.web2.0特征之一就是物联网原创内容。( ×) 25.1PB(1024TB)的数据能够存储到一张仅DVD大小的聚合物碟片上。(√) 26.NewSQL这类数据库不仅具有NoSQL对海量数据的存储管理能力,还保持了传统数据库 支持ACID和SQL等特性。( √) 27.HBase采用行键、列族、列限定符、时间戳来定位一个单元格。(√) 28.行键是按照字典序存储。( √) 29.每个Application都有自己专属的Executor进程,并且该进程在Application运行期间一直 驻留。Executor进程以多线程的方式运行Task。 (√) 30.Spark可以部署在资源管理器YARN之上,提供一站式的大数据解决方案。(√) 31.Hadoop属于开发运行环境中的运行环境。 (√) 32.为保证一致性,关系数据库遵守ACID模型,NoSQL数据库遵守BASE模型。(√) 33.HDFS采用抽象的块概念可以简化系统设计,适合数据备份,但不可以支持大规模文件存储。(×) 34.相对于之前的HDFS10而言,HDFS2.0增加了HDFS HA和HDFS联邦等新特性。(√) 35.HDFS把硬件出错看成一种常态,设计了错误恢复机制。 (√) 36.UMP系统是低成本和高性能的MySQL数据库方案,关键模块采用Erlang语言实现。 (√) 37.Mnesia是一个集中式数据库管理系统。 (×) 38.UMP系统只为一个用户创建一个MySQL实例。 (×) 39.RDS实例或简称“实例”,是用户购买RDS服务的基本单位。 (√) 40.Map函数和Reduce函数都是以key,value作为输入。 (√) 41.MapReduce程序一定要用java来写。(×) 42.词频计算是典型的分组聚合运算。 (√) 43.Tez支持DAG作业的计算框架,对作业的操作进行重新分解和组合,解决了不同的MapReduce任务之间存在重复操作,降低效率的问题。(√) 44.流计算秉承一个基本理念,即数据的价值随着时间的流逝而降低,如用户点击流。(√) 45.分布式数据库HBase的数据类型只有字符串。(√) 46.新建RDS账号,MySQL实例支持最多创建20个账号,SQL Server实例支持最多创建50个账号。(×) 47.HDFS HA提供两个名称节点,很好的解决了可扩展性、系统性能和隔离性三个方面的问题。(×) 48.Spark Streaming的原理是将数据分解成一系列短小的批处理作业。(√) 49.Hadoop擅长批处理,不适合流计算。(√) 50.Shuffle过程是指对Map输出结果进行分区、排序、合并等处理并交给Reduce的过程。(√) 51.HDFS HA本质上不是单名称节点。(×) 52.Spark可以部署在资源管理器YARN之上,提供一站式的大数据解决方案。(√) 53.RDD在Spark架构中运行第一步是创建RDD对象。(√) 54.UMP系统是低成本和高性能的MySQL数据库方案,关键模块采用Erlang语言实现。(√) 55.BigTable是一个分布式存储系统,使用谷歌分布式文件系统MapReduce作为底层数据存储。(×) 56.在用户购买RDS实例时,所选择的内存大小已经决定了该实例的最大连接数。(√) 57.MapReduce设计的一个理念是“计算向数据靠拢”,而不是“数据向计算靠拢” (√) 58.HBase操作不存在复杂的表与表之间的关系,只有简单的插入、查询、删除、清空等。(√) 59.资源池是为MySQL实例分配资源的基本单位。(√) 60.split 是一个逻辑概念,它只包含一些元数据信息,比如数据起始位置、数据长度、数据所在节点等。它的划分方法完全由用户自己决定。 (√)补充: Web2.0网站系统通常要求严格的数据库事务。(×) YARN架构设计基本思路就是“放权” (√) Reduce从(C)读取数据。 A.本地存储 B.磁盘 C.硬盘 D.主存“软状态”是指(状态可以有一段时间不同步,具有一定的滞后性)。5.Map端的所有Shuffle过程结束后,所有Map输出结果都保存在Map机器的本地磁盘上 (√) P138 16.在许多企业实际应用中,Hadoop和Spark的统一部署是一种比较现实合理的选择。()。 √ 23.在流处理流程中,实时查询服务可以不断更新结果,并将用户所需的结果实时推送给用户。() √ 24.Spark的设计遵循“一个软件栈满足不同应用场景”的理念,逐渐形成了一套完整的生态系统。() √ 26.DAG:是Directed Acyclic Graph(有向无环图)的简称,反映RDD之间的依赖关系。() √ 27.Spark运行架构包括集群资源管理器(Cluster Manager)、运行作业任务的工作节点(Worker Node)、每个应用的任务控制节点(Driver)和每个工作节点上负责具体任务的执行进程(Executor)。() √ 28.一个Application由一个Driver和若干个Job构成,一个Job由多个Stage构成,一个Stage由多个没有Shuffle关系的Task组成。() √ 29.Stage的类型包括两种:_和_。 ShuffleMapStage,ResultStage 30.Spark用Scala语言实现了RDD的API,程序员可以通过调用API实现对RDD的各种操作。() √
1. 文件I/O次数当前有一个由100个块组成的文件,且文件控制块已经在主存。对于采用连续、链接(单向链)和一级索引结构(且索引块已经在主存)时,如果下面的条件成立,访问一个块,需要执行多少次磁盘I/O操作在连续分配时,假定在开头已经没有空间扩展文件,但在结尾处还有扩展的空间。并假定要扩展的信息块已经在主存: ①这个块被加到文件开头; ②这个块被加到文件中间; ③这个块被加到文件结尾; ④从文件开头删除一块; ⑤从文件中间删除一块; ⑥从文件结尾删除一块。解析1. 连续结构①由于开头已经没有空间扩展文件,若要把这个块加到文件开头,必须查文件控制块,找到文件的第一个物理块,计算文件的第100块的位置,先将第100块读入主存,然后再将它写入磁盘的下一块中。这样每一块需要两次访问磁盘,之后将主存的信息写入磁盘的文件的第一物理块中。共访问201次。 ②这个块被加到文件中间时,根据上面的分析可知,需要访问101次磁盘。 ③这个块被加到文件结尾,直接将主存信息写入磁盘即可。只需要1次访问磁盘。 ④从开头删除一块时,只需修改文件控制快中第一块位置和文件大小即可,不需要磁盘I/O。 ⑤从文件中间删除一块时,由①可知,需要移动后面的49块,共需98次磁盘I/O,需要修改文件控制块中文件大小。 ⑥从文件结尾删除一块时,只需要修改文件控制块中文件大小即可,不需要磁盘I/O。2.链接结构①由于是链接结构,要把这个块加到文件开头时,将原第一个物理块号作为指针写入信息块,只需要将该块信息写入一个磁盘块,并修改文件控制块中第一块位置和文件大小即可,访问磁盘1次。 ②需要读前50块,以便找到第51块的链接指针。将第51块的链接指针写入要插入的信息块,再为该信息块分配一个盘块,将信息块写入其中。将分配的块号写入第50块中。共需要52次磁盘I/O。 ③这个块被加到文件结尾,先将100块读出,以找到第100块,并修改它的链接字为插入块的块号。之后写入第100块和插入的信息块。共需要102次磁盘访问。 ④从文件开头删除一块时,需要1次磁盘I/O,将第一块读出,将它的链接字内容送文件控制块中第一位置,并修改文件大小。 ⑤从文件中间删除一块时,需要读前50块,以便找到第51块的链接指针。将第51块中的链接指针写入第50块中,共需要52次磁盘I/O。 ⑥从文件结尾删除一块时,需要读前99个磁盘块,将第99块的指针置位空后写回去。共需要100次。3.索引结构①由于是索引结构,且索引块在主存,要把这个块加到文件开头,只需要将该信息块写入一个磁盘块,并修改文件控制块中第一块位置和文件大小即可。访问磁盘1次。 ②只需要将该信息块写入一个磁盘块,并修改文件控制块中第一块位置和文件大写即可。访问磁盘1次。 ③只需要将该信息块写入一个磁盘块,并修改文件控制块中第一块位置和文件大小即可。访问磁盘1次。 ④只需要将该信息块写入一个磁盘块,并修改文件控制块中第一块位置和文件大小即可。访问磁盘1次。 ⑤只需要将该信息块写入一个磁盘块,并修改文件控制块第一块位置和文件大小即可。访问磁盘1次。 ⑥只需要将该信息块写入一个磁盘块,并修改文件控制块中第一块位置和文件大小即可,访问磁盘1次。
2022年01月
2021年12月