1.HTTP和HTTPS
2.301和302,怎么判断500
- 永久性重定向、临时性,都可以改post
- 500
- 原因:前端JSON格式错误(比如有值没传),后端无判空,运行错误。
- 捕获:
.catch(error => {console.log(error.response.data.error.message)
}
3.跨域
4.闭包
- 函数嵌套
- 自执行函数
- 保存变量、保护变量
- 防止污染
- 垃圾回收、内存
5.垂直居中
- flex
- 绝对定位
6.自适应
7.node接触过吗
听说过koa2、pm2守护进程
8.mvvm
9.vue单向数据流
9.vue组件参数传递方式
9.vue双向数据绑定和单项绑定
双向绑定实例
定义:
组件中变量(data中或props中)的值改变时,文本框的值也跟着改变,文本框的值改变(用户操作,比如输入,清空)时,组件中属性(data中或props中)的值 也同步变化
语法:
v-model
<input v-model&#61;"multiple" type&#61;"text" >
export default {
props: [&#39;packageData&#39;],data: () &#61;> ({originPrice: 300,multiple: 1})
}
以上是双向绑定,
一边是文本框的值,
一边是data属性multiple,
只要一边的值发生变化,另一边将同步改变
单项绑定实例
修改组件中变量(data中或props中)的值改变时,文本框的值也跟着改变
语法:
<input type&#61;"text" id&#61;"agentCode" v-bind:value&#61;"orgFullName" value&#61;"" >
当修改data中orgFullName的值时,文本框的值也跟着改变
可以简写:
:value&#61;"orgFullName"
<template><div class&#61;"clearfloat"><p class&#61;"Tstore-buleTitle fl" style&#61;"line-height:28px;">测试信息</p><div class&#61;"Tcode-box fl"><input type&#61;"text" id&#61;"testId" :value&#61;"orgFullName" value&#61;"" ></div><a class&#61;"Tcode-btn fl" &#64;click&#61;"queryAgent" >验证</a></div></template>
<script>import testService from &#39;&#64;/services/testService&#39;export default {data: () &#61;> ({orgFullName: &#39;&#39;}),methods: {queryAgent: function () {
this.orgFullName &#61; &#39;&#39;testService.queryAgent($(&#39;#testId&#39;).val()).then(testValue &#61;> {if (testValue && testValue.orgFullName) {this.orgFullName &#61; testValue.orgFullName}})}}}
</script>
使用 v-model 来进行数据双向绑定。要牢记&#xff1a;
<input v-model&#61;"something">
这不过是以下示例的语法糖&#xff1a;
<input
v-bind:value&#61;"something"
v-on:input&#61;"something &#61; $event.target.value">
10.vue的响应式和观察者模式
- 在数据变化的时候&#xff0c;视图也会随着改变&#xff0c;这就是响应式
- VUE使用Object.defineProperty 中getter和setter方法中的观察者模式来实现响应式
Object.defineProperty
次方法是对象方法&#xff0c;在一个对象上定义一些新的属性及方法&#xff0c;或改变对象的现有方法&#xff0c;并返回这个对象。
举个示例看一下&#xff1a;
var mVal &#61; 0;
var o &#61; {};
Object.defineProperty(o, &#39;m&#39;){get: function(){console.log(&#39;这里监听获取m值");return mVal;},set: function(newVal){console.log(&#39;这里监听修改m值");mVal &#61; newVal;},enumerable : true,configurable : true
}
o.m &#61; 88;
console.log(o.m);
分析&#xff1a;当调用o.m给对象o中的m属性赋值的时候&#xff0c;会调用set方法&#xff0c;将m的值赋给mVal&#xff0c;此时就会调用get方法&#xff0c;获取这个值。
通过这种方式我们就可以实现一个简单的vue双向绑定了&#xff0c;给data中的所有属性加上get和set方法
观察者模式
- 观察者模式分为注册环节与发布环节。
将需要修改的属性集中注册一下&#xff0c;当处理完后一起发布出去。
function Observer(){this.dep &#61; [];register(fn){this.dep.push(fn)}notify(){this.dep.forEach(item &#61;> item())}
}
依次注册多个想要执行的函数
const wantCake &#61; new Observer();
wantCake.register(console.log(&#39;call dish&#39;));
wantCake.register(console.log(&#39;call jaks&#39;));
wantCake.register(console.log(&#39;call mejdh&#39;));在完成后通知所有客户并执行函数
wantCake.notify()
1、init阶段&#xff0c;VUE实例的data属性reactive化&#xff0c;加上get、set方法
function defineReactive(obj: Object, key: String, ...){const dep &#61; new Dep();Object.defineProperty(o, key){get: function reactiveGetter(){...dep.depend();return value;...},set: function reactiveSetter(newVal){...val &#61; newVal;dep.notify();...},enumerable : true,configurable : true}
}
const Dep{static target: ?Watcher;subs: Array<Watcher>;depend () {if (Dep.target) {Dep.target.addDep(this)}}notify () {const subs &#61; this.subs.slice()for (let i &#61; 0, l &#61; subs.length; i < l; i&#43;&#43;) {subs[i].update()}}
}
这里的dep是一个观察者类&#xff0c;每一个属性都有一个dep&#xff0c;调用getter时去dep里注册函数&#xff0c;在调用setter时&#xff0c;执行注册的函数。
2、mount阶段
mountComponent(vm: Component, el: ?Element, ...) {vm.$el &#61; el...updateComponent &#61; () &#61;> {vm._update(vm._render(), ...)}new Watcher(vm, updateComponent, ...)...
}class Watcher {getter: Function;constructor(vm: Component, expOrFn: string | Function, ...) {...this.getter &#61; expOrFnDep.target &#61; this this.value &#61; this.getter.call(vm, vm) ...}
}
在mount时会创建一个Watcher类&#xff0c;这个类是链接dep与vue组件的桥梁。每一个watcher对应一个vue component。
在new Watcher()时会调用getter方法&#xff0c;此时会调用render重新渲染函数。
render函数会访问data属性&#xff0c;这时就去调用这个属性的getter函数
get: function reactiveGetter () {....dep.depend()return value....},
depend () {if (Dep.target) {Dep.target.addDep(this)}
}
在depend函数中&#xff0c;dep就是watcher对象本身。这样每次渲染这个组件时&#xff0c;如果用到了这个属性&#xff0c;组件对应的watcher都会注册到这个属性的dep中。这个过程被称为依赖收集。
在收集完所有的依赖后&#xff0c;如果这个属性变化&#xff0c;就会通知watcher去更新相关的组件。
3、更新阶段
属性改变时&#xff0c;回去调用dep里面的notify函数&#xff0c;然后通知所有的watcher去调用update函数进行更新。
notify () {const subs &#61; this.subs.slice()for (let i &#61; 0, l &#61; subs.length; i < l; i&#43;&#43;) {subs[i].update()}
}
4、流程展示
reactive属性
setter
Dep
notify
watcher
re-render
VueComponent
5、总结一下
第一步&#xff1a;组件初始化时给data中所有属性添加get、set&#xff0c;reactive化&#xff1b;然后注册一个Watcher对象&#xff0c;此时watcher会立即调用组价你的render去生成虚拟DOM&#xff0c;此时会用到data&#xff0c;所以会触发get函数&#xff0c;将当前的watcher注册到sub里。
第二步&#xff1a;在data属性变化时&#xff0c;会遍历sub中所有watcher对象&#xff0c;通知它们去渲染组件。
借鉴文章&#xff1a;https://zhuanlan.zhihu.com/p/88648401
11.小程序使用过吗
无
12.性能优化
回答的是&#xff1a;
- 生命周期的优化
- CSS spires
- 懒加载
- 标签的位置
13.数组去重
- num &#61; […new Set(num)]
- 用对象的key
- 用数组的indexof查找
14.正则&#xff0c;匹配一个电话号码
15.判断素数
function isPrime(num){var n&#61;Math.sqrt(num);for(var i&#61;2;i<&#61;n;i&#43;&#43;){if(num%i&#61;&#61;0){ return false;}}return true;
}console.log(isPrime(3))
16.26进制字符串相加
var readline &#61; require(&#39;readline&#39;);
var rl &#61; readline.createInterface({ input: process.stdin,output: process.stdout
});
function convertToTen(str){var num&#61;0,index&#61;1;for(let i&#61;str.length-1;i>&#61;0;i--){num&#43;&#61;((str.charCodeAt(i)-97)%26) * index;index &#61; index * 26;}return num;
}
function convertToTwoteenSix(num){var str&#61;&#39;&#39;;while(num!&#61;&#61;0){var temp &#61; num%26;str&#43;&#61;String.fromCharCode(temp&#43;97);num &#61; parseInt(num/26);}return str.split(&#39;&#39;).reverse().join(&#39;&#39;);
}
var inputs &#61; [];
rl.on(&#39;line&#39;, function(line) { var data &#61; line.trim().toLowerCase(); var a &#61; convertToTen(data);inputs.push(a);if(inputs.length&#61;&#61;&#61;2){console.log(convertToTwoteenSix(inputs[0]&#43;inputs[1]));inputs&#61;[];}
});
var ConvertNum &#61; function (str) {var n &#61; 0;var s &#61; str.match(/./g);var j &#61; 0;for (var i &#61; str.length - 1, j &#61; 1; i >&#61; 0; i--, j *&#61; 26) {var c &#61; s[i].toUpperCase();if (c < &#39;A&#39; || c > &#39;Z&#39;) {return 0;}n &#43;&#61; (c.charCodeAt(0) - 64) * j;}return n;}var teststr &#61; "AB";alert(ConvertNum(teststr));var Convert26&#61;function(num){var str&#61;"";while (num > 0){var m &#61; num % 26;if (m &#61;&#61; 0){m &#61; 26;}str &#61; String.fromCharCode(m &#43; 64) &#43; str;num &#61; (num - m) / 26;}return str;}var num &#61; 28;alert(Convert26(num));
17.COOKIE和session
18.rem vh
vh就是当前屏幕可见高度的1%&#xff0c;也就是说height:100vh &#61;&#61; height:100%;但是当元素没有内容时候&#xff0c;设置height:100%&#xff0c;该元素不会被撑开&#xff0c;此时高度为0&#xff0c;但是设置height:100vh&#xff0c;该元素会被撑开屏幕高度一致。
CDG-fit技术栈记录