当前位置: 首页 > news >正文

首涂模板网站网站版块策划

首涂模板网站,网站版块策划,网站建设应重视后期的服务和维护,韶关最新消息简介 以下是本人一年多整理的前端学习笔记#xff0c;现汇总分享给大家#xff0c;很多问题都是面试必问的 更多学习资源#xff0c;可以点击我获取更多 1 js数据类型 原始类型#xff1a; null undefined number string boolean Symbol BigInt 引用类型#xff1a; 对…简介 以下是本人一年多整理的前端学习笔记现汇总分享给大家很多问题都是面试必问的 更多学习资源可以点击我获取更多 1 js数据类型 原始类型 null undefined number string boolean Symbol BigInt 引用类型 对象 2 判断一个对象属性是否存在 本身属性判断 obj.hasOwnProperty(key) 包括了上级属性判断 key in obj Reflect.get(obj, ‘key’) 没有返回undefined Reflect.has(obj, ‘key’) 3 把 10000000 格式化成 10,000,000 // 1 把 10000000 格式化成 10,000,000 let str 10000000 str str.replace(/(?\B(\d{3})$)/g, ,) console.log(str)4 平滑滚动 div{scroll-behavior: smooth }5 禁止函数new方式调用 function fn(){if (new.target){throw new Error(cant invoke with new)}console.log(fn call) } new fn() // error6 零宽字符以及应用场景 var account1 我\u200d是\u200d中\u200d国\u200d人,account2 我是中国人; console.log(account1.length, account2.length) // 打印 9 5 console.log(account1, account2) // 打印 我‍是‍中‍国‍人 我是中国人/u200d 是零宽度字符不会具体显示出来作用如下 1 起到水印防止文章盗版别人拷贝文字也会把零宽字符也会一起盗版 2 实现隐藏信息加密传递和解密处理 7 js可迭代器理解 可迭代协议就是任何一个对象只要包含Symbol.iterator, 且返回一个迭代器就表示可以迭代 {[Symbol.iterator]: function () {return 迭代器} }比如如下数组就是可迭代对象 var arr [1,2,3] undefined var iter arr[Symbol.iterator]() undefined iter.next() {value: 1, done: false} iter.next() {value: 2, done: false} iter.next() {value: 3, done: false} iter.next() {value: undefined, done: true}面试题 比如实现如下 const [a, b] {a: 1, b: 2} 运行上面代码会报出如下错误 caught TypeError: {(intermediate value)(intermediate value)} is not iterableat anonymous:1:16原因是{a: 1, b: 2} 不是一个可迭代的对象那么如何实现迭代呢是要让对象实现Symbol.iterator就可以 Object.prototype[Symbol.iterator] function(){return Object.values(this)[Symbol.iterator]() }8 null 和 undefined区别 null 表示是一个对象但是此时没有对象就是null undefined 表示是任何一个值但是此时没有值就是undefined 以下这些都是undefined 变量被声明但没有赋值调用函数参数没有提供对象属性没有赋值函数没有返回值 另外解释 null 是一个表示无的对象空对象指针转为数值时为0undefined 是一个表示无的原始值转为数值时为NaN。 9 标记模板字符串 const fontSize 20 const color #00ff00 const hi stylefont-size: ${fontSize}px,color: ${color} aaaaaa function style () {console.log(arguments)return style }style 是一个函数会把模板值作为参数传给函数 10 promise终极面试 Promise.resolve().then(() {console.log(0)return Promise.resolve(4) }).then((res) {console.log(res) });Promise.resolve().then(() {console.log(1)}).then(() {console.log(2)}).then(() {console.log(3)}).then(() {console.log(5)}).then(() {console.log(6)})print 0 1 2 3 4 5 611 微软经典算法面试9宫格输入法排列组合 function keyboardMap(digits) {var map [, , abc, def, ghi, jkl,mno, pqrs, tuv, wxyz];var result []for (var i 0 ; i digits.length; i) {// result result 组合map[digits[i]]result _compose(result, map[digits[i]])}function _compose(arr1, arr2) {if (arr1.length 0) return arr2if (arr2.length 0) return arr1var r []for (var i 0 ; i arr1.length; i) {for (var j 0 ; j arr2.length; j) {r.push(arr1[i] arr2[j])}}return r}return result }console.log(keyboardMap(2345678))12 并发请求 /*** 并发请求* param {*} urls 待请求的url数组* param {*} maxNum 最大并发数* returns */ function concurRequest(urls, maxNum) {return new Promise((resolve) {if (urls.length 0){resolve([])return}const results []let count 0 // 当前请求完成数量let index 0 // 下一个请求下标async function request() {if(index urls.length) returnconst i indexconst url urls[index]indexconsole.log(url)try{const resp await fetch(url)results[i] resp}catch(err) {results[i] err} finally{countif (count urls.length) {console.log(over)resolve(results)}request()}// console.log(results)}const times Math.min(maxNum, urls.length)for (let i 0 ; i times; i) {request()}}) }const urls [] for (let i 1 ; i 10; i) {urls.push(https://www.baidu.com/?a i) } concurRequest(urls, 1)13 如何将class转换为function class Example{constructor(name){this.name name}func(){console.log(this.name)} } // 开始转化为function use strict; function Example(name) {// 只能用new的方式执行if (!(this instanceof Example)) {throw new TypeError(Class consturctor cannot be invoked without new);}this.name name } // 设置func不可枚举 Object.defineProperty(Example.prototype, func, {value: function () {// func 不能通过newif (!(this instanceof Example)) {throw new TypeError( new func is error);}console.log(this.name)},enumerable: false }) Example.prototype.func function (){console.log(this.name) }14 可以重试的请求方法 function request(url, maxCount 5) {return fetch(url).catch(err maxCount 0 ? Promise.reject(err) : request(url, maxCount - 1)) }request(https://www.baidu.com, 6) .then((resp) {console(resp) }).catch((err) {console.log(err) })15 let 和 var区别 1 污染全局 2 块级作用 3 重复生命 4 暂时性死区 TDZ 16keyof基础进阶 const cat {name: jiang,age: 3 }const user {loginId: 123 }function T extends object, K extends keyof T getValue(obj: T, name: K): T[K] {return obj[name] }getValue(cat, name) getValue(user, loginId)17 大整数相加 function sum(a, b){let result const len Math.max(a.length, b.length)//a和b位数补齐a a.padStart(len, 0)b b.padStart(len, 0)let carry 0 for (let i len - 1; i 0; i--) {const n a[i] b[i] carrycarry Math.floor(n / 10)result (n % 10) result}if (carry){result 1 result}return result }console.log(sum(1112222222222222222222222222222222222222222233333333333333333333333, 2))18 粘性定位 .box{position: sticky;top: 0;}19 文本溢出处理 1 单行文本溢出 .txt{width: 200px;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;}2 多行文本溢出 .txt{width: 200px;height: 150px;line-height: 30px;overflow: hidden;display: -webkit-box;-webkit-line-clamp: 5;-webkit-box-orient: vertical;}20 获取鼠标位置的各种方式 1 e.x 鼠标到视口窗口左侧距离忽略滚动条 2 e.clientX 同e.x 3 e.pageX 鼠标到页面左侧距离包含滚动条的距离 4 e.screenX 鼠标到电脑整个屏幕左侧距离 5 e.movementX 鼠标到上一次位置的横向距离 6 e.offsetX 鼠标到目标元素e.target)左侧距离 21 flip 动画思想 https://www.imgeek.net/article/825358760 22 让事件只触发一次 XXX.addEventListener(XXXX, () {}, {once: true })23 模拟new操作 // 模仿new操作 function newFun(Fun, ...args) {// 1 创建一个空对象let newObj {}// 2 把空对象和构造函数通过原型链进行链接newObj.__proto__ Fun.prototype// 3 把构造函数的this绑定到新的对象上const result Fun.apply(newObj, args)return result instanceof Object ? result : newObj }function Person (name) {this.name name }Person.prototype.say function (){console.log(this.name say) }var p1 newFun(Person, jiang) p1.say()24 js关于this指向的问题 1.全局对象中的this指向指向的是window 2.全局作用域或者普通函数中的this指向全局window 3.this永远指向最后调用它的那个对象在不是箭头函数的情况下 4.new 关键词改变了this的指向 5.apply,call,bind可以改变this指向不是箭头函数 6.箭头函数中的this它的指向在定义的时候就已经确定了箭头函数它没有this,看外层是否有函数有就是外层函数的this没有就是window 7.匿名函数中的this永远指向了window匿名函数的执行环境具有全局性因此this指向window 25 js何如实现继承 1.原型链继承 缺点无法调用父类构造函数 2.借用构造函数维承 缺点无法电泳父类原型函数 3.组合式继承 缺点会调用两次构造方法 4.ES6的class类继承 26 scripte标签里的async和defer有什么区别 当没有async和defer这两个属性的时候 浏览器会立刻加载并执行指定的脚本 normal情况 parse dom - fetch script - exec - parse dom有async: 加载和渲染后面元素的过程将和script的加载和执行并行进行(异步) parse dom - parse dom - exec - parse dom - fetch script 有defer: 加载和渲染后面元素的过程将和script的加载并行进行(异步)但是它的执行事件要等所有元素解析完成之后才会执行 parse dom - 全部解析完 parse dom - exec - fetch script 扩展link 的preload 和 prefetch区别 preload 先加载后面请求不会再加载只要碰到link就是立即加载 prefetch 先获取只是现在用不用碰到link不会立即获取会等到空闲时候才会获取 27 函数箭头特点 不能作为构造函数使用不能new 箭头函数就没有原型 箭头函数没有arguments 箭头函数不能使用call applybind去噶便this的执行 this指向外层第一个函数的this 28 js判断类型方式 // 1 typeof() 对于基本数据类型没问题遇到引用数据类型无效 console.log(typeof(666)) // number console.log(typeof([1,2,3]))// object // 2 instanceof() 只能判断引用数据类不能判断基本数据类型 console.log([] instanceof Array) // true console.log(abc instanceof String) // false // 3 constructor 几乎可以判断基本数据类型和引用类型 // 但是如果改变的原型就不能使用了 console.log((abc).constructor String) // true // 4 Object.prototype.toString.call() // 可以判断任何数据类型 var opt Object.prototype.toString console.log(opt.call(2)) //[object Number] console.log(opt.call(true)) //[object Boolean] console.log(opt.call(abc)) //[object String] console.log(opt.call([])) // [object Array]29 Proxy比defineProperty好在哪里 defineProperty实现, 无法监听新增的属性 const obj {a: 1,b: 2,c: {a: 1,b: 2} } let v obj.a Object.defineProperty(obj, a, {get(){console.log(a, 读取)return v},set(val) {console.log(a, 赋值)v val} })obj.a 10 console.log(obj.a) // 不生效 definePropert 无法深度遍历 obj.c.a 20 defineProperty递归实现多层级监听 const obj {a: 1,b: 2,c: {a: 1,b: 2} }// 手写递归遍历达到多层级监听的问题function _isObject(v) {return typeof v object v ! null}function observe(obj) {for (const k in obj) {let v obj[k]if (_isObject(v)) {observe(v)}Object.defineProperty(obj, k, {get(){console.log(k, 读取)return v},set(val) {console.log(k, 赋值)v val}})}}observe(obj)obj.a 江obj.c.a 华console.log(obj.c.a) proxy简单实现 const proxy new Proxy(obj, {get(target, k) {let v target[k]console.log(k, 读取)return v},set(target, k , val) {if (target[k] ! val) {target[k] valconsole.log(k, 更改)}} })proxy递过实现多层级监听 const obj {a: 1,b: 2,c: {a: 1,b: 2} }function _isObject(v) {return typeof v object v ! null}function observe(obj) {// proxy实现const proxy new Proxy(obj, {get(target, k) {let v target[k]if (_isObject(v)) {v observe(v)}console.log(k, 读取)return v},set(target, k , val) {if (target[k] ! val) {target[k] valconsole.log(k, 更改)}}})return proxy }const proxy observe(obj) proxy.a aaa proxy.c.a bbbbb proxy.ccccconsole.log(proxy.c.a)20 宽度适应内容 width: fit-content21 对象数组去重 const arr [{a: 1, b: 2},{b: 2, a: 1},{a: 1, b: 2, c: {a: 1, b: 2}},{b: 2, a: 1, c: {b: 2, a: 1}} ] //错误做法 // const newArr [...new Set(arr)] // console.log(newArr)const isObject (val) typeof val object val ! null const newArr [...arr] for (let i 0; i newArr.length; i) {for (let j i 1; j newArr.length; j) {// if (newArr[j] newArr[i]) {// newArr.splice(j, 1)// j--// }if (equals(newArr[i], newArr[j])) {newArr.splice(j, 1)j--}} }function equals(val1, val2) {if (isObject(val1) isObject(val2)) {const keys1 Object.keys(val1),keys2 Object.keys(val2)if (keys1.length ! keys2.length) {return false}for (const k of keys1) {if (!keys2.includes(k)) {return false}if (!equals(val1[k], val2[k])) {return false}}return true} else {return val1 val2 } }console.log(newArr) 22 文字颜色和背景混合 .title{font-size: 3em;transition: 0.5s,mix-blend-mode: difference}23 并发任务控制 function timeout(time) {return new Promise((resolve) {setTimeout(() {resolve();}, time)}); }class SuperTask{constructor(paralleCount){// 并发数量this.paralleCount paralleCountthis.runningCount 0 ; // 正在运行任务数this.tasks []}add(task){return new Promise((resolve, reject) {this.tasks.push({task, resolve, reject})this._run()})}_run(){while(this.runningCount this.paralleCount this.tasks.length){const {task, resolve, reject} this.tasks.shift()this.runningCounttask().then(resolve, reject).finally(() {this.runningCount--this._run()})}} } const superTask new SuperTask(2);function addTask(time, name){superTask.add(() timeout(time)).then(() {console.log(任务${name}完成)}) } // 同一时段最多只能执行两个 addTask(10000, 1) // 10000 输入 1 addTask(5000, 2) // 5000 输入 1 addTask(3000, 3) // 8000 输入 1 addTask(4000, 4) // 12000 输入 1 addTask(5000, 5) // 15000 输入 124 消除异步传染性 因为getUser是异步导致以下全部函数都是异步 async function getUser(){return await fetch().then((resp) resp) }async function m1(){return await getUser() }async function m2(){return await m1() }async function m3(){return await m2() }async function main(){const user await m3()console.log(user) }main()function getUser(){return fetch(https://www/baidu.com) }function m1(){return getUser() }function m2(){return m1() }function m3(){return m2() }function main(){const user m3()console.log(user) }function run(func){const cache []let i 0;const _originalFetch window.fetchwindow.fetch (...args) {if(cache[i]){if (cache[i].status fulfilled) {return cache[i].data} else if (cache[i].status rejected) {throw cache[i].err}}const result {status: pending,data: null,err: null}cache[i] resultconst prom _originalFetch(...args).then(respresp).then(resp{result.status fulfilledresult.data resp}, err {result.status rejectedresult.data err})throw prom}try{func()}catch(err) {if (err instanceof Promise){const reRun () {i 0func()}err.then(reRun, reRun)}} }run(main)25 文字环绕设置 img{width: 50%;height: 50%;border-radius: 50%;shape-outside: circle(50%)}26 Promise like 判断 function isPromiseLike(value) {return (value ! null (typeof value object || typeof value function) typeof value.then function) }27 认识Symbol.toStringTag function A(){} const aa new A() Object.prototype.toString.call(aa) [object Object] A.prototype[Symbol.toStringTag] A A Object.prototype.toString.call(aa) [object A]38 具名导入和结构 // import导入只是标记一下变量ESM符号绑定 import {n, increase} from ./a // 结构是具体赋值 const {n, increase} a39 模拟一个微队列 function asyncRun(func){if (typeof Promise ! undefined) {Promise.resolve().then(func)} else if (typeof MutationObserver ! undefined) {const ob new MutationObserver(func)const textNode document.createTextNode(0)ob.observe(textNode, {characterData: true})textNode.data 1} else {setTimeout(func)} }40 js实现单例 方案一缺点原型链上追加属性无效 function singleton(className){let ins;return class {constructor(...args){if (!ins) {ins new className(...args)}return ins}} }class Video {constructor(){console.log(video created)this.name jiang}}const SingleVideo singleton(Video)const video1 new SingleVideo() const video2 new SingleVideo() console.log(video1 video2) console.log(video1) 方案二proxy代理方式完美方案 function singleton(className){let ins;// 使用代理并挟持构造器return new Proxy(className, {construct(target, args) {if (!ins) {ins new target(...args)}return ins}}) }class Video {constructor(){console.log(video created)this.name jiang}}const SingleVideo singleton(Video)const video1 new SingleVideo() const video2 new SingleVideo() console.log(video1 video2) console.log(video1) 41 冻结对象提升效率 有时候vue2在频繁给数组对象赋值会很消耗性能因为要执行Object.defineProterty 冻结对象 this.datas Object.freeze(this.getDatas())42 js函数重载 const searcher {}function addMethod(object, name, fn) {const old object[name]object[name] function (...args) {if (args.length fn.length) {return fn.apply(this, args)} else {return old.apply(this, args)}} } addMethod(searcher, find, () {console.log(查询所有用户) })addMethod(searcher, find, (name) {console.log(按照用户名查询) })addMethod(searcher, find, (firstname, lastname) {console.log(按照姓和名查询) })searcher.find() searcher.find(jiang) searcher.find(hua, jiang)42 vue一次性渲染列表太大出现白屏依次延迟加载方案 import {ref} from vue export function useDefer(maxFrameCount 1000) {const frameCount ref(0)const refreshFrameCount () {requestAnimationFrame(() {frameCount.value;if (frameCount.value maxFrameCount) {refreshFrameCount()}})}refreshFrameCount();return function (showInFrameCount) {return frameCount.value showInFrameCount} }使用 const defer useDefer() div v-forn in 100mycomp v-ifdefer(n)/mycomp /div43 对象属性筛选 const pick (obj, ...props) {return Object.fromEntries(Object.entries(obj).filter(([k]) props.includes(k))) } let obj {name: jiang,age: 35 } console.log(pick(obj, name)) // { name: jiang }44 随机颜色 const randomColor () # Math.floor(Math.random() * 0xffffff).toString(16).padEnd(6, 0) console.log(randomColor())45 随机字符串 const randomString () Math.random().toString(36).slice(2) console.log(randomString())46 从html获取纯文字 const removeTag (fragment) new DOMParser().parseFromString(fragment, text/html).body.textContent | console.log(removeTag(div你哈/div))47 什么数据响应 数据变化后会自动重新运行依赖该数据的函数 48 let和var区别 是否污染全局是否是块级作用域是否能重复声明是否有暂时性死区 48 无限递归是否栈溢出 function foo(){// setTimeout(foo, 0) // 不会栈溢出setTimeout(foo(), 0) // 会栈溢出 } foo()49 可以重试的请求方式 function request(url, maxCount 5) {return fetch(url).catch(err maxCount 0? Promise.reject(err) : request(url, maxCount--)) } request(http://wwww, 5)50 apply作用 修改this指向等同call但不一样的是call参数不是数组 函数.apply(参数1 …参数2) 等价于 参数1.函数(…参数2) console.log.call.call.call.call.apply((a) a, [1,2]) // 不输入任何值51 js真正私有字段 class A{#name; // 定义私有字段constructor(){this.#name jiang}#method(){console.log(私有方式外面不能访问)console.log(this.#name)} }const a new A() A.#name // 无法访问52 Math.floor 和 parseInt区别 Math.floor 是向左取整 parseInt 是向靠近0的一侧取整 console.log(Math.floor(2.5)) // 2 console.log(parseInt(2.5)) // 2 console.log(Math.floor(-2.5)) // -3 console.log(parseInt(-2.5)) // -253 控制动画停止与运行 .container{animation: rotate 20s linear paused infinite; }.container:hover{animation-play-state: running; }54 磨砂玻璃特效 元素背后的div模糊 .mark{backdrop-filter: blur(5px)}55 元素缩放方式 zoomscale span{font-size: 12px;transform: scale(0.5);display:inline-block;transform-origin: left center}56 智能弹幕不遮挡人脸方案 .danmu{-webkit-mask-image: url(./mark.svg);-webkit-mask-position: center;-webkit-mask-repeat: no-repeat;}57 js滚动元素到可视区域 elm.scrollIntoView({behavior: smooth,block: center})58 块级函数 var a; console.log(b) if (true){console.log(a)console.log(b)a 5function a() {}function b() {}a 0console.log(a) }console.log(a) console.log(b)// 函数不管在哪里声明都会提升到顶层 // 如果是判断里面提升到顶部会赋值undefine // 当代码hi行到判断里面函数a和b会生成块级作用域值是本身 59 transform .item{width: 100px;height: 100px;transform: rotate(120deg) translate(100px, 100px) } transform 执行顺序是从右往左先平移在旋转且旋转都是按照平移钱为中心旋转60 保持宽高比 .container{width: 90%;margin: 0 auto;aspect-ratio: 16/9.0}61 元素的尺寸 参考https://www.douyin.com/user/MS4wLjABAAAAi2oukRVcHpgD-HbVdzsxE7tYykr91YuIKukR_X_Yy08EFWRQhRrECDF6FvbvT8Xa?is_search1list_namefollowmodal_id7124153340170112268nt0 clientWidth clientHeight 边框以内的尺寸四舍五入的整数 不包含滚动条offsetWidth offsetHeight 布局尺寸包含滚动条scrollWidth scrollHeight 内容尺寸包含边距和溢出部分不需滚动且没有溢出等同于clientXXXgetBoundingClientRect()包含小数 const rect dom.getBoundingClientRect() 如果盒子没有旋转变形等情况下 rect.width 和 rect.height 等同于scrollXXXX 如果盒子旋转或变形 rect 是最小矩形去框住这个盒子 62 this指向问题 通过new调用指向新对象直接函数调用 指向全局对象对象调用 obj.func 指向objcallapplybind 指向第一个参数 63 经典面试题[‘1’, ‘2’, ‘3’].map(parseInt) console.log([1, 2, 3].map(parseInt)) // 得到结果 [ 1, NaN, NaN ] /*** [* 函数(1, 0),* 函数(2, 1),* 函数(3, 2)* ]*/64 设置阴影方式 box-shadow 根据外面盒子来做阴影filter: drop-shadow 根据盒子像素点来做阴影透明的地方不管 65 flex margin 简化布局 .parent{display: flex}.item{margin: auto; // 整体居中margin-left: auto; // 居右margin-right: auto; // 居左边}66 数据分组 const people [{name: jiang, age: 20},{name: mao, age: 22},{name: han, age: 30}, ]function groupBy(arr, generateKey){// 参数归一化if (typeof generateKey string) {const propName generateKeygenerateKey (item) item[propName]}const result []for (const item of arr) {const key generateKey(item)if (!result[key]) {result[key] [item]} else {result[key].push(item)}}return result }console.log(groupBy(people, (item) item.age))console.log(groupBy(people, (item) item.name))console.log(groupBy(people, name))const arr [1,2,3,4,5,6,7,8] console.log(groupBy(arr, (item) item % 2 0 ? 偶 : 奇)) 67 css 属性默认值设置 initial主动将某一css属性设为默认值 unset清除浏览器默认样式(全部清除all:unset) revert恢复浏览器默认样式 (全部恢复all:revert) 68 原型链prototype作用 概念每个对象都有一个原型prototype并从愿原型上继承属性和方法原型本身也是一个对象它也有自己的原型形成一个链式结构 对象寻找属性过程 假设 p 是对象p.name 先从p对象找有没有name属性 如果没有p.proto(指向Parent.protorype)上有没有name属性 如果没有Object.prototype上有没有name属性 如果没有返回null 69 块级格式化上下文 全称Block Formatting Context 简称 BFC 概念: 它是一块独立的渲染区域 它规定了在该区域钟常规流块盒的布局 常规流块盒在水平方向必须撑满包含块常规流块盒在包含块的垂直方向一次摆放常规流盒若外边距无缝相邻则进行外边距合并常规流块盒的自动高度和摆放位置无视浮动元素 BFC渲染区域 这个区域是由某个HTML元素创建以下元素会在其内部创建BFC区域根元素意味着html元素创建的BFC区域覆盖网页所有的元素浮动和绝对定位元素overflow不等于visable的块盒 1. float: left 2. position: absolute 3. overflow: hiddenBFC具体规则 创建BFC元素它的自动高度需要计算浮动元素创建BFC元素它的边框盒不会与浮动元素重叠创建BFC元素不会和它的子元素进行外边距合并 70 高度塌陷清除浮动办法 .clearfix::after{content: ;display: block;clear: both}或则position: absolute或则float: left或则overflow: auto , scroll hidden或则display: flow-root71 vue3效率提升主要表现在哪些方面 参考https://www.douyin.com/user/MS4wLjABAAAAeIIkCgELXG6XdUxuE9nQ6W4AfS-aoPFbtmnBL8ytcYtBSyurgePBYZXJpB0LJBCT?modal_id7214297604476112188 静态元素或则静态属性会被提升预字符串化缓存事件处理函数Block TreePatchFlag 72 随机数 const randomNum (min, max) Math.random()*(max - min) min 73 事件循环 主线程 主线程是执行代码的地方遇到函数会把该函数放入执行栈 执行栈 执行结构有函数就会从栈取出直接执行 任务队列 在执行栈中遇到比如setTimeout会放入任务队列等到计时结束会任务队列放入执行栈判断是否要执行 任务分为宏任务和微任务优先检查微任务是否有执行如果没有在检查宏任务是否有执行 微任务是在当前事件循环的尾部去执行宏任务是在下一次事件循环的开始去执行 宏任务 有明确的异步任务需要执行和回调需要其他异步线程支持。 setTimeout setInterval setImmediate 微任务 没有明确的异步任务需要执行只有回调不需要其他异步线程支持。 promise.then promise.catch new MutaionObserver() promise.nextTick() 74 浏览器缓存策略 强缓存本地缓存 不发起请求直接从缓存里面内容浏览器会把jscssimage存入内存下次直接从内存取协商缓存弱缓存 需要向后台发请求通过判断来决定是否协商缓存如果内容没有变化返回304历览器就用缓存里面的内同触发条件 强缓存 http1.0: 时间戳响应标头 http1.1: Cache-control 响应标头 弱缓存 http1.0: 请求头if-modified-since 响应头 last-modified http1.1请求头if-none-match 响应头 Etag 75 为什么需要虚拟dom 框架设置跨平台 76 ES6 结构基本使用 // 对象结构 const user {name: jiang,sex: 男 } const {name 默认值, sex: gender 男} user console.log(name, gender)// obj存放了不包含name的剩下字段 const {name: name1, ...obj} user// 数组结构 const numbers [0, 1, 2] const [a, , b] numbers const {0: a1, 2: b2} numbers const[a3, b3, ...num] numbers console.log(a, b)//参数结构 function ajax({method get, url /} {}) ajax({method: aaa,url:http })77 vue3 自定义指令 自定义指令 const map new WeakMap() const ob new ResizeObserver((entries) {for (const entry of entries) {const handler map.get(entry.target)if (handler) {const box entry.borderBoxSize[0]handler({width: box.inlineSize,height: box.blockSize})}} })export default {mounted(el: HTMLElement, binding: any) {ob.observe(el)map.set(el, binding.value)},unmounted(el: HTMLElement) {ob.unobserve(el)}, }注册指令main.js import sizeDirect from ./directive/sizeDirect ... app.directive(size-ob, sizeDirect)使用 div classdesktop-main v-size-obhandlerSize/div ... const handlerSize ((size: any) {console.log(handlerSize, size.width, size.height) })78 实现memoize缓存函数 function memoize(func, resolver) {const memoized function (...args) {const key resolver ? resolver.apply(this, args) : args[0];if (memoized.cache.has(key)) {return memoized.cache.get(key)}const result func.apply(this, args)memoized.cache.set(key, result)return result;}memoized.cache new WeakMap()return memoized }var object {a: 1, b: 2}var values memoize((obj) Object.values(obj)) console.log(values(object))79 模拟实现lodash的get函数 function get(object, path, defaultValue) {let obj objectif (typeof path string) {const reg /[^\[\].]/gpath path.match(reg)}for (const key of path) {if (!obj) {return defaultValue}obj obj[key]}return obj undefined ? defaultValue : obj }const object {a: [{b: {c: 1}}]} console.log(get(object, [a, 0, b], null)) console.log(get(object, (a[0].b.c), null)) 80 给fetch添加超时功能 function createFetchWithTimeout(timeout 1000) {return function (url, options) {return new Promise((resolve, reject) {const signalController new AbortController();fetch(url, {...options,signal: signalController.signal}).then(resolve, reject);setTimeout(() {reject(new Error(fetch timeout))// 取消请求signalController.abort()}, timeout)})} }const request createFetchWithTimeout(3000) request(http:****)81. 主流浏览器有哪些 Navigator(Gecko)Opera(Preston/Blink)IE(Trident) / Edge(Chromium)Firfox(Gecko)Safari(Webkit)Chrome(Webkit, chromium, Blink) 82. 浏览器有哪些进程和线程 进程 浏览器主进程只有一个GPU进程3D渲染第三方插件进程浏览器渲染进程内核 线程 GUI渲染线程html cssjs解析引擎线程事件触发线程事件队列定时器触发线程(setTimeout)异步网络请求线程(Ajax) 83. canvas转成file canvas.toBlob((blob) {const file new File([blob], avatar.jpg, {type: image/jpeg}) }, image/jpeg)84. dataURL转blob dataURLToBlob: function (dataurl) {let arr dataurl.split(,)let mime arr[0].match(/:(.*?);/)[1]let bstr atob(arr[1])let n bstr.lengthlet u8arr new Uint8Array(n)while (n--) {u8arr[n] bstr.charCodeAt(n)}return new Blob([u8arr], { type: mime }) }85. 盒子水平居中方式 方式1 .parent{position: relative;width: 800px;height: 800px;background: red; }.children{width: 100px;height: 100px;background: blue;position: absolute;left: 50%;top: 50%;transform: translate(-50%, -50%);}方式2 .parent{position: relative;width: 800px;height: 800px;background: red; }.children{width: 100px;height: 100px;background: blue;position: absolute;left: 0px;right: 0px;top: 0px;bottom: 0px;margin: auto;}方式3flex方式 方式4 文本居中 line-height : height 图片居中 vertical-align middle flex定位: display: flex; margin: auto 86. 隐藏元素方式 1 visibility: hiddn, 占用空间 2 opacity 0 不会改变布局也会触发事件 3 display: none 不占用空间 改变布局 4 transform: scale(0) 缩放无限小元素所在的位置保留 87. Symbol 作用 保证每个属性都是独一无二的防止属性冲突 参考 ![https://blog.csdn.net/wsz123456wsz/article/details/127598604] 88. js 安全性 XSS 跨站脚本攻击 攻击者通过注入恶意代码来利用网络漏洞从而在受害者浏览器与逆行代码分为三种存储型反射型DOM型 存储型XSS攻击者向目标网站的数据库注入恶意脚本当用户访问这些脚本会被执行 解决办法过滤输入数据并编码输出数据反射型XSS攻击者向目标网站发生恶意链接当用户点击脚本被执行 解决办法校验数据数据编码输出数据DOM型XSS攻击者将恶意脚本注入到网页中用户交互时脚本被执行 解决办法使用安全的js库避免使用eval函数 CSRF 跨站请求伪造 攻击者通过欺骗用户到目标网站上执行某些操作来发起伪造请求比如一个攻击者可能会发送一个包含修改用户密码的请求而这个请求看起来是来自用户自己的浏览器因此网站可能会对请求进行处理并修改用户密码。由于这个请求来自攻击者而不是用户因此这种攻击被称为跨站请求伪造。 解决办法 使用令牌CSRF令牌是一种随机生成的值用于验证用户的请求是否来自合法来源。服务器会将CSRF令牌包含在生成的表单中然后在处理表单提交时验证该令牌。如果请求中没有正确的CSRF令牌服务器将拒绝请求。另一种防止CSRF攻击的方法是使用SameSite属性。SameSite属性是一种cookie属性可以控制cookie是否可以被跨站点请求访问。当设置SameSite属性为“strict”时浏览器将禁止跨站点请求访问该cookie从而防止CSRF攻击。 CORS 跨源资源共享 跨域请求是指来自不同域的资源请求例如从一个网站向另一个网站发出AJAX请求。由于浏览器的同源策略一般情况下跨域请求是不允许的。CORS是一种通过HTTP头来授权浏览器允许特定的跨域请求的机制。 解决办法配置CORS为了配置CORS服务器需要向响应添加一些特定的HTTP头。这些头告诉浏览器哪些跨域请求是允许的哪些不允许。常见的CORS头包括Access-Control-Allow-Origin、Access-Control-Allow-Methods和Access-Control-Allow-Headers等。 89. js安全最佳实战 禁用不必要的js功能使用https使用密码哈希密码不能明文存储定期更新js库 90. vue 通讯方式 props和$emit父组件provide子组件inject来注入变量$refs获取组件实例eventBusvuex状态管理 91. vue生命周期 beforCreate 无法访问datamethodscomputedcreated 可以访问无法访问datamethodscomputed不能访问dombeforeMounte render首次调用mounted 真实dom挂在完成beforeUpdate 数据修改但是页面未修改updated 页面修改完成beforeDestory 可以做销毁前的一些工作destoryed 92. vue事件指令 v-once - 定义它的元素或组件只渲染一次包括元素或组件的所有节点首次渲染后不再随数据的变化重新渲染将被视为静态内容。v-cloak - 这个指令保持在元素上直到关联实例结束编译 – 解决初始化慢到页面闪动的最佳实践。v-bind - 绑定属性动态更新HTML元素上的属性。例如 v-bind:class。v-on - 用于监听DOM事件。例如 v-on:click v-on:keyupv-html - 赋值就是变量的innerHTML – 注意防止xss攻击v-text - 更新元素的textContentv-model - 1、在普通标签。变成value和input的语法糖并且会处理拼音输入法的问题。2、再组件上。也是处理value和input语法糖。v-if / v-else / v-else-if。可以配合template使用在render函数里面就是三元表达式。v-show - 使用指令来实现 – 最终会通过display来进行显示隐藏v-for - 循环指令编译出来的结果是 -L 代表渲染列表。优先级比v-if高最好不要一起使用尽量使用计算属性去解决。注意增加唯一key值不要使用index作为key。v-pre - 跳过这个元素以及子元素的编译过程以此来加快整个项目的编译速度。 93. vue computed 和watch区别 computed 有缓存值可以设置setter 和 getter一般用在模板渲染中watch 监听值变化适合用户监听值变化然后去做一些复杂的业务逻辑 94. vue v-if 和v-for为什么不能同时使用 会先解析v-for,再解析v-if, 会带来性能消耗可以使用template先判断if template v-ifisShowp v-foritem in items /template可以使用计算属性, 过滤掉不需要显示的 computed: {items: function() {return this.list.filter(function (item) {return item.isShow})} }95. vue2 响应数据原理 思路 数据劫持 观察者模式 数据劫持 利用Object.defineProperty劫持对象属性的set和get数据变化时候触发消息给订阅者。vue 双向绑定整合了ObserverComplile和Watcher Observer 监听器对数据对象遍历包括子鼠星利用defineProperty监听setter和getter来监听数据变化Compile 解析器 解析编译Vue模板数据 渲染视图同时将每个执行对应的绑定更新数据监听数据变化添加到监听数据订阅者同步更新函数Watcher 订阅者 订阅observer属性变化的消息当发生变化来通知complie来更新函数 来搭建Observer 和Compile通信桥廊Dep 订阅器采用发布订阅模式用来手监听阅者watcher对监听observice和watcher进行统一管理 https://img-blog.csdnimg.cn/20190920152632212.png 96 vue 检测数组变化 vue将data中的数组进行了原型链重写指向了自己的原型方法如果数组包含了引用类型会再次遍历依赖实现了数组变化监听有以下两种情况无法监听到变化 利用索引设置项 vm.items[index] newValue修改数组长度 vm.items.length newLength 以上解决办法 vm.$set(vm.items, indexOfItem, newValue)97. vue 父子组件生命周期函数执行顺序 渲染过程 父beforeCreate - 父created - 父beforeMount - 子beforeCreate - 子created -子beforeMount -子Mounted - 父 mounted更新过程 父 beforeUpdate - 子 beforeUpdate - 子 updated - 父 updated销毁过程 父 beforeDestroy - 子 beforeDestroy - 子 destroyed - 父 destroyed 总结父组件先开始子组件先结束 98. vue v-model双向绑定的原理 model 更新视图使用数据劫持观察者模式 参考 95视图更新modelv-model本质是valueinput的语法糖用户输入监听input变化从而更新value input v-modelsomething 相当于 input v-bind:valuesomething v-on:inputsomething $event.target.value 如果在自定义组件中会利用名为value的prop和input事件 父组件 ModelChild v-modelmessage/ModelChild子组件 div{{value}}/divprops:{value: String }, methods: {test1(){this.$emit(input, 小红)}, },99. vue3响应和vue2响应式区别 vue2 使用object.defineProperty, vue3 使用proxyObject.defineProperty 无法检测数组下标变化且智能代理对象的第一层属性如果对象属性还是对象需要递归遍历proxy代理也是第一层子属性如果是对象则通过reactive继续做代理实现深度代理Object.defineProperty无法监控新增加的属性需要借助$set, proxy没问题proxy再ie上有兼容问题 100. vue2 和 vue3 diff算法分别说一下 diff 算法就是比较新旧两颗树找出差异化利用打补丁的方式进行局部渲染触发时机是 _update(_rende()) 同层比较只比较统一层级不会跨级tag不相同直接删除重建不在深度遍历tag和key相同认为是相同节点继续深度遍历 101. hash 和 history 模式实现原理 hash 是带 # 地址变化不会重新请求通过hasChange事件可以知道hash是否发生变化history实现主要具有html5 发布的两个标准pushState 和 replaceState这两个api可以再改变url但是不会重新发送请求区别 hash兼容低版本但是history不行hash有# history没有刷新页面hash模式可以正常加载到hash对应页面而history没有处理的话会返回404一般需要后端将所有页面都配置重定向路由 102. vue-router路由钩子函数是什么执行顺序是什么 钩子函数总类有全局守卫路由守卫组件守卫全局路由守卫 beforeEach全局前置守卫路由跳转前触发比如拦截登录验证beforeResolve全局解析守卫和beforeEach类似路由跳转前触发再beforeEach和组件内beforeRouteEnter后afterEach前触发afterEach, 全局后置钩子发生在beforeEach和beforeResolve 之后没有next 路由守护 beforeEnter 再beforeEach后执行 const router new VueRouter({routes: [{path: /foo,component: Foo,beforeEnter: (to, from, next) {// ...}}]组件守卫 为配置路由的组件添加生命周期函数 template... /template script export default{data(){//...},beforeRouteEnter (to, from, next) {// 在渲染该组件的对应路由被 confirm 前调用// 不能获取组件实例 this,可以通过next(vm {// 通过 vm 访问组件实例})// 因为当守卫执行前组件实例还没被创建},beforeRouteUpdate (to, from, next) {// 在当前路由改变但是该组件被复用时调用// 举例来说对于一个带有动态参数的路径 /foo/:id在 /foo/1 和 /foo/2 之间跳转的时候// 由于会渲染同样的 Foo 组件因此组件实例会被复用。而这个钩子就会在这个情况下被调用。// 可以访问组件实例 this},beforeRouteLeave (to, from, next) {// 导航离开该组件的对应路由时调用// 可以访问组件实例 this} } /script触发顺序 1 触发进入其它路由 2 调用要离开路由的组件守卫beforeRouteLeave 3 调用全局的前置守卫beforeEach 4 在重用的组件里调用 beforeRouteUpdate 5 在路由配置里调用 beforeEnter 6 解析异步路由组件 7 在将要进入的路由组件中调用beforeRouteEnter 8 调用全局的解析守卫beforeResolve 9 导航被确认 10 调用全局的后置钩子afterEach。 11 触发 DOM 更新mounted。 12 执行beforeRouteEnter守卫中传给 next的回调函数 103. vue项目中你做了哪些优化 对象层级不要太深否则会影响性能不需要响应的数据不要放在data中可以使用Object.freeze冻结v-if, v-show, computed,watch分场景使用大数据表格做虚拟列表防止内存泄漏组件销毁把全局变量和时间清理图片懒加载路由懒加载异步路由按需加载防抖和节流应用服务器端渲染或则预渲染 104. nextTick 原理 作用vue更新dom不会立马更新是异步的nextTick回调实在下次dom更新循环结束后回调原理使用了微任务和宏任务,和执行环境有关 PromiseMutationObserver h5新加额功能如果以前都不行则采用setTimeout 105. Vue.set原理 了解 Vue 响应式原理的同学都知道在两种情况下修改 Vue 是不会触发视图更新的。 在实例创建之后添加新的属性到实例上给响应式对象新增属性 直接更改数组下标来修改数组的值。 Vue.set 或者说是 $set 原理如下 因为响应式数据 我们给对象和数组本身新增了 ob 属性代表的是 Observer 实例。 当给对象新增不存在的属性首先会把新的属性进行响应式跟踪 然后会触发对象 ob 的 dep 收集到的 watcher 去更新当修改数组索引时我们调用数组本身的 splice 方法去 更新数组。 106. css盒子模型 ie盒子模型w3c盒子模型盒子模型有 内容content填充padding margin border区别 IE盒子模型把content算到border和padding里面去了 107. css 优先级 !import 行内样式 ID选择器 类选择器 标签选择器 通配符 继承 浏览器默认值 108. link 和 import区别 link是XHTML标签除了加载CSS外还可以定义RSS等imprt只加载csslink和htm元素同时加载import需要等元素全部加载才会加载link无兼容性问题import在css2.1引入link支持js控制dom去改变元素import不支持 109. rem em vh px含义 rem 相对于根元素文字大小相关em 相对于父元素大小vw vh 视口的宽高px 分辨率 110. 解决chrome 小于12px像素问题 -webkit-text-size-adjust: none 110 new操作符做了什么 创建空对象this指向该对象同时继承了该函数原型属性和方法加载到this引用中新创建的对象由this所引用并返回this 111. iframe 优缺点 优点 解决加载缓存满的第三方内存如广告等安全的沙盒机制并行加载脚本 缺点 iframe会阻塞主页面的onload事件内容为空也需要加载时间没有语意 112. href和src区别 请求资源类型不同 href指向网络资源建立和当前元素或当前文档链接之间的联系src会将资源下载到文档中比如脚本img图片 作用不同 href当前文档和引用资源建立关系src替换当前内容 浏览器解析不同 href 不会阻塞浏览器的解析下载src会停止其他资源下载处理将资源加载编译执行完 113. rgba 和 opacity透明效果有和不同 rgba 设置后后代元素不会继承不透明属性opactiy 会继承父类的opacity属性 114 position的值relative和absolute分别是相对谁进行定位的 relative 相对定位, 相对于自己本身在正常文档流中位置进行定位absolute决定定位相对于近一级定位不是static的父元素进行定位fixed 绝对定位相对于浏览器或则iframe进行定位static 默认值没有丁定位在正常文档流中定位sticky粘性定位容器位置根据文档流计算得出 115 calc, support, media calc 函数动态计算长度支持 - / 等support 主要检查浏览器支付支持css某个属性media 媒体查询 针对不同媒体类型定义不同样式 116 如何画三角形 .a {width: 0;height: 0;border-width: 100px;border-style: solid;border-color: transparent #0099CC transparent transparent;transform: rotate(90deg); /*顺时针旋转90°*/ } div classa/div117 css 兼容性问题如何解决 每个浏览器都有默认的margin和padding解决方案 全局 *{margin:0, padding: 0}chrome默认中文不小于12px解决方案 通过-webkit-text-size-adjust: none 解决 118 document.write 和innerHtml区别 document.write 绘制整个界面innerHtml 绘制一部分 117 闭包 闭包三个特点 函数嵌套函数函数内部可以引用外部的参数和变量参数和变量不会被垃圾回收 118 垃圾回收机制 标记清除法 进入环境打上标记 离开环境清除标记引用计数法引用了一次1移出了引用-1 119 vuex store状态存储响应 State 基础数据定义了状态的数据结构Getter 从基础数据派生的数据允许store获取数据 mapGetter辅助函数将store的getter映射到局部计算属性Mutation 唯一的更改store的状态方法 必须是同步Action 装饰器包裹了mutations可以异步不能直接改变状态Module 模块化vuex允许将多个store拆分成多个store且保存在单一的状态树中 120 谈谈对 keep-alive了解 一般用作组件状态保留的避免重新渲染 一般结合路由和动态组件一起使用用于缓存组件提供了include和exclude支持字符串和正则表达式 exclude优先级高于include两个钩子函数activated和deactviated被激活和被移除触发 121 vue路由模式 hash 使用url hash来计算支持所有浏览器history 依赖html5 history apiabstract 只有所有js环境比如node.js 122 vue key的作用 key是对vue的vnode的唯一标记通过keydiff操作会更准更快特别是在带有for循环的时候需要设置key #123 vue3 新的更改 监听机制 解决了数组下表该变化和新增属性不能被监听到的问题模板 修改了作用域插槽把插槽改成函数自会影响子组件渲染对象是组件声明 124 vue模板编译原理 模板字符串 转成 elementAST解释器 切割vue生成AST语法树大量正则匹配AST进行静态节点标记主要来做虚拟dom的渲染优化dom更新不需要diff静态节点使用elementAST生成render函数代码字符串组件渲染调用render函数就可以 125 性能6大指标 加载优化执行优化渲染优化样式优化脚本优化 6 V8 引擎优化 126 如何防止回流 回流产生 窗口调整大小改变字体增加样式或则删除样式内容变化input操作domoffsetWidth 和offsetHeight多层内联样式 如何避免 避免使用table布局dom 叶子节点更改class避免多层内联样式设置动画最好脱离文档流操作元素可以先设置不可见 display: none 操作完成在显示出来避免频繁操作dom 127 移动端优化 使用css3动画开启硬件加速touch代替click合理使用requestAnimationFRame少用setTimeout避免css3阴影渐变效果 127 Array.forEach 和 Array.map forEach 遍历每个元素但不返回新的数组map 遍历数组并返回新的数组 128 vue 导入图片方式 css 静态引入image中的srcimport 语句URL 方式 129 浅拷贝 深拷贝 浅拷贝 let aar [2,3,[4,6]] let arr2 [..arr] arr[0] ! arr2[0] arr[2] arr2[2]let obj (a: 1, b: {c: 1}) let obj1 {...obj} let obj2 Object.assign(obj2, obj)深拷贝 let arr [2,3,[4,6]] let arr2 JSON.parse(JSON.stringify(arr))function deepCopy(obj, cache new WeakMap) {if (type obj ! object || obj null) {return obj }if (cache.has(obj)){return cache.get(obj)}const clone Array.isArray(obj) ? [] : {}cache.set(obj, clone)for (let key in obj) {if (Object.prototype.hasOwnProperty.call(obj, key)) {clone[key] deepCopy(obj[key], clone)}}return clone }130 useVModel 改变props数据通用方法 // useVModel.jsimport {computed} from vue const cacheMap new WeakMap(); export function useVModel(props, propName, emit) {return computed({get() {if (cacheMap.has(props[propName])) {return cacheMap.get(props[propName])}const proxy new Proxy(props[propName], {get(target, key) {return Reflect.get(target, key)},set(target, key, value) {emit(update: propName, {...target, [key]: value})return true}})cacheMap.set(props[propName], proxy)return proxy},set(val) {emit(update: propName, val)}}) }// 使用 // index.vue templatediv classchild v-modelobjRef/child/div /templatescript setup langts import { ref } from vue; import Child from ./Child.vue const objRef ref({name: jiang}) /scriptstyle scoped /style // Child.vue templateinput v-modelmodelValue.namediv class{{ modelValue.name }}/div /templatescript setup langts import {useVModel} from ./useVModel.jsconst props defineProps({// modelValue 是默认名字 使用v-mode111 传值modelValue: {type: Object,default: {}} }) const emits defineEmits([update:modelValue]) const nameProxy useVModel(props, modelValue, emits) /scriptstyle scoped /style140 主题切换 html[data-themedark]{--text-color: #fff;--bg1: #102128; }:root {--text-color: #333;--bg1: #fbd988; }html切换主题 html data-themedark/html141 防止debug setInterval(function() {debuggetCheck(); }, 1000)var debuggetCheck function () {function doCheck(a) {if (( a / a)[length] ! 1 || a % 20 0){//动态生成匿名函数函数体是 debugger 动态生成的类似eval(function(){}[constructor](debugger)());} else {(function(){}[constructor](debugger)());}doCheck(a)}try{doCheck(0)}catch(err) {} }debuggetCheck();131 ES6 Promise 和 Promise A Promise A 是Promise的一个规范包含 promise状态pending初始状态fulfilled最终状态rejected最终环境then方法promise解析过程resolvePromise ES6的Promise是PromiseA规范的实现并增加了all和race等promise状态流转 pending-resolve-fulfilledpending-reject-rejected
http://www.w-s-a.com/news/641997/

相关文章:

  • 网站制作过程内容深圳最好的活动策划公司
  • 深圳网站关键词排名查询公司网站怎么做啊
  • 微网站 制作平台广州电商聚集地
  • 建设外国商城网站网站服务器 虚拟主机
  • 天河网站建设开发电子商务公司名字大全
  • 站长推荐为何用wdcp建立网站连不上ftp
  • 云南旅行社网站开发学编程多久可以写游戏辅助
  • 推广网站的步骤网站备案号中信息有变
  • 优秀企业建站织梦能不能做门户网站
  • 广东省建设局官方网站wordpress 自动安装 插件怎么用
  • 哪类小网站容易做h5页面制作代码
  • 北京网站建设公司华网百度热搜seo
  • 小清新博客网站中山做网站公司
  • 美团做团购网站如何新建自己的网站
  • 安卓软件制作网站电子商务网站建设实训总结报告
  • 肃宁网站制作价格外国设计师素材网站
  • 自已建网站用jsp做的可运行的网站
  • 外贸建站代理网站建设设计公司哪家好
  • 普升高端品牌网站建设台州中兴建设咨询有限公司网站
  • 模板演示网站移动网站开发公司
  • 网站管理办法制度公司招聘信息
  • 宜昌市建设监理协会网站免备案免费域名
  • 河北省建设银行网站首页备案号怎么放到网站
  • 做电脑网站用什么软件有哪些wordpress版权修改
  • 加强部门网站建设工作wordpress文章页横幅
  • 中英网站怎么做wordpress本地音乐
  • 万网提供的网站建设服务的具体项目祥云平台网站建设
  • ftp网站怎么看后台的代码网站 制作软件
  • 网站开发软件教程网站tag 怎么实现
  • 中国建设监理协会化工监理协会网站彩票站自己做网站吗