学习周总结:第二次(12.25~12.31)

力扣刷题

只刷了栈和队列

  • 用栈实现队列:

    1. 需要一个stackIn和一个stackOut数组(都是栈)
    2. 进队就放入stackIn,出队就放入stackOut,然后出
  • 匹配问题都用栈来实现

  • 滑动窗口最大值还没看懂

封装了一个可编辑的table组件(基于原生HTML)

  • 父组件:
<template>
    <my-table
        :data="tableData"
        @submit="editData"
    />
</template>

<script setup lang="ts">
import { Ref, ref } from 'vue';
import MyTable from './my-ui/MyTable/MyTable.vue';
import { editDataArgs, tableData } from './interface/my-table';

const tableData: Ref<tableData> = ref({
    tHead: [
        {
            key: 'id',
            text: '学号',
            editable: false
        },
        {
            key: 'name',
            text: '姓名',
            editable: false
        },
        {
            key: 'age',
            text: '年龄',
            editable: false
        },
        {
            key: 'chinese',
            text: '语文',
            editable: true
        },
        {
            key: 'math',
            text: '数学',
            editable: true
        },
        {
            key: 'english',
            text: '英语',
            editable: true
        },
    ],
    tBody: [
        {
            id: 1,
            name: '张三',
            age: 16,
            chinese: 121,
            math: 132,
            english: 138
        },
        {
            id: 2,
            name: '李四',
            age: 18,
            chinese: 100,
            math: 120,
            english: 131
        },
        {
            id: 3,
            name: '王五',
            age: 19,
            chinese: 98,
            math: 150,
            english: 67
        }
    ]
});

/**
 *
 * @param index 第几项
 * @param key   是哪个值
 * @param value 新值
 * @param text  这个值的tHead的text
 * @param removeInput  移除input框的方法
 */
const editData = ({index, key, value, text}: editDataArgs, removeInput: Function) => {
    if (tableData.value.tBody[index][key] != value) {
        const cfm: boolean = window.confirm(`你要确定将数据下标为[${ index }]项的${ text }的内容修改为${ value }`);
        if (cfm) {
            tableData.value.tBody.forEach((item: any, idx: any) => {
                idx === index && (item[key] = value);
            });
        } else {
            removeInput();
        }
    }
};

</script>

<style scoped lang="scss">

</style>
  • table-edit组件:
<template>
    <table border="1" class="my-table">
        <thead>
        <tr>
            <th
                v-for="info of tHead"
                :key="info.key"
            >
                {{ info.text }}
            </th>
        </tr>
        </thead>

        <tbody>
        <tr
            v-for="(item, index) of tBody"
            :key="item.id"
        >
            <td
                v-for="(value, key) in item"
                :key="key"
                @click.stop="showEditInput($event, key.toString(), index)"
            >
                {{ value }}
            </td>
        </tr>
        </tbody>
    </table>
</template>

<script setup lang="ts">
import { createApp, reactive, toRefs } from 'vue';
import EditInput from './EditInput.vue';
import { stateType } from '../../interface/my-table';

let editInputApp: any = null;

const state: stateType = reactive({
    key: '',
    value: '',
    index: -1,
    text: ''
});

const props = defineProps({
    data: {
        type: Object,
        default: () => ({
            tHead: [],
            tBody: []
        })
    }
});

const emit: any = defineEmits(['submit']);

const {tHead, tBody} = toRefs(props.data);

const showEditInput = (event: any, key: string, index: number) => {
    console.log('event:', event, 'key:', key, 'index:', index);
    editInputApp && removeEditInputApp();
    if (!checkEditable(key)) return;

    const target = event.target;
    const oFrag = document.createDocumentFragment();

    editInputApp = createApp(EditInput, {
        value: target.textContent,
        setValue
    });

    if (editInputApp) {
        editInputApp.mount(oFrag);
        target.appendChild(oFrag);
        target.querySelector('.edit-input').select();
    }

    setData({index, key, text: findText(key), value: ''});
};

const setData = ({index, key, text, value = ''}: stateType) => {
    state.key = key;
    state.index = index;
    state.text = text;
    state.value = value;
};

const setValue = (value: number | string) => {
    state.value = value;
    emit('submit', {...state}, removeEditInputApp);
};

const findText = (key: string) => {
    const {text} = tHead.value.find((item: any) => item.key === key);
    return text;
};

const removeEditInputApp = () => {
    editInputApp && editInputApp.unmount();
    setData({
        index: -1,
        key: '',
        value: '',
        text: ''
    });
};

const checkEditable = (key: string) => {
    const {editable} = tHead.value.find((item: any) => item.key === key);
    return editable;
};

window.addEventListener('click', () => removeEditInputApp(), false);

</script>

<style scoped lang="scss">
.my-table {
    width: 50%;
    border-collapse: collapse;
}

tr {
    height: 30px;

    td {
        position: relative;
        text-align: center;
        cursor: pointer;
    }
}
</style>
  • input组件:
<template>
    <input
        type="text"
        class="edit-input"
        :value="value"
        @input="onInput"
        @blur="onBlur"
        @click="onClick"
    />

</template>

<script setup lang="ts">
import { ref } from 'vue';

const props = defineProps({
    value: {
        type: String,
        default: ''
    },
    setValue: {
        type: Function,
        default: () => {
        }
    }
});

const inputValue = ref(props.value);

const onInput = (e) => {
    inputValue.value = e.target.value.trim();
};

const onClick = (e) => {
    e.stopPropagation();
};

const onBlur = () => {
    props.setValue(inputValue.value);
};
</script>

<style scoped lang="scss">
.edit-input {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    box-sizing: border-box;
    border: 1px solid orange;
    text-align: center;
    outline: none;
    font-size: 16px;
}
</style>

读Vuejs设计与实现

看了前三章

一、权衡的艺术

虚拟DOM的意义在于使找出差异的性能消耗最小化。

原生JS操作DOM方法、虚拟DOM和innerHTML操作页面的性能还需要考虑对开发者的心智负担,综合来说虚拟DOM是一个很好的方法

二、框架设计的核心要素

框架设计要考虑开发体验,提供有好的警告信息

Tree-Shaking:是一种排除dead code的机制,通过/*#__PURE__/*来辅助进行Tree-Shaking

三、Vue.js 3 的设计思路

Vue.js是一个声明式框架,不仅可以通过模板来描述UI,还支持用虚拟DOM来描述,而且更加灵活
  • 最基本渲染器的实现
<div id="root"></div>
<script>
    const root = document.querySelector('#root');
    const node = {
        tag: 'div',
        props: {
            onClick: () => alert('hello')
        },	
        children: [
            {
                tag: 'h1',
                children: 'click me'
            }
        ]
    };


    const render = (node, root) => {
        const el = document.createElement(node.tag);

        for (const key in node.props) {
            if (/^on/.test(key)) {
                el.addEventListener(
                        key.slice(2).toLowerCase(),
                        node.props[key]
                );
            }
        }

        if (typeof node.children === 'string') {
            const text = document.createTextNode(node.children);
            el.appendChild(text);
        } else {
            node.children.forEach(item => render(item, el));
        }
        root.appendChild(el);
    };

    render(node, root);

</script>
  • 组件的本质:是一组虚拟DOM元素的封装,可以返回一个虚拟DOM的函数
<div id="root"></div>
<script>
    const root = document.querySelector('#root');
    const MyComponent = {
        render () {
            return {
                tag: 'div',
                props: {
                    onClick: () => alert('hello')
                },
                children: 'click me'
            };
        }
    };
    const vnode = {
        tag: MyComponent
    };


    const mountElement = (vnode, root) => {
        const el = document.createElement(vnode.tag);

        for (const key in vnode.props) {
            if (/^on/.test(key)) {
                el.addEventListener(
                        key.slice(2).toLowerCase(),
                        vnode.props[key]
                );
            }
        }

        if (typeof vnode.children === 'string') {
            const text = document.createTextNode(vnode.children);
            el.appendChild(text);
        } else if (Array.isArray(vnode.children)) {
            vnode.children.forEach(item => renderer(item, el));
        }
        root.appendChild(el);
    };

    const mountComponent = (vnode, container) => {
        const subtree = vnode.tag.render();
        renderer(subtree, container);
    };

    function renderer (vnode, container) {
        if (typeof vnode.tag === 'string') {
            mountElement(vnode, container);
        } else if (typeof vnode.tag === 'object') {
            mountComponent(vnode, container);
        }
    }

    renderer(vnode, root);
</script>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ianarua

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值