『202410』每日积累

耶温

1162字约4分钟

2024-10-08

『08』『算法』『两数相除』

『Leetcode-两数相除』

var divide = function (dividend, divisor) { 
    // 溢出
    if (dividend === 0) return 0;
    if (dividend == -2147483648 && divisor == -1) return 2147483647; // 溢出
    const sign = (dividend > 0) ^ (divisor > 0) ? -1 : 1; // 符号

    let strT = Math.abs(dividend).toString(); // 被除数
    let d = Math.abs(divisor); // 除数
  
   
    let result = '0' // 结果
    let i = d.toString().length; // 被除数索引
    let s = parseInt(strT.slice(0, i)); // 截取相同位被除数

    while (i <= strT.length) { // 循环截取被除数
        let num = 0;  // 商
        while (s >= d) { // 循环除数
            s = s - d
            num++
        }
        result += num // 拼接商
        s = parseInt(s + strT[i]) // 拼接被除数
        i++
    }
    result = parseInt(result)
    return sign === 1 ? result : -result;
};

『08』『算法』『串联所有单词的字串』

『Leetcode-两数相除』

// 题解答案
var findSubstring = function(s, words) {
    if (!s || !words || !words.length) return [];
    let windows = {}, needs = {}, oneWordLen = words[0].length;
    for (let w of words) {
        needs[w] ? needs[w]++ : needs[w] = 1;
    }
    let l = 0, r = 0, count = 0, needsKeyLen = Object.keys(needs).length, ans = [];
    for (let i = 0; i < oneWordLen; i++) {
        windows = {};
        r = l = i;
        count = 0;
        while (r <= s.length - oneWordLen) {
            let w1 = s.slice(r, r + oneWordLen);
            r += oneWordLen;
            if (!needs[w1]) {
                windows = {};
                l = r;
                count = 0;
                continue;
            }
            windows[w1] ? windows[w1]++ : windows[w1] = 1;
            if (windows[w1] === needs[w1]) count++;
            while (count === needsKeyLen) {
                if (r - l === oneWordLen * words.length) ans.push(l);
                let w2 = s.slice(l, l + oneWordLen);
                l += oneWordLen;
                if (needs[w2]) {
                    windows[w2]--;
                    if (windows[w2] < needs[w2]) count--;
                }
            }
        }
    }
    return ans;
};

『08』『面试』『Vue 双向绑定原理』

Vue双向绑定原理主要是基于数据劫持和发布-订阅模式。

vue2.0 使用 Object.defineProperty 实现双向绑定,vue3.0 使用 Proxy 实现双向绑定。

  • defineProperty 只能劫持对象的属性,需要对每个对象的每个属性进行遍历,如果对象嵌套层级过深,则需要递归到底,手动定义 gettersettergettersetter 每次获取属性都会执行一次,如果属性值是对象,还需要深度遍历。
  • Proxy 可以劫持整个对象,并返回一个新对象,不需要对对象的每个属性进行遍历,省去不必要的性能消耗。Proxy 还可以直接监听对象而非属性,可以直接监听数组的变化,并且有多达13种拦截方法。

// vue2.0
function defineReactive(obj, key, val) {
    Object.defineProperty(obj, key, {
        enumerable: true,
        configurable: true,
        get() {
            console.log(`get ${key}`);
            return val;
        },
        set(newVal) {
            console.log(`set ${key}`);
            val = newVal;
        }
    })
}

// 测试
const obj = {};
defineReactive(obj, 'name', 'yeven');
obj.name; // get name
obj.name = 'yeven2'; // set name
// vue3.0
function reactive(obj) {
    return new Proxy(obj, {
        get(target, key) {
            console.log(`get ${key}`);
            return target[key];
        },
        set(target, key, newVal) {
            console.log(`set ${key}`);
            target[key] = newVal;
        }
    })
}
// 测试
const obj = {};
const proxyObj = reactive(obj);
proxyObj.name; // get name
proxyObj.name = 'yeven2'; // set name

proxyObj.age = 18; // set age
console.log(proxyObj.age); // get age

『08』『面试』『常用伪元素』

伪元素: 用于设置元素特定部分的外观。它们有 ::before::after 两种,分别用于在元素内容的前面和后面插入内容。

  • ::before: 在元素内容的前面插入内容。
  • ::after: 在元素内容的后面插入内容。
  • ::first-line: 设置元素的第一行文本的样式。
  • ::first-letter: 设置元素的第一个字母或第一个单词的样式。
  • ::selection: 设置用户选中文本的样式。
  • ::placeholder: 设置表单元素的占位符文本的样式。
email 代码演示
<style>
    .box::before {
        content: 'Before';
        color: red;
    }
    .box::after {
        content: 'After';
        color: blue;
    }
    .box::first-line {
        color: green;
    }
    .box::first-letter {
        color: yellow;
    }
    .box::selection {
        background-color: pink;
        color: white;
    }
    input::placeholder {
        color: red;
    }
</style>
<div class="box">Hello World</div>
<input type="text" placeholder="请输入内容">

伪类: 用于设置元素的特殊状态。它们有 :hover:active:focus:visited 等。

『08』『面试』『CSS 水平垂直居中』

  1. 使用 positiontransform 属性

.parent {
    position: relative;
    width: 300px;
    height: 300px;
    background-color: #ccc;
}

.child {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 100px;
    height: 100px;
    background-color: #f00;
}
  1. 使用 flex 布局

.parent {
    display: flex;
    justify-content: center;
    align-items: center;
    width: 300px;
    height: 300px;
    background-color: #ccc;
}

.child {
    width: 100px;
    height: 100px;
    background-color: #f00;
}
  1. 使用 grid 布局
.parent {
    display: grid;
    place-items: center;
    width: 300px;
    height: 300px;
    background-color: #ccc;
}

.child {
    width: 100px;
    height: 100px;
    background-color: #f00;
}

『08』『面试』『Vue 组件通信』

Vue2

  1. 父子组件通信
  • 父组件通过 props 向子组件传递数据。
  • 子组件通过 $emit 向父组件发送事件和消息。
  1. 兄弟组件通信
  • 使用事件总线(Event Bus)。
  • 使用 Vuex 状态管理。
  1. 祖孙组件通信
  • 使用 provideinject 进行跨组件通信。
  1. 跨组件通信
  • 使用 Vuex 状态管理。

Vue3

Vue3-组件通信

  1. 父子组件通信 与 Vue2 相同
  • 父组件通过 props 向子组件传递数据。
  • 子组件通过 $emit 向父组件发送事件和消息。
  1. 兄弟组件通信
  • 使用事件总线(Event Bus)。可以用 mitt 库。
  1. 祖孙组件通信
  • 使用 provideinject 进行跨组件通信。
  1. 跨组件通信
  • 使用 Vuex 或者 Pinia 状态管理。