// 节流 每过一段时间执行一次
// 定时器实现
function throttle(fn, wait) {
var timer = null
var args, that
if (typeof fn !== 'function') {
throw new TypeError('Expected a function')
}
wait = +wait || 0
return function(){
args = arguments, that = this
if(!timer){
timer = setTimeout(function(){
timer = null
},wait)
return fn.apply(that, args)
}
}
}
var f = throttle(function(a){
console.log(a)
},1000)
f(1);f(2);f(3);f(4);f(5);
// 时间戳实现
function _throttle(fn, wait) {
var preTime = 0
var args, that
if (typeof fn !== 'function') {
throw new TypeError('Expected a function')
}
wait = +wait || 0
return function(){
var dif = new Date().getTime()-preTime
if(preTime === 0 || dif >= wait){
args = arguments;
that = this
preTime = new Date().getTime()
return fn.apply(that, args)
}
}
}
var f = _throttle(function(a){
console.log(a)
console.log(this)
},1000)
f(1);f(2);f(3);f(4);f(5);
// 防抖 指定时间内没有新的触发才执行
function debounce(fn, time){
var timer = null
var args = arguments, that = this
return function(){
args = arguments;
that = this
clearTimeout(timer)
timer = setTimeout(function(){
fn.apply(that, args)
}, time)
}
}
function debounce(fn, wait, leading = false){
var preTime = 0,timer = null,result
var args , that ;
if (typeof fn !== 'function') {
throw new TypeError('Expected a function')
}
wait = +wait || 0
var invokeFunc = function(){
// 防止同一触发执行在 lead 为 true 时执行2次
if(args && that){
const a = args, t = args
args = that = null
result = fn.apply(a, t)
}
return result
}
var run = function(interval){
timer = setTimeout(function(){
var difTime = new Date().getTime()-preTime
if(difTime>=wait){
clearTimeout(timer)
timer = null
return invokeFunc()
}else {
run(wait-difTime)
}
}, interval)
}
return function(){
args = arguments
that = this
preTime = new Date().getTime()
if(!timer){
run(wait)
if(leading) {
return invokeFunc()
}
}
return result
}
}
var f = debounce(function(a){
console.log(a)
},1000,true)
f(1);f(2)
//
function sort(arr){
if(arr.length<=1){
return arr
}
for (let i = 0; i < arr.length-1; i++) {
for (let j = i+1; j < arr.length; j++) {
if(arr[i]>arr[j]){
[arr[i],arr[j]] = [arr[j],arr[i]]
}
}
}
return arr
}
function sort(arr){
if(arr.length<=1){
return arr
}
for (let i = 0; i < arr.length-1; i++) {
var minIndex = i;
for (let j = i+1; j < arr.length; j++) {
if(arr[j]<arr[minIndex]){
minIndex = j
}
}
[arr[i],arr[minIndex]] = [arr[minIndex],arr[i]]
}
return arr
}
sort([2,1,2323,22,22,323,4])
function quickSort(arr){
if(arr.length<2){
return arr
}
var left = [],
right = [],
middle = arr.splice(Math.floor(arr.length/2),1)[0]
for (let index = 0; index < arr.length; index++) {
const element = arr[index];
if(element >= middle){
right.push(element)
}else {
left.push(element)
}
}
return [...quickSort(left),middle, ...quickSort(right)]
}
quickSort([2,1,2323,22,22,323,4])
// 深拷贝 递归
var deepCopy = (function (){
let arr = []
const that = {}
function copy(target) {
if(this !== that){
arr = []
console.log('外部调用时清空arr,防止arr无限大')
}
if(Array.isArray(target)) {
return target.map(item=>{
const findItem = arr.find(i=>{return i.item === item})
if(findItem){
return findItem.itemCopy
}else {
const value = copy.call(that, item)
arr.push({
item: item,
itemCopy: value
})
return value
}
})
}
if(Object.prototype.toString.call(target) === '[object Object]'){
const re = {}
Object.keys(target).forEach(key => {
const ele = target[key]
const findItem = arr.find(i=>{return i.item === ele})
if(findItem){
re[key] = findItem.itemCopy
return
}
debugger
const value = copy.call(that,ele)
re[key] = value
arr.push({
item: ele,
itemCopy: value
})
console.log(arr.length)
})
return re
}
return target
}
return copy
})()
function deepCopy(source){
const copy = []
const _copy = function(target){
const findItem = arr.find(i=>{return i.item === target})
if(findItem){
return findItem.itemCopy
}
if(isObject(target)){
const re = {}
for(let [k,v] of Object.entries(target)){
copy.push({
item: v,
itemCopy:
})
re[k] = _copy(v)
}
return re
}else if(Array.isArray(target)){}
}
return _copy(source)
}
function isObject(target){
return Object.prototype.toString.call(target) === '[object Object]'
}
deepCopy({a:{a:1}})
function deepCopy(target){
const copy = function(source){
const re = {}
const stack = [{value:source, parent: re, key:'value'}]
while (stack.length>0){
const ele = stack.pop()
if(isObject(ele.value)){
ele.parent[ele.key] = {}
for(let [k,v] of Object.entries(ele.value)){
if(isObject(v)){
ele.parent[ele.key][k] = {}
stack.push({
value: v,
parent: ele.parent[ele.key][k],
key: k
})
}else if(Array.isArray(v)){
ele.parent[ele.key][k] = []
v.forEach((i,index)=>{
stack.push({
value: i,
parent: ele.parent[ele.key][k],
key: index
})
})
}else {
ele.parent[ele.key][k] = v
}
}
}else if(Array.isArray(ele.value)) {
ele.parent[ele.key] = []
for(let i=0;i<ele.value.length;i++){
let v = ele.value[i]
if(isObject(v)){
ele.parent[ele.key][i] = {}
stack.push({
value: v,
parent: ele.parent[ele.key][i],
key: i
})
}else if(Array.isArray(v)){
ele.parent[ele.key][i] = []
v.forEach((i,index)=>{
stack.push({
value: i,
parent: ele.parent[ele.key][i],
key: index
})
})
}else {
ele.parent[ele.key][i] = v
}
}
}else {
ele.parent[ele.key] = ele.value
}
}
return re['value']
}
if(isObject(target)){
return copy(target)
}else if(Array.isArray(target)){
return target.map(i=>{
return copy(i)
})
}else {
return target
}
}
function deepCopy(target){
let stack = []
let re =[] // copy结果存储
// 初始化栈
if(isObject(target)){
stack.push({
value: target,
parent: re,
key: 0
})
}else if(Array.isArray(target)){
target.forEach((v,index)=>{
stack.push({
value: v,
parent: re,
key: index
})
})
}else {
return target
}
// 解决循环引用
const copyed = []
while (stack.length>0){
const ele = stack.pop()
const exits = copyed.find(i=>i.source === ele.value)
if(exits){
ele.parent[ele.key] = exits.target
continue
}
if(isObject(ele.value)){
ele.parent[ele.key] = {}
copyed.push({
source: ele.value,
target: ele.parent[ele.key]
})
for(let [k,v] of Object.entries(ele.value)){
stack.push({
value: v,
parent: ele.parent[ele.key],
key: k
})
}
}else if(Array.isArray(ele.value)) {
ele.parent[ele.key] = []
copyed.push({
source: ele.value,
target: ele.parent[ele.key]
})
ele.value.forEach((v,k)=>{
stack.push({
value: v,
parent: ele.parent[ele.key],
key: k
})
})
}else {
ele.parent[ele.key] = ele.value
}
}
return isObject(target)? re[0] : re
}
/*
http:连接过程:
3次握手
客户端 SYN=1 seq=j
服务端 ACK=1 ack=j+1 seq=k
客户端 ACK=1 ack=k+1
4次挥手
客户端 FIN=j
服务端 ACK=j+1
服务端 FIN=k
客户端 ACK=k+1
http2
头部压缩
多路复用,同个域名只需要一个连接,省去了tcp连接时间
https
传输加密,需要配置ssl证书
vue
双向绑定: Object.defineProperties
生命周期: beforeCreate created mounted beforUpdate updated beforeDestory destoryed errorCaptured activated deactivated
透传:provide inject
指令:Vue.directive 全局指令。选项:
bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前
componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。
unbind:只调用一次,指令与元素解绑时调用。
// 注册
Vue.directive('my-directive', {
bind: function () {},
inserted: function () {},
update: function () {},
componentUpdated: function () {},
unbind: function () {}
})
// 注册 (指令函数)
Vue.directive('my-directive', function () {
// 这里将会被 `bind` 和 `update` 调用
})
vue router 生命周期: beforeEach afterEach beforeEnter beforeRouterEnter beforeRouterLeave beforeRouterUpdate
vue3 组合式API
双向绑定: 使用Proxy,对于ie还是使用 Object.defineProperties const a = reactive({title: '22'}) const a = ref(22)
生命周期: setup(props, context) return 值将会在其他生命周期和模板中使用,ref值在模板中是展开的,不需要使用.value访问。 使用其他生命周期时为 on+原周期钩子 如 onMounted = (()=>{}) 这些钩子只能在setup中同步使用。另外 原beforeCreate created钩子没有,对应的逻辑应该直接写在 setup 钩子函数里面
透传: 直接在setup中 使用 provide(name, ref(value)) 在子组件中 接受 const name = inject('name', 可选默认值) provide值必须是ref、reactive的才能是响应式的
指令: createApp().directives 或者组件中使用directives选项
// 注册
app.directive('my-directive', {
// 指令是具有一组生命周期的钩子:
// 在绑定元素的父组件挂载之前调用
beforeMount() {},
// 绑定元素的父组件挂载时调用
mounted() {},
// 在包含组件的 VNode 更新之前调用
beforeUpdate() {},
// 在包含组件的 VNode 及其子组件的 VNode 更新之后调用
updated() {},
// 在绑定元素的父组件卸载之前调用
beforeUnmount() {},
// 卸载绑定元素的父组件时调用
unmounted() {}
})
// 注册 (功能指令)
app.directive('my-directive', () => {
// 这将被作为 `mounted` 和 `updated` 调用
})
组件注册: app.component(name, Component) 局部注册:组件的components:{name:Component}选项
新增内置组件: Teleport 组件 用于将组件渲染到指定的container,如body
<teleport to="body">
<div>A</div>
</teleport>
新增插件:插件是自包含的代码,通常向 Vue 添加全局级功能。它可以是公开 install() 方法的 object,也可以是 function
// plugins/i18n.js
export default {
install: (app, options) => {
app.config.globalProperties.$translate = (key) => {
return key.split('.')
.reduce((o, i) => { if (o) return o[i] }, options)
}
app.provide('i18n', options)
}
}
// 使用方式
const app = createApp(Root)
const i18nStrings = {
greetings: {
hi: 'Hallo!'
}
}
app.use(i18nPlugin, i18nStrings)
React
生命周期:
初始化: constructor getDerivedStateFromProps render(必须实现) componentDidMount
更新: getDerivedStateFromProps shoudComponentUpdate render getSnapshotBeforeUpdate(在最近一次渲染输出(提交到 DOM 节点)之前调用。它使得组件能在发生更改之前从 DOM 中捕获一些信息(例如,滚动位置)。此生命周期的任何返回值将作为参数传递给 componentDidUpdate()) componentDidUpdate
销毁: componentWillUnmount
错误处理: getDerivedStateFromError componentDidCatch
static getDerivedStateFromError(error) {
// 更新 state 使下一次渲染可以显示降级 UI
return { hasError: true };
}
componentDidCatch(error, info) {
// "组件堆栈" 例子:
// in ComponentThatThrows (created by App)
// in ErrorBoundary (created by App)
// in div (created by App)
// in App
logComponentStackToMyService(info.componentStack);
}
渲染组件到指定元素: ReactDOM.createPortal(child, container) 类似vue3中Teleport组件
Fragments 用于返回多个元素
render() {
return (
<React.Fragment>
<ChildA />
<ChildB />
<ChildC />
</React.Fragment>
);
}
React Hook 16.8版本的新增特性,Hook 不能在 class 组件中使用,只能在函数最外层调用 Hook。不要在循环、条件判断或者子函数中调用
useState const [count, setCount] = useState(0);
useEffect
// 相当于 componentDidMount 和 componentDidUpdate componentWillUnmount
useEffect(() => {
ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
// 副作用函数还可以通过返回一个函数来指定如何“清除”副作用
return () => {
ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
};
},[count]); // 仅仅在count更新时执行
useContext:
接收一个 context 对象(React.createContext 的返回值)并返回该 context 的当前值。useContext(MyContext) 相当于 class 组件中的 static contextType = MyContext 或者 <MyContext.Consumer>。
useReducer:
useState 的替代方案。它接收一个形如 (state, action) => newState 的 reducer,并返回当前的 state 以及与其配套的 dispatch 方法。
const initialState = {count: 0};
function reducer(state, action) {
switch (action.type) {
case 'increment':
return {count: state.count + 1};
case 'decrement':
return {count: state.count - 1};
default:
throw new Error();
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<>
Count: {state.count}
<button onClick={() => dispatch({type: 'decrement'})}>-</button>
<button onClick={() => dispatch({type: 'increment'})}>+</button>
</>
);
}
useCallback:
把内联回调函数及依赖项数组作为参数传入 useCallback,它将返回该回调函数的 memoized 版本,该回调函数仅在某个依赖项改变时才会更新
useMemo:
useCallback(fn, deps) 相当于 useMemo(() => fn, deps)。
useRef:useRef 返回一个可变的 ref 对象,其 .current 属性被初始化为传入的参数
const inputEl = useRef(null); 类似:const inputEl = React.createRef();
自定义Hook:如果函数的名字以 “use” 开头并调用其他 Hook,我们就说这是一个自定义 Hook
function useFriendStatus(friendID) {
const [isOnline, setIsOnline] = useState(null);
return isOnline;
}
// 使用
const isOnline = useFriendStatus(props.friend.id);
*/
复习
©著作权归作者所有,转载或内容合作请联系作者
- 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
- 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
- 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
推荐阅读更多精彩内容
- 小学寒假培训机构哪个好?名思教育13年专注1对1,承诺用心教好每一个孩子。 语文学习并不是没有方法,只是需要较长时...
- express cnpm install express --save cnpm install nodemon ...