力扣刷题
只刷了栈和队列
-
用栈实现队列:
- 需要一个
stackIn
和一个stackOut
数组(都是栈) - 进队就放入
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>