Open fanmingfei opened 4 years ago
html
<div id="people"></div>
<div id="language"></div>
js
const renderList = [];
const firstMemoized = { value: null, next: null };
let currentMemoized = firstMemoized;
function reRender(memoized) {
currentMemoized = firstMemoized
renderList.forEach(r => r());
}
function render(container, component) {
renderList.push(() => container.innerHTML = component());
container.innerHTML = component();
}
function tmpl(iterators, ...params) {
return iterators.reduce((a, b, index) => a + params[index - 1] + b)
}
const setTimeout = (...args) => {
const memoized = currentMemoized.next ? currentMemoized.next : (window.setTimeout(...args), currentMemoized.next = { value: undefined, next: null });
currentMemoized = currentMemoized.next;
}
const setInterval = (...args) => {
const memoized = currentMemoized.next ? currentMemoized.next : (window.setInterval(...args), currentMemoized.next = { value: undefined, next: null });
currentMemoized = currentMemoized.next;
}
function useState(initialValue) {
const memoized = currentMemoized.next ? currentMemoized.next : currentMemoized.next = { value: initialValue, next: null };
currentMemoized = currentMemoized.next;
const setState = newValue => (memoized.value = newValue) && reRender();
return [
memoized.value,
setState
]
}
function People() {
const [name, setName] = useState('LiLei')
const [old, setOld] = useState(1)
let i = 1
setInterval(() => {
i++
console.log(i)
setOld(i)
}, 1000)
return tmpl`<div>My name is ${name}, I\'m ${old} years old.</div>`;
}
function Language() {
const [language, setLanguage] = useState('Toy')
setTimeout(() => {
setLanguage('HTML')
}, 2000)
setTimeout(() => {
setLanguage('CSS')
}, 4000)
setTimeout(() => {
setLanguage('JavaScript')
}, 6000)
return tmpl`<div>I love ${language}</div>`
}
render(document.querySelector('#people'), People)
render(document.querySelector('#language'), Language)
const {render, useState, tmpl} = outer()
function outer() {
const cache = {}
let curComponent
const render = (node, component) => {
curComponent = component.name
const tpl = component()
cache[component.name] = () => node.innerHTML = parse(tpl)
node.innerHTML = parse(tpl)
}
const useState = initValue => {
const component = curComponent
const data = {value: initValue}
const setData = newValue => {
data.value = newValue
cache[component]()
}
return [data, setData]
}
const parse = tpl => {
const [strings, ...varis] = tpl
return strings.reduce((res, item, i) => {
res = res.concat(item, varis.slice(i, i+1)[0]?.value)
return res
},[]).join('')
}
const tmpl = (...p) => p
return {render, useState, tmpl}
}
function People() {
const [name, setName] = useState('LiLei')
const [old, setOld] = useState(1)
let i = 1
setInterval(()=>{
i++
setOld(i)
}, 1000)
return tmpl`<div>My name is ${name}, I\'m ${old} years old.</div>`;
}
function Language() {
const [language, setLanguage] = useState('Toy')
setTimeout(()=>{
setLanguage('HTML')
}, 2000)
setTimeout(()=>{
setLanguage('CSS')
}, 4000)
setTimeout(()=>{
setLanguage('JavaScript')
}, 6000)
return tmpl`<div>I love ${language}</div>`
}
render(document.querySelector('#people'), People)
render(document.querySelector('#language'), Language)
const makeHook = (hooks) => {
let currentComponent
let fns = {}
for(let fnName in hooks) {
fns[fnName] = (...args)=> hooks[fnName](currentComponent)(...args)
}
return {
setComponent(Component) {
currentComponent = Component
},
hooks: fns
}
}
function createEvent () {
const map = new Map()
return (Component) => {
if (map.has(Component)) return map.get(Component)
const events = new Map()
const obj = {
on(name, fn) {
if (!events.has(name)) events.set(name, [])
events.get(name).push(fn)
},
emit(name, ...args) {
console.log(name, ...args)
if (!events.get(name)) return false
for (let fn of events.get(name)) {
fn instanceof Function && fn(...args);
}
}
}
map.set(Component, obj)
return obj
}
}
const makeEvent = createEvent()
const current = {}
const hooks = makeHook({
useState: Component => initialValue => {
let value = {value: initialValue}
const setValue = (newValue)=> {
console.log(newValue)
value.value = newValue
makeEvent(Component).emit('stateChange', value)
}
return [value, setValue]
},
useStateChange: Component => (callback) => {
makeEvent(Component).on('stateChange', (value)=>callback(value))
},
})
function makeHTML (tmpl) {
const html = [...tmpl[0]].reduce((str, curr, i)=>{
let {value} = tmpl[i] || {value: ''}
return str += value + curr
})
return html
}
const { useState, useStateChange } = hooks.hooks
function render(dom, Component) {
hooks.setComponent(Component)
const tmpl = Component()
useStateChange(()=>{
dom.innerHTML = makeHTML(tmpl)
})
dom.innerHTML = makeHTML(tmpl)
}
const tmpl = (...arg)=>arg
function People() {
const [name, setName] = useState('LiLei')
const [old, setOld] = useState(1)
let i = 1
setInterval(()=>{
i++
setOld(i)
}, 1000)
return tmpl`<div>My name is ${name}, I\'m ${old} years old.</div>`;
}
function Language() {
const [language, setLanguage] = useState('Toy')
setTimeout(()=>{
setLanguage('HTML')
}, 2000)
setTimeout(()=>{
setLanguage('CSS')
}, 4000)
setTimeout(()=>{
setLanguage('JavaScript')
}, 6000)
return tmpl`<div>I love ${language}</div>`
}
render(document.querySelector('#people'), People)
render(document.querySelector('#language'), Language)
题目: html
javascript
在 javascript 最上面增加代码,实现以下效果。
效果图:![](https://gw.alicdn.com/tfs/TB1r_7Gx2b2gK0jSZK9XXaEgFXa-600-598.gif)