Closed amenzai closed 5 years ago
webpack笔记 babel使用 rollup.js 使用:
参考1-构造函数和集成ES5 参考2-class 和 extends
参考
jquery 和 zepto 的简单使用 他俩如何使用原型
zepto 如何使用原型
var zepto = {} zepto.init = function(selector) { // resoure code 略 only write prototype var slice = Array.prototype.slice var dom = slice.call(document.querySelectorAll(selector)) return zepto.Z(dom, selector) } // use var $ = function(selector) { return zepto.init(selector) } // 构造函数 function Z(dom, selector) { var i, len = dom ? dom.length : 0 for(i = 0; i < len; i++) { this[i] = dom[i] } this.length = len this.selector = selector || '' } zepto.Z = function(dom, selector) { return new Z(dom, selector) } $.fn = { constructor: zepto.Z, css: function(key, value) { }, html: function(value) { } } zepto.Z.prototype = Z.prototype = $.fn
jQuery 如何使用原型
(function(window) { var jQuery = function(selector) { return new jQuery.fn.init(selector) } jQuery.fn = { constructor: jQuery, css: function(key, value) { alert('css') }, html: function(value) { return 'html' } } var init = jQuery.fn.init = function(selector) { var slice = Array.prototype.slice var dom = slice.call(document.querySelectorAll(selector)) var i, len = dom ? dom.length : 0 for (i = 0; i < len; i++) { this[i] = dom[i] } this.length = len this.selector = selector || '' } init.prototype = jQuery.fn window.$ = jQuery })(window)
$.fn.myMethod = function() {}
单线程:只有一个线程,同时只能做一件事(for 循环多次、alert),两段JS不能同时执行 原因:避免DOM渲染的冲突 解决方案:异步
什么是异步队列?何时被放入异步队列?轮询的过程
jquery1.5的变化:
$.ajax().done().fail().done() $.ajax().then(function(){}, function(){}).then()
jquery-deferred: 对扩展开放,对修改关闭 dtdAPI分为两类,用意不同:
function waitHandle() { // 定义 var dtd = $.Deferred() var wait = function(dtd) { var task = function() { console.log('执行完成') // 成功 dtd.resolve() // 失败 // dtd.reject() } setTimeout(task, 1000) // wait 返回 return dtd.promise() } // 最终返回 return wait(dtd) } // 使用(B 员工) var w = waitHandle() // promise 对象 $.when(w).then(function() { console.log('ok 1') }, function() { console.log('err 1') })
问题:
设计一个需求场景 -》用jquery实现 -》遇到的问题
浏览器渲染 DOM 是很慢的,运行 JS 快成一匹马
// 点击按钮,改变表格数据 // jquery demo // html // <div id="container"></div> // <button id="btn-change">change</button> // js var data = [{ name: '张三', age: '20', address: '北京' }, { name: '李四', age: '21', address: '上海' }, { name: '王五', age: '22', address: '广州' } ] // 渲染函数 function render(data) { var $container = $('#container') // 清空容器,重要!!! $container.html('') // 拼接 table var $table = $('<table>') $table.append($('<tr><td>name</td><td>age</td><td>address</td>/tr>')) data.forEach(function (item) { $table.append($('<tr><td>' + item.name + '</td><td>' + item.age + '</td><td>' + item.address + '</td>/tr>')) }) // 渲染到页面 $container.append($table) } $('#btn-change').click(function () { data[1].age = 30 data[2].address = '深圳' // re-render 再次渲染 render(data) }) // 页面加载完立刻执行(初次渲染) render(data) // 存在的问题就是,没有改变数据的地方,也会重新渲染
遇到的问题:
vdom:
snabbdom用法:
// <script src="https://cdn.bootcss.com/snabbdom/0.7.1/snabbdom.js"></script> // <script src="https://cdn.bootcss.com/snabbdom/0.7.1/snabbdom-class.js"></script> // <script src="https://cdn.bootcss.com/snabbdom/0.7.1/snabbdom-props.js"></script> // <script src="https://cdn.bootcss.com/snabbdom/0.7.1/snabbdom-style.js"></script> // <script src="https://cdn.bootcss.com/snabbdom/0.7.1/snabbdom-eventlisteners.js"></script> // <script src="https://cdn.bootcss.com/snabbdom/0.7.1/h.js"></script> var snabbdom = window.snabbdom // 定义 patch var patch = snabbdom.init([ snabbdom_class, snabbdom_props, snabbdom_style, snabbdom_eventlisteners ]) // 定义 h var h = snabbdom.h var container = document.getElementById('container') // 生成 vnode var vnode = h('ul#list', {}, [ h('li.item', {}, 'Item 1'), h('li.item', {}, 'Item 2') ]) patch(container, vnode) document.getElementById('btn-change').addEventListener('click', function () { // 生成 newVnode var newVnode = h('ul#list', {}, [ h('li.item', {}, 'Item 1'), h('li.item', {}, 'Item B'), h('li.item', {}, 'Item 3') ]) patch(vnode, newVnode) // 找出差异,渲染差异 })
// jquery例子改造 var snabbdom = window.snabbdom // 定义关键函数 patch var patch = snabbdom.init([ snabbdom_class, snabbdom_props, snabbdom_style, snabbdom_eventlisteners ]) // 定义关键函数 h var h = snabbdom.h // 原始数据 var data = [{ name: '张三', age: '20', address: '北京' }, { name: '李四', age: '21', address: '上海' }, { name: '王五', age: '22', address: '广州' } ] // 把表头也放在 data 中 data.unshift({ name: '姓名', age: '年龄', address: '地址' }) var container = document.getElementById('container') // 渲染函数 var vnode function render(data) { var newVnode = h('table', {}, data.map(function (item) { var tds = [] var i for (i in item) { if (item.hasOwnProperty(i)) { tds.push(h('td', {}, item[i] + '')) } } return h('tr', {}, tds) })) if (vnode) { // re-render patch(vnode, newVnode) } else { // 初次渲染 patch(container, newVnode) } // 存储当前的 vnode 结果 vnode = newVnode } // 初次渲染 render(data) var btnChange = document.getElementById('btn-change') btnChange.addEventListener('click', function () { data[1].age = 30 data[2].address = '深圳' // re-render render(data) })
核心API:
// diff 算法实现 // code demo function createElement(vnode) { var tag = vnode.tag // 'ul' var attrs = vnode.attrs || {} var children = vnode.children || [] if (!tag) { return null } // 创建真实的 DOM 元素 var elem = document.createElement(tag) // 属性 var attrName for (attrName in attrs) { if (attrs.hasOwnProperty(attrName)) { // 给 elem 添加属性 elem.setAttribute(attrName, attrs[attrName]) } } // 子元素 children.forEach(function (childVnode) { // 给 elem 添加子元素 elem.appendChild(createElement(childVnode)) // 递归 }) // 返回真实的 DOM 元素 return elem } // vnode newVnode compare function updateChildren(vnode, newVnode) { var children = vnode.children || [] var newChildren = newVnode.children || [] children.forEach(function (childVnode, index) { var newChildVnode = newChildren[index] if (childVnode.tag === newChildVnode.tag) { // 深层次对比,递归 updateChildren(childVnode, newChildVnode) } else { // 替换 replaceNode(childVnode, newChildVnode) } }) } function replaceNode(vnode, newVnode) { var elem = vnode.elem // 真实的 DOM 节点 var newElem = createElement(newVnode) // 替换 }
answer:
todolist
// jquery // html // <div> // <input type="text" name="" id="txt-title"> // <button id="btn-submit">submit</button> // </div> // <div> // <ul id="ul-list"></ul> // </div> var $txtTitle = $('#txt-title') var $btnSubmit = $('#btn-submit') var $ulList = $('#ul-list') $btnSubmit.click(function () { var title = $txtTitle.val() if (!title) { return } var $li = $('<li>' + title + '</li>') $ulList.append($li) $txtTitle.val('') }) // vue // <div id="app"> // <div> // <input v-model="title"> // <button v-on:click="add">submit</button> // </div> // <div> // <ul> // <li v-for="item in list">{{item}}</li> // </ul> // </div> // </div> // data 独立 var data = { title: '', list: [] } // 初始化 Vue 实例 var vm = new Vue({ el: '#app', data: data, methods: { add: function () { this.list.push(this.title) this.title = '' } } }) /* with(this){ // this 就是 vm return _c( 'div', { attrs:{"id":"app"} }, [ _c( 'div', [ _c( 'input', { directives:[ { name:"model", rawName:"v-model", value:(title), expression:"title" } ], domProps:{ "value":(title) }, on:{ "input":function($event){ if($event.target.composing)return; title=$event.target.value } } } ), _v(" "), _c( 'button', { on:{ "click":add } }, [_v("submit")] ) ] ), _v(" "), _c('div', [ _c( 'ul', _l((list),function(item){return _c('li',[_v(_s(item))])}) ) ] ) ] ) } */
区别:
MVC:
MVVM:
关于 ViewModel
解答:
MVVM三要素:
// var obj = { // name: 'zhangsan', // age: 25 // } // console.log(obj) // var obj = {} // var _name = 'shangsan' // Object.defineProperty(obj, 'name', { // get: function () { // console.log('get', _name) // 监听 // return _name // }, // set: function (newVal) { // console.log('set', newVal) // 监听 // _name = newVal // } // }) // var vm = new Vue({ // el: '#app', // data: { // name: 'zhangsan', // age: 20 // } // }) var vm = {} var data = { name: 'zhangsan', age: 20 } var key, value for (key in data) { (function (key) { // 保证 key 的独立作用域 Object.defineProperty(vm, key, { get: function () { console.log('get', data[key]) // 监听 return data[key] }, set: function (newVal) { console.log('set', newVal) // 监听 data[key] = newVal } }) })(key) }
答案:
根据 todo-list demo 的 render 函数:
render函数解决了模板中“逻辑”(v-for v-if)的问题 还剩下模板生成 html 的问题 另外,vm._c 是什么?render 函数返回了什么?
// html // <div id="app"> // <p>{{price}}</p> // </div> // js var vm = new Vue({ el: '#app', data: { price: 100 } }) // 以下是手写的 ppt 中的 render 函数 function render() { with(this) { // this 就是 vm return _c( 'div', { attrs: { 'id': 'app' } }, [ _c('p', [_v(_s(price))]) ] ) } } function render1() { return vm._c( 'div', { attrs: { 'id': 'app' } }, [ vm._c('p', [vm._v(vm._s(vm.price))]) ] ) }
模板:字符串,有逻辑,嵌入 JS 变量……
模板必须转换为 JS 代码(有逻辑、渲染 html、JS 变量)
render 函数是什么样子的
render 函数执行是返回 vnode
updateComponent
第一步:解析模板成 render 函数
第二步:响应式开始监听
第三步:首次渲染,显示页面,且绑定依赖
第四步:data 属性变化,触发 rerender
// jsx test // devDependencies: babel-plugin-transform-react-jsx // .babelrc // {"plugins": ["transform-react-jsx"]} // demo.js /* @jsx h */ // 上面这段注释,用于更改 React.cerateElement()函数名称 // var profile = <div> // <img src="avatar.png" className="profile" /> // <h3>{[user.firstName, user.lastName].join(' ')}</h3> // </div>; // class Input extends Component { // render() { // return ( // <div> // <input value={this.state.title} onChange={this.changeHandle.bind(this)}/> // <button onClick={this.clickHandle.bind(this)}>submit</button> // </div> // ); // } // } // 命令行输入:babel --plugins trnasform-react-jsx demo.jsx
<div>
问题解答:
微信JSDK
// schema 使用的封装 // html // <button id="btn1">扫一扫</button> // <button id="btn2">分享</button> // <script type="text/javascript" src="./invoke.js"></script> (function(window, undefined) { // 调用 schema 的封装 function _invoke(action, data, callback) { // 拼装 schema 协议 var schema = 'myapp://utils/' + action schema += schema.indexOf('?') === -1 ? '?' : '&' // 拼接参数 for (var key in data) { if (data.hasOwnProperty(key)) { schema += key + '=' + data[key] + '&' } } // 处理 callback callbackName = action + Date.now() window[callbackName] = callback schema += 'callback=' + callbackName // 触发 var iframe = document.createElement('iframe') iframe.style.display = 'none' iframe.src = schema // 重要! var body = document.body body.appendChild(iframe) setTimeout(function() { body.removeChild(iframe) iframe = null }) } // 暴露到全局变量 window.invoke = { share: function(data, callback) { _invoke('share', data, callback) }, scan: function(data, callback) { _invoke('scan', data, callback) } login: function(data, callback) { _invoke('login', data, callback) } } })(window)
JS高级面试
ES6 常用语法
模块化的使用和编译环境
webpack笔记 babel使用 rollup.js 使用:
Class 与 JS 构造函数的区别
参考1-构造函数和集成ES5 参考2-class 和 extends
Promise 的用法
参考
ES6 其他常用功能
参考
原型高级应用
原型如何实际应用
jquery 和 zepto 的简单使用 他俩如何使用原型
zepto 如何使用原型
jQuery 如何使用原型
原型如何满足扩展
$.fn.myMethod = function() {}
异步全面讲解
什么是单线程,和异步有何关系?什么是 event-loop
单线程:只有一个线程,同时只能做一件事(for 循环多次、alert),两段JS不能同时执行 原因:避免DOM渲染的冲突 解决方案:异步
什么是异步队列?何时被放入异步队列?轮询的过程
目前 JS 解决异步的方案有哪些
如果只用 jQuery 如何解决异步
jquery1.5的变化:
$.ajax().done().fail().done() $.ajax().then(function(){}, function(){}).then()
jquery-deferred: 对扩展开放,对修改关闭 dtdAPI分为两类,用意不同:
Promise 的标准
问题:
async / await 的使用
问题:
虚拟DOM
什么是Vdom,为何要用Vdom
设计一个需求场景 -》用jquery实现 -》遇到的问题
浏览器渲染 DOM 是很慢的,运行 JS 快成一匹马
遇到的问题:
vdom:
Vdom如何使用,核心函数有哪些
snabbdom用法:
核心API:
了解diff算法吗
answer:
MVVM(Vue)
说一下使用 jQuery 和使用框架的区别
todolist
区别:
说一下对 MVVM 的理解
MVC:
MVVM:
关于 ViewModel
解答:
MVVM三要素:
vue 中如何实现响应式
答案:
vue 中如何解析模板
根据 todo-list demo 的 render 函数:
render函数解决了模板中“逻辑”(v-for v-if)的问题 还剩下模板生成 html 的问题 另外,vm._c 是什么?render 函数返回了什么?
vue 的整个实现流程
模板:字符串,有逻辑,嵌入 JS 变量……
模板必须转换为 JS 代码(有逻辑、渲染 html、JS 变量)
render 函数是什么样子的
render 函数执行是返回 vnode
updateComponent
第一步:解析模板成 render 函数
第二步:响应式开始监听
第三步:首次渲染,显示页面,且绑定依赖
第四步:data 属性变化,触发 rerender
组件化 React
说一下对组件化的理解
JSX 本质是什么
JSX 和 vdom 的关系
<div>
即可,vdom 可以做到说一下 setState 的过程
阐述自己对 React 和 vue 的认识
问题解答:
hybrid
hybrid 是什么,为何用 hybrid?
介绍一下 hybrid 更新和上线的流程?
hybrid 和 h5 的主要区别
前端 JS 和客户端如何通讯?
微信JSDK
你热爱编程吗