文章目录

  • 一、 手写JS
    • 1-1 数组方法
      • 1月5号 数组扁平化
      • 1月6号 Array.prototype.map()
      • 1月7号 Array.prototype.filter()
      • 1月8号 Array.prototype.forEach()
      • 1月31号 Array.prototype.reduce()
      • 1月21号 类数组转为数组
    • 1-2 JS相关应用题
      • 1-2-1 判断JS实例的类型
        • 1月9号 instanceOf
      • 1-2-2 sleep【1月10号】
      • 1-2-3 js继承【1月11号】
      • 1-2-4 前端跨域【1月15号】
      • 1-2-5 浅拷贝【1月16号】
      • 1-2-6 深拷贝【1月17号】
      • 1-2-7 去重【1月18号】
      • 1-2-8 列表转成树形结构/ 树转列表【1月19.20】
      • 1-2-9 防抖 【2023/1/22】
      • 1-2-10 节流【2023/1/23】
      • 1-2-11 实现一个ajax【2023/2/2】
      • 1-2-12 实现generator的自动执行器【2023/2/3】
      • 1-2-13 实现hash路由【2023/2/10】
      • 1-2-14 实现history路由【2023/2/11】
      • 1-2-15 发布订阅【2023/2/12】
    • 1-3 面向对象编程
      • 1-3-1 this关键字
        • 1-3-1-1 call【1月14号】
        • 1-3-1-2 apply【1月12号】
        • 1-3-1-3 bind【1月13号】
        • 1-3-1-4 实现一个new【2023/2/1】
    • 1-4 Promise
      • 1-4-1 Promise.all【2023/124】
      • 1-4-2 Promise.reject【2023/1/25】
      • 1-4-3 Promise.resolve【2023/1/26】
      • 1-4-4 Promise.race【2023/1/27】
      • 1-4-5 Promise.prototype.catch【2023/1/28】
    • 1-5 正则
      • 1-5-1 正则手机号【2023/2/14】
      • 1-5-2 qq【2023/2/15】
      • 1-5-3 颜色【2023/2/16】
      • 1-5-4 邮箱【2023/2/17】
  • 二、 框架
    • 2-1 vue
      • 2-1-1 数据代理vue2【2023/2/19】
      • 2-1-2 父子组件
      • 2-1-3 组件传参
    • 2-2 react
      • 2-2-1 JSON2DOM = react的render函数

之前博客

  • instanceOf
  • Javascript数组去重
  • 继承
  • 手写bind
  • JS实现sleep,普通版+promise+async/await
  • 前端跨域以及解决++常见 http status
  • 请求响应头
  • 重绘重排
  • 防抖节流
  • 安全问题

别人博客

  • JavaScript高级语法之跨域(postMessage,CORS,JSONP)
  • 32个js手撸题目

一、 手写JS

1-1 数组方法

1月5号 数组扁平化

  1. map+push
let newArr = [];
const flatten = (arr, depth=1) => {arr.map((item) => {// debugger;if(depth > 0|| depth == 'Infinity')  (Array.isArray(item) ? flatten(item, depth-1): newArr.push(item) )  ;else  newArr.push(item)})return newArr;}
console.log(flatten(arr,Infinity))
  1. reduce + concat
function flatDeep(arr, d = 1) {return d > 0? arr.reduce((acc, val) => acc.concat(Array.isArray(val) ? flatDeep(val, d - 1) : val), []): arr.slice();
}
  1. const res1 = arr.flat(Infinity);

  2. const res2 =JSON.stringify(arr).replace(/\[\|\]/g, '').split(',').map(item => parseInt(item))

1月6号 Array.prototype.map()

  1. 极其简单写法,只传入callback
    const arr = [1, 2, 3]Array.prototype.map = function (callback) {const res = [];for (let i = 0; i < this.length; i++) {res.push(callback(this[i], i, this))}return res;}const res = arr.map((ele, index, arr) => {return ele * 2})console.log(res)
})
Array.prototype.map = function(callback, objThis) {// 排除回调非函数情况if(typeof callback !== 'function') {throw new TypeError("callback type error!");}// 排除this为非可迭代对象情况if(this == null || typeof this[Symbol.iterator] !==  function) {throw new TypeError(`${this} is not a iterable`);}const res = [];for(let i = 0; i < this.length; ++i) {res.push(callback.call(objThis, this[i], i, this))}return res
}const arr = [1, 2, 3]const res = arr.map((ele, index, arr) => {return ele * 2})console.log(res)

1月7号 Array.prototype.filter()

Array.prototype._filter = function (callback) {const res = [];for (let i = 0; i < this.length; i++) {callback(this[i], i, this) && res.push(this[i]) }return res;
};

1月8号 Array.prototype.forEach()

forEach和map类似,但是forEach不返回结果

Array.prototype._forEach = function(callback, objThis) {if(typeof callback !== "function") {throw new TypeError("callback type error!")}for(let i = 0; i < this.length; i++) {callback.call(objThis, this[i], i, this);}
}

1月31号 Array.prototype.reduce()

  arr.reduce(function(){},initValue)Array.prototype.reduce = function(fn,initValue) {let result = initValue === undefined ? this[1] : initValue;for(let i =0; i<this.length ;i++){result = fn(result, this[i],i,this)}return result;}

1月21号 类数组转为数组

 <script>let likeNum = document.getElementsByClassName('likeSum')[0].childNodesconsole.dir(likeNum);// 方法一:console.log(Array.from(likeNum))// 方法二: console.log(Array.prototype.slice.call(likeNum))// 方法三console.log([...likeNum])// 没有想到的方法// 方法四:利用concatArray.prototype.concat.apply([], document.querySelectorAll('div'));</script>

1-2 JS相关应用题

1-2-1 判断JS实例的类型

typeof,instanceOf,Object.prototype.toString().call()

1月9号 instanceOf

function _instanceOf(left, right) {const rightProto = right.prototype;const leftProto = left.__proto__;while(leftProto.__proto__ !== null) {if(rightProto === leftProto) {return true;}}return false
}
// 测试用例
function Person () {}
const no = new Person()

1-2-2 sleep【1月10号】

 <script>// 普通版本function sleep (slTime) {let start = new Date()while(new Date - start <= slTime) {}}const t5 = new Date()sleep(3000)const t6 = new Date()console.log(t6 - t5)// promise 实现function sleep (slTime) {return  new Promise(resolve =>{setTimeout(resolve,slTime)})}const t1 = new Date();sleep(3000).then(()=>{const t2 = new Date();console.log(t2-t1);})// async,await实现function sleep (slTime) {return  new Promise(resolve =>{setTimeout(resolve,slTime)})}(async function test(){const t1 = new Date();await sleep(3000)const t2 = new Date();console.log(t2 - t1);}())</script>

1-2-3 js继承【1月11号】

    <script>// ES5// function father(age, name) {//     this.age = age;//     this.name = name;// }// father.prototype.say = function() {//     console.log('爸爸在说话');// }// function Child(age, name, sex) {//     father.call(this, age, name);//     this.sex = sex// }// Child.prototype = new father()// let child11 = new Child(20, '哈哈', '女');// child11.say();// console.log(child11);// ES6class Father {constructor(name, sex) {this.name = name; this.sex = sex;}sayHello() {console.log('爸爸说话');}}class Child extends Father {constructor(name, sex, age) {super(name, sex);this.age = age;}eat() {console.log(`${this.name}在吃饭`);}}const child = new Child('儿子');child.eat()</script>

1-2-4 前端跨域【1月15号】

    <script>function jsonP ({url, params, callback})  {return new Promise((resolve, reject) => {let script = document.body.createElement('script')window[callback] = function(data) {resolve(data)document.body.removeChild(script)}params = {...params, callback} let arr = [];for(let key in params) {arr.push(`${key} = ${params[key]}`)}script.src = `${url}?${arr.join('&')}`document.body.appendChild(script)})}jsonP({url: '',params: {wd: 'I love you'},callback: 'show'}).then(data => {console.log(data);})function jsonp({url, params, callback}){return new Promise((resolve, reject) => {//动态创建script标签let script = document.createElement('script');//处理传入的参数params = {...params, callback};//转换参数表达式let arr = []for(let key in params) {arr.push(`${key}=${params[key]}`)}//在路径中,参数用 & 隔开script.src = `${url}?${arr.join('&')}`//添加 script 标签document.body.appendChild(script);//声明回调函数window[callback] = function(data) {//执行异步函数resolve(data);//请求完后移除该script标签document.body.removeChild(script)}})}</script><!-- 在vue.config.js中添加如下配置:devServer: {proxy: "http://localhost:5000"
} -->

1-2-5 浅拷贝【1月16号】

  • Object.assign({},obj) 第二层以上就是浅拷贝
        // 方法一let obj1 = Object.assign({}, obj)console.log(obj1);obj1.c.c = 2obj1.b = 3console.log(obj);// 方法二let obj2 = {};for(let key in obj) {obj2[key]  = obj[key] }obj2.a = 3obj2.c.c = 11console.log(obj);// 方法三let obj3 = {}obj3 = obj

1-2-6 深拷贝【1月17号】

        let obj = {a: 1,b: 2,c: {c: 1,d: 2}}// 方法一let obj1 = JSON.parse(JSON.stringify(obj)) // 测试用例// console.log(obj1);// obj1.b = 22// obj1.c.c = 11// console.log(obj);// 方法二function deepClone(obj) {let objClone = Array.isArray(obj) ? [] : {}for(let key of Object.keys(obj)) {objClone[key] = (typeof obj[key] === 'object' ? deepClone(obj[key]) : obj[key])}return objClone}console.log(deepClone(obj))

1-2-7 去重【1月18号】

        var arr = [1, 1, 'true', 'true', true, true, 15, 15, false, false, undefined, undefined, null, null, NaN, NaN, 'NaN', 0, 0, 'a', 'a', {}, {}];// 方法一: setlet newArr = [...new Set(arr)]console.log(newArr);// 方法二:两层遍历+splicefunction unique(arr) {for(let i = 0; i < arr.length; i++) {for(let j = i+1; j < arr.length; j++){if(arr[i] === arr[j]){arr.splice(j, 1);    //会改变原来的arrj--;}  }}return arr;}console.log(unique(arr));console.log(arr);var arr = [1, 1, 'true', 'true', true, true, 15, 15, false, false, undefined, undefined, null, null, NaN, NaN, 'NaN', 0, 0, 'a', 'a', {}, {}];// 方法三 : filter+indexOfconst newArr2 = [];arr.filter((item, index) =>{if(arr.indexOf(item) === index) {newArr2.push(item)}})console.log(newArr2);// 方法四 : includeslet newArr3 = [];for (let i = 0; i<arr.length; i++) {if( !newArr3.includes(arr[i]) ) {newArr3.push(arr[i]);}}console.log(newArr3);// 方法五:filter + hasOwnProperty----------> 貌似有点点问题let obj = {}let result = arr.filter((item, index) => {return obj.hasOwnProperty(item) ? false : (obj[item] = true)})console.log(result);

1-2-8 列表转成树形结构/ 树转列表【1月19.20】

 <script>let arr = [{ id: 1, name: "部门1", pid: 0 },{ id: 2, name: "部门2", pid: 1 },{ id: 3, name: "部门3", pid: 1 },{ id: 4, name: "部门4", pid: 2 },{ id: 5, name: "部门5", pid: 2 },{ id: 6, name: "部门6", pid: 3 },];function get_tree(arr) {let list = [];arr.forEach(element => {const chiildren_arr = arr.filter(ele => {return element.id === ele.pid})if (chiildren_arr.length > 0) {element.children = chiildren_arr}if (element.pid === 0) {list.push(element);}});return list;}const result = get_tree(arr);console.log(result);//树转列表const ToList = TreeList => {const list = [];const dfs = (TreeList) => {TreeList.filter((item)=>{if(item.children) {dfs(item.children);delete item.children}list.push(item);})}dfs(TreeList)return list}console.log(ToList(result))</script>

1-2-9 防抖 【2023/1/22】

const debounce = (fn, delay) => {const timer = null;return function() {clearTimeout(timer)setTimeout(()=> {fn.apply(this, arguments)},delay)}
}

1-2-10 节流【2023/1/23】

const throttle = (fn, delay) => {const timer = null;return function() {if(timer) return;timer = setTimeout(()=>{fn.apply(this, arguments);timer = null;},delay)}
}

1-2-11 实现一个ajax【2023/2/2】

<!-- 实现一个AJAX异步调用和局部刷新,通常需要以下几个步骤:创建XMLHttpRequest对象,也就是创建一个异步调用对象.创建一个新的HTTP请求,并指定该HTTP请求的方法、URL及验证信息.设置响应HTTP请求状态变化的函数.发送HTTP请求.获取异步调用返回的数据.使用JavaScript和DOM实现局部刷新. -->
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>AJAX原生请求</title></head><body><button>点击发送请求</button><script>// 获取button元素const btn = document.getElementsByTagName('button')[0];// 绑定事件btn.onclick = function() {function Ajax(type, url, data, success) {var xhr = null; // 初始化xhrif (window.XMLHttpRequest) { //兼容IExhr = new XMLHttpRequest();} else {xhr = new ActiveXObject('Microsoft.XMLHTTP')}var type = type.toUpperCase();var random = Math.random(); //创建随机数// GET处理缓存问题if (type == 'GET') {if (data) {xhr.open('GET', url + '?' + data, true); //如果有数据就拼接} else {xhr.open('GET', url + '?t=' + random, true); //如果没有数据就传入一个随机数}xhr.send();// POST 设置请求头} else if (type == 'POST') {xhr.open('POST', url, true);xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");xhr.send(data);}xhr.onreadystatechange = function() { // 创建监听函数if (xhr.readyState == 4 && xhr.status == 200) {success(xhr.responseText);}}}// 调用函数Ajax('get', 'https://netease-cloud-music-api-crete722p-hannah-bingo.vercel.app/playlist/hot', "", function(data) {console.log(JSON.parse(data));});}</script>
</body></html>

1-2-12 实现generator的自动执行器【2023/2/3】


function run(gen) {let g = gen();function next(data) {let result = g.next(data);if (result.done) return result.value;if (result.value instanceof Promise) {result.value.then(data => next(data));} else {result.value(next);}}return next();
}// ======== e.g. ==========function func(data, cb) {console.log(data);cb();
}function *gen() {let a = yield Promise.resolve(1);console.log(a);let b = yield Promise.resolve(2);console.log(b);yield func.bind(null, a + b);
}
run(gen);
/**
output:
1
2
3
**/

1-2-13 实现hash路由【2023/2/10】

<!DOCTYPE html>
<html>
<head><title>hash 路由</title>
</head>
<body><header><a href="#home">首页</a><a href="#center">个人中心页</a><a href="#help">帮助页</a></header><p id="content"></p><script>window.addEventListener('hashchange', (e) => {let content = document.getElementById('content');content.innerText = location.hash;})
</script>
</body>
</html>

1-2-14 实现history路由【2023/2/11】


<!DOCTYPE html>
<html>
<head><title>history 路由</title>
</head>
<body><header><a onclick="changeRoute(this)" data-path="home">首页</a><a onclick="changeRoute(this)" data-path="center">个人中心页</a><a onclick="changeRoute(this)" data-path="help">帮助页</a></header><p id="content"></p><script>function changeRoute(route) {let path = route.dataset.path;/*** window.history.pushState(state, title, url)* state:一个与添加的记录相关联的状态对象,主要用于popstate事件。该事件触发时,该对象会传入回调函数。*        也就是说,浏览器会将这个对象序列化以后保留在本地,重新载入这个页面的时候,可以拿到这个对象。*        如果不需要这个对象,此处可以填 null。* title:新页面的标题。但是,现在所有浏览器都忽视这个参数,所以这里可以填空字符串。* url:新的网址,必须与当前页面处在同一个域。浏览器的地址栏将显示这个网址。*/changePage(path);history.pushState({ content: path }, null, path);}/*** 调用 history.pushState() 或者 history.replaceState() 不会触发 popstate 事件。* 点击后退、前进按钮、或者在 js 中调用 history.back()、history.forward()、history.go() 方法会触发*/window.addEventListener('popstate', (e) => {let content = e.state && e.state.content;changePage(content);});function changePage(pageContent) {let content = document.getElementById('content');content.innerText = pageContent;}
</script>
</body>
</html>

1-2-15 发布订阅【2023/2/12】

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><script>// 解答一class EventEmitter {constructor() {// key: 事件名// value: callback [] 回调数组this.events = {}}on(name, callback) {if (this.events[name]) {this.events[name].push(callback)} else {this.events[name] = [callback]}}off(name, callback) {if (!this.message[name]) return;if (!callback) {// 如果没有callback,就删掉整个事件this.message[name] = undefined;}this.message[name] = this.message[name].filter((item) => item !== callback);}emit(name, ...args) {if (!this.events[name]) returnthis.events[name].forEach(cb => cb(...args))}}// 解答二class EventEmiter {constructor() {this.cache = {}; //存放不同的事件}on(name, fn) { //事件名,回调if (this.cache[name]) {this.cache[name].push(fn)}else {this.cache[name] = [fn]; //添加新事件}}off(name, fn) { //删除事件的某个回调let tasks = this.cache[name]; //拿到对应的回调队列if (tasks) {const index = tasks.findIndex(f => f === fn);if (index >= 0) {tasks.splice(index, 1)}}}emit(name, once = false, ...args) {if (this.cache[name]) {//创建副本,如果回调函数内继续注册相同事件会造成死循环let tasks = this.cache[name].slice();for (let fn of tasks) {fn(...args)}if (once) {delete this.cache[name]}}}}//testlet eventsBus = new EventEmiter()let fn1 = function (name, age) {console.log(name, age)}let fn2 = function (name, age) {console.log('fn', name, age);}eventsBus.on("test", fn1)eventsBus.on("test", fn2)eventsBus.emit("test", false, "Jason", 18)// 解答三:// 发布订阅中心,on-订阅,off-取消订阅,emit发布,内部需要一个单独事件中心,events存储export default class EventBus   {constructor(){ this.events= {} }emit(eventName, data) {if(this.events[eventName] ){this.events[eventName].forEach(fn => fn(data))}}on(eventName, fn) {this.events[eventName] = this.events[eventName] || []this.events[eventName].push(fn)}off(eventName, fn) {if(this.events[eventName]) {for(let i in  this.events[eventName] ) {if(this.events[eventName][i] === fn) {this.events[eventName].splice(i,1);break;}}}}}
//Jason 18
//fn Jason 18</script>
</body></html>

1-3 面向对象编程

1-3-1 this关键字

1-3-1-1 call【1月14号】

        Function.prototype.call = (context, ...args) => {context = (context === undefined || context === null) ? window : context context._fn = thislet result = context._fn(...args)delete context._fnreturn result}

1-3-1-2 apply【1月12号】

Function.prototype.apply = function(context, args) {context = (context === undefined || context === null) ? window : contextcontext._fn = thislet result = context._fn(...args)delete context._fnreturn result}

1-3-1-3 bind【1月13号】

        Function.prototype.bind2 = function(context, ...args1) {context = (context === undefined || context === null) ? window : contextlet _this = this;return function(...args2) {context._fn = _this;let result = context._fn(...[...args1, ...args2])delete context._fnreturn result}}

1-3-1-4 实现一个new【2023/2/1】

// 手动实现一个 new 关键字的功能的函数 _new(fun, args) --> new fun(args)
function _new(fun, ...args) {if (typeof fun !== 'function') {return new Error('参数必须是一个函数');}let obj = Object.create(fun.prototype);let res = fun.call(obj, ...args);if (res !== null && (typeof res === 'object' || typeof res === 'function')) {return res;}return obj;
}

1-4 Promise

1-4-1 Promise.all【2023/124】

  Promise.all([1,2,4]);Promise.all = function(promises){return new Promise((resolve, reject) => {let count = 0;let arr = [];for(let i = 0; i<promises.length; i++) {promises[i].then(v=>{count++;arr[i] = v;if(count === promises.length) {// 修改状态resolve(arr);}}),r=>{reject(r);   }}})}

1-4-2 Promise.reject【2023/1/25】

 Promise.reject(reason)Promise.reject = function(reason) {return new Promise((resolve, reject) => {reject(reason);})}

1-4-3 Promise.resolve【2023/1/26】

   Promise.resolve = function(value) {return new Rromise((resolve, reject) => {if(value instanceof Promise) {value.then(v =>{resolve(v);},r=> {reject(r);})}else {resolve(value);}})}

1-4-4 Promise.race【2023/1/27】

  Promise.race = function(promises) {return new Promise((resolve, reject)=>{for(let i = 0; i<promises.length; i++) {promises[i].then(v=>{// 修改返回对象的状态为成功resolve(v)},r=>{reject(r)})}})}

1-4-5 Promise.prototype.catch【2023/1/28】

 Promise.prototype.catch = function(onRejected){return this.then(undefined, onRejected);}

1-5 正则

1-5-1 正则手机号【2023/2/14】

let reg1 = /^1[44578]\d{9}$/g;
let str1 = '15555555555'
console.log(reg1.test(str1));

1-5-2 qq【2023/2/15】

let reg2 = /^[1-9][0-9]{4,9}$/g;
let str2 = '159333'
console.log(reg2.test(str2));

1-5-3 颜色【2023/2/16】

let reg3 = /#?([0-9a-fA-F]{6}) | [0-9a-fA-F]{3}/g;
let str3 = '#abc'
console.log(reg3.test(str3));

1-5-4 邮箱【2023/2/17】

let reg4 = /^([A-Za-z0-9_\-\.]+)+@([A-Za-z0-9_\-\.]+)\.([A-Za-z]{2,6})$/g;var reg = /^([a-zA-Z]|[0-9])(\w|\-)+@[a-zA-Z0-9]+\.([a-zA-Z]{2,4})$/;
let str4 = 'a11bc@didi.com'console.log(reg4.test(str4));

二、 框架

2-1 vue

2-1-1 数据代理vue2【2023/2/19】

let number = 1;let person = {name: '张三',sex: '男',age: number}Object.defineProperty(person, 'age', {configurable: true,// writable: true,enumerable:true,get: function() {console.log('有人读取了age属性');return number},set: function(value) {console.log('有人修改了age属性,值是:',value);number = value}})console.log(person);

2-1-2 父子组件

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head><body><div id="root"><school /></div><script>// 子组件const student = Vue.extend({name: 'student',template: `<div>子组件</div>`,data() {return {};},beforeCreate() {console.log("子组件————beforeCreate...");},created() {console.log("子组件————create...");},beforeMount() {console.log("子组件————beforeMount...");},mounted() {console.log("子组件————mounted...");},beforeUpdate() {console.log("子组件————beforeUpdate...");},updated() {console.log("子组件————updated...");},beforeDestroy() {console.log("子组件————beforeDestroy...");},destroyed() {console.log("子组件————destroyed...");}})// 父组件const school = Vue.extend({name: 'school',template: `<div>{{text}}<button @click="handle">点击销毁</button><student/></div> `,components: {student},data() {return {text: "哈哈",};},methods: {handle() {this.$destroy();},},beforeCreate() {console.log("父组件————beforeCreate...");},created() {console.log("父组件————create...");},beforeMount() {console.log("父组件————beforeMount...");},mounted() {console.log("父组件————mounted...");},beforeUpdate() {console.log("父组件————beforeUpdate...");},updated() {console.log("父组件————updated...");},beforeDestroy() {console.log("父组件————beforeDestroy...");},destroyed() {console.log("父组件————destroyed...");},})const vm = new Vue({name: 'vm',el: '#root',components: {school}})</script></body></html>

2-1-3 组件传参

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body><div id="root"><!-- 方法一 --><!-- <school name="aaa" ref="school" @get-data="getData2"/> --><h1>方法二</h1><school name="aaa" ref="school" :getData = "getData2"/><student2/></div><!-- <div id="root2"><student2/></div> --><script>const student =  Vue.extend({name: 'student',template: `<div><h5>{{name}}</h5></div>`,data(){return {name: 'ntt'}}})const school =  Vue.extend({name: 'school',template: `<div><h2>{{name2}}</h2><h2>接收到的props之: {{name}}</h2><student/><hr/><hr/><hr/><button @click="sendData()">发送数据</button></div>`,// props: {//     name: {//         type: String,//         required: true,//         deafult: 'TY'//     },//     getData:{//         required: true//     }  // },props: ['name','getData'],mounted() {this.getData(this.name2)},data(){return {name2: 'TYUT'}},methods: {sendData() {this.$emit('get-data',this.name2)console.log(this.name2);}},components: {student}})// // 全局组件// const student2 = Vue.extend({//     template: `//     <h2>safafad</h2>//   `// })// Vue.component('student2', student2)const vm = new Vue({name: 'vm',el: '#root',components: {school},data() {return {jj:'nihao '}},// mounted() {//     this.$ref.school.$on('getData',this.getData)// },methods: {getData2(data) {console.log(data);}},mounted() {}})</script></body>
</html>

2-2 react

2-2-1 JSON2DOM = react的render函数

{tag: 'DIV',attrs:{id:'app'},children: [{tag: 'SPAN',children: [{ tag: 'A', children: [] }]},{tag: 'SPAN',children: [{ tag: 'A', children: [] },{ tag: 'A', children: [] }]}]
}
把上诉虚拟Dom转化成下方真实Dom
<div id="app"><span><a></a></span><span><a></a><a></a></span>
</div>
// 真正的渲染函数
function _render(vnode) {// 如果是数字类型转化为字符串if (typeof vnode === "number") {vnode = String(vnode);}// 字符串类型直接就是文本节点if (typeof vnode === "string") {return document.createTextNode(vnode);}// 普通DOMconst dom = document.createElement(vnode.tag);if (vnode.attrs) {// 遍历属性Object.keys(vnode.attrs).forEach((key) => {const value = vnode.attrs[key];dom.setAttribute(key, value);});}// 子数组进行递归操作vnode.children.forEach((child) => dom.appendChild(_render(child)));return dom;
}

【每日手写JS代码】相关推荐

  1. javascript算法+手写js面试题

    链表 function ListNode(val, next) {this.val = (val===undefined ? 0 : val)this.next = (next===undefined ...

  2. 【低代码】手写低代码中的编译器/翻译器

    编译器.解释器 相信计算机的同学对这两个词一定不陌生,从学计算机开始,我们就知道了计算机是二进制的世界,而我们用高级语言编写的代码计算机是无法理解的,编译器就是将我们编写的代码编译成计算机可以执行的二 ...

  3. MATLABSTM32CubeMX联合开发系列——不用手写一行代码就能实现CAN通讯

    MATLAB&STM32CubeMX联合开发系列--不用手写一行代码就能实现CAN通讯 从第一次搭建好MATLAB和STM32CubeMX的联合开发环境有一段时间了,之前已经发布了两个实例分享 ...

  4. 写JS代码让自己头秃的点

    写JS代码让自己头秃的点 主要还是自己没系统学习js的锅吧,记录一下. 匿名函数内用this 匿名函数中,this指代的是window对象,不是直观理解中的,局部this,这就会产生undefine的 ...

  5. 深度篇—— CNN 卷积神经网络(四) 使用 tf cnn 进行 mnist 手写数字 代码演示项目

    返回主目录 返回 CNN 卷积神经网络目录 上一章:深度篇-- CNN 卷积神经网络(三) 关于 ROI pooling 和 ROI Align 与 插值 本小节,细说 使用 tf cnn 进行 mn ...

  6. 关于使用eclipse写JS代码没有提示的解决方法

    关于使用eclipse写JS代码没有提示的解决方法 eclipse原本是不会自动提示JS代码的,但是可以通过安装插件实现JS代码的提示功能 首先:help->Eclipse Marketplac ...

  7. 手写YOLOv3|代码详细注释

    手写YOLOv3|代码详细注释 一. 数据预处理 一. Yolov3网络 一. Train 一. Detection 源代码:https://github.com/eriklindernoren/Py ...

  8. Tensorflow反卷积(DeConv)实现原理+手写python代码实现反卷积(DeConv)

    最近看到一个巨牛的人工智能教程,分享一下给大家.教程不仅是零基础,通俗易懂,而且非常风趣幽默,像看小说一样!觉得太牛了,所以分享给大家.平时碎片时间可以当小说看,[点这里可以去膜拜一下大神的" ...

  9. 原生 遍历_前端原生写js代码还是用vue等框架写项目?

    其实对于初入前端的同学来说,我个人推荐写原生.因为扎实的js基础是通过写原生代码逐步理解js的数据类型,语法,闭包,原型链,继承等知识,只有在项目中主动应用这些js的基本知识,才能逐步提高你的编码能力 ...

最新文章

  1. 10-GLBP Weighting //2.1.5(GNS3版本,后面都是如此注明)
  2. python通讯录管理程序的用户可行性_通讯录管理系统项目可行性分析
  3. 从LASSO回归到结构性稀疏:线性回归的正则项都带来了什么?
  4. Hive:表1inner join表2结果group by优化
  5. TP引用样式表和js文件及验证码
  6. 疯狂java 李刚 pdf_Java开发教程 – 《疯狂Java讲义第4版》PDF及代码+李刚
  7. Go语言开发实战课后编程题
  8. AvalonDock学习总结
  9. SovitChart工具1分钟快速开发前端统计图表
  10. VS高版本兼容XP系统
  11. python 桌面应用 h5_hdf 5文件格式及python中利用h5py模块读写h5文件
  12. 白话 贝叶斯公式_[白话解析] 深入浅出朴素贝叶斯模型原理及应用
  13. Android:修改电池容量
  14. Netgear WNDR3800 用 LAN口 替换 WAN口
  15. ENDNOTE中使用Adobe打开PDF后提示“只读无法保存”
  16. 曹旭东--关于无人驾驶
  17. 在你生日那天,哈勃望远镜看到了什么
  18. 《水经注地图服务》新版发布
  19. Ubuntu系统下Git版本控制使用教程|1-6
  20. ESP32 开发笔记(三)源码示例 13_IR_Send_RMT 使用RMT实现红外数据发送(NEC编码)

热门文章

  1. extjs资源库云平台 2013.7.20--综合信息发布平台
  2. Excel插件:核对两表的差异,1按单元格核对,2按行核对
  3. 解决$.ajax()请求异常~ jQuery提示parsererror错误解决办法
  4. 云队友丨“悟空”倒下,知乎难安
  5. 高品质混响延迟插件9个合集 – ValhallaDSP Bundle 2020 WiN
  6. 谷歌地图地名显示繁体字_阴阳师犬夜叉铁碎牙隐藏机制 犬夜叉铁碎牙隐藏技能介绍...
  7. 「AI癌症检测 」手机拍照就能检测肿瘤,也太牛了吧!
  8. 可盈可乐区块链行业周报(12.01-12.15)
  9. 在绝望中寻找希望-下篇 写给生活
  10. 京东价格保护高并发 | 七步走保证用户体验