[Daily handwritten JS code]

Article directory

previous blog

other people's blog

1. Handwritten JS

1-1 Array methods

Array flattening on January 5th

  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))

January 6 Array.prototype.map()

  1. Extremely simple way of writing, only pass in 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)

January 7th 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;
};

January 8 Array.prototype.forEach()

forEach is similar to map, but forEach does not return results

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);
	}	
}

January 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;
        }

On January 21, the class array is converted into an array

 <script>
        let likeNum = document.getElementsByClassName('likeSum')[0].childNodes
        console.dir(likeNum);
        // 方法一:
        console.log(Array.from(likeNum))
        // 方法二: 
        console.log(Array.prototype.slice.call(likeNum))
        // 方法三
        console.log([...likeNum])

        // 没有想到的方法
        // 方法四:利用concat
        Array.prototype.concat.apply([], document.querySelectorAll('div'));
    </script>

1-2 JS-related application questions

1-2-1 Determine the type of JS instance

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

January 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 [January 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 inheritance [January 11th]

    <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);


        // ES6
        class 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 Cross-domain front-end [January 15th]

    <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 shallow copy [January 16]

  • Object.assign({},obj) The second layer and above are shallow copies
        // 方法一
        let obj1 = Object.assign({
    
    }, obj)
        console.log(obj1);
        obj1.c.c = 2
        obj1.b = 3
        console.log(obj);
        // 方法二
        let obj2 = {
    
    };
        for(let key in obj) {
    
    
            obj2[key]  = obj[key] 
        }
        obj2.a = 3
        obj2.c.c = 11
        console.log(obj);
        // 方法三
        let obj3 = {
    
    }
        obj3 = obj

1-2-6 Deep copy [January 17th]

        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 deduplication [January 18]

        var arr = [1, 1, 'true', 'true', true, true, 15, 15, false, false, undefined, undefined, null, null, NaN, NaN, 'NaN', 0, 0, 'a', 'a', {
    
    }, {
    
    }];

        // 方法一: set
        let newArr = [...new Set(arr)]
        console.log(newArr);
        

        // 方法二:两层遍历+splice
        function 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);    //会改变原来的arr
                        j--;
                    }  
                }
            }
            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+indexOf
        const newArr2 = [];
        arr.filter((item, index) =>{
    
    
            if(arr.indexOf(item) === index) {
    
    
                newArr2.push(item)
            }
        })
        console.log(newArr2);


        // 方法四 : includes
        let 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 Convert list to tree structure / tree to list [January 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 anti-shake 【2023/1/22】

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

1-2-10 Throttling【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 Implement an 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; // 初始化xhr
                if (window.XMLHttpRequest) {
    
     //兼容IE
                    xhr = 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 Realize the automatic actuator of the 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 Implement hash routing【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 Implement history routing【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 Publish Subscribe【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]) return
                this.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]
                    }
                }
            }
        }
        //test
        let 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 Object-Oriented Programming

1-3-1 this keyword

1-3-1-1 call [January 14]

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

1-3-1-2 apply [January 12]


        Function.prototype.apply = function(context, args) {
    
    
            context = (context === undefined || context === null) ? window : context
            context._fn = this
            let result = context._fn(...args)
            delete context._fn
            return result
        }

1-3-1-3 bind [January 13]

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

1-3-1-4 Realize a 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 Regular

1-5-1 regular mobile phone number 【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 color 【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 mailbox 【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 = '[email protected]'
 console.log(reg4.test(str4));

2. Framework

2-1 vue

2-1-1 Data proxy 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 Parent-child components

<!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 Component parameter passing

<!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 = render function of react

{
    
    
  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);
  }
  // 普通DOM
  const 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;
}

Guess you like

Origin blog.csdn.net/hannah2233/article/details/128571616