你好2020


今天正好有个老朋友聊起来jquery源码,他对于源码不了解,我抱着学习交流的心态,给他讲解了核心实现。(好像自己也鸽了好长时间)
顺便在哪个cdn服务商找个jquery文件打开, 我这里用的1.2.3版本为例,最新版本也差不多,只有两三处变化https://cdnjs.cloudflare.com/ajax/libs/jquery/1.2.3/jquery.js
17-20行传入选择器,返回自身new出来的init方法,估计你们也没用过$()的第二个参数,这里省略掉
var jQuery = window.jQuery = function(selector) {
return new jQuery.prototype.init(selector);
}26-27行这就是为什么总是用$开头的原因,挂载到window对象下,属于全局变量
// Map the jQuery namespace to the '$' one
window.$ = jQuery;36-547行剔除我们不需要的保留核心,留下init方法,内部做了jquery实例与选择器的判断,这里我们忽略掉,简化
jQuery.fn = jQuery.prototype = {
init: function(selector) {
var nodes = document.querySelectorAll(selector);
for (var i in nodes) {
this[i] = nodes[i];
}
return this;
}
//此处省略十万字
}549行来上一段这个,jquery原型链传递给jquery原型下init方法的原型,回头再看new时候的代码,很清楚明了
jQuery.prototype.init.prototype = jQuery.prototype;在jQuery的原型上继续增加功能就很接近初版jQuery了,这里我是简单实现了text()方法
var jQuery= function (selector) {
return new jQuery.fn.init(selector);
}
jQuery.fn = jQuery.prototype = {
init: function (selector) {
var nodes = document.querySelectorAll(selector);
for (var i in nodes) {
this[i] = nodes[i];
}
return this;
},
element: function (callback) {
for (var i = 0; i < this.length; i++) {
callback(this[i]);
}
},
text: function (content) {
if (content == '' || content) {
this.element(function (node) {
node.innerHTML = content;
})
return content;
} else {
return this[0].innerHTML;
}
},
}
jQuery.prototype.init.prototype = jQuery.prototype;
window.$ = jQuery;核心其实一点不复杂,插件的实现我倒是很喜欢,自身的功能我看来大部分全是用插件实现的,工具自身的巧妙设计加上便利性。
在传统页面制作上jquery一把梭用的很舒服,但MVVM的出现改变了大家的思考方式,只需关注业务逻辑,不需要手动操作DOM, 不需要关注数据状态的同步问题,对于项目管理轻松不少。
如果有简单需求的单页上,jquery还是有用武之地的,上MVVM只能是徒增麻烦。

GOG启动,预购!
快速部署多站点环境,基于docker,docker-compose编排方便直接添加,每个站点独立使用一个fpm实例性能更好一些
Link: flxxyz/fast-deploy-website
最近感觉好卡啊
tx香港像炸了?既然备案了还是考虑再搬进国内8 (确实放进国内了hhh)
之前用过面板,纯手搭,现在还是用的宝塔老版本,计划备份站点,重置服务器,几天前在屋里虚拟化设备上用docker配置过实例
看了下上一篇文章发布时间还是在两个月之前,哇,一下在家玩了一个多月了
想下在家都干嘛了,睡觉,玩游戏,看电影,写代码,看书,参加活动,拼模型,捡垃圾,适当的运动,房间整理。
大致的时间分配如下图
看小米手环每天睡觉的时间差不多都在10个小时,steam收藏家的游戏买了还要玩?当然是玩手游啦,荒野乱斗简单快速的玩法真的不错,固定的四张地图场景,还有一张活动地图,固定的地图玩法可以,在时间段内推出新活动,新活动会对场景物体进行微调,增加一些特定玩法,队伍的奖励机制也很巧妙,除非你是倒数123,都会有奖励,每场比赛类似于排位赛,胜利会获得奖杯(英雄个人奖杯与总奖杯),总奖杯只会一直累加,失败只会减少英雄个人奖杯,玩长时间真的有毒。
把最近整的一些小玩意整理分享一下
手机号登录,分析一下页面可以知道一般是有两个按钮(获取验证码,登录)两个框(输入手机号,输入验证码)
所以有了下面这个玩意(不看具体功能,只看结构)
<template>
<div class="login-wrapper">
<div class="title-bar">登录</div>
<div class="wrapper phone-wrapper">
<span class="title">手机号</span>
<input class="input phone" type="text" placeholder="手机号">
</div>
<div class="wrapper code-wrapper">
<span class="title">验证码</span>
<input class="input code" type="number" placeholder="验证码">
<div class="send">获取验证码</div>
</div>
<div class="wrapper btn-wrapper">
<div class="input btn">登录</div>
</div>
</div>
</template>这个时候就可以开始写逻辑了,也是来简单分析一下,登录需要点击,获取验证码需要点击并且能倒数秒数,也就是动态修改文字,体验好一点可以检查限定手机号位数,验证码位数。
那就差不多是下面这个样子
<template>
<div class="login-wrapper">
<div class="title-bar">登录</div>
<div class="wrapper phone-wrapper">
<span class="title">手机号</span>
<input class="input phone" type="text" placeholder="手机号"
:value="phone"
ref="phone" v-on:change="changePhone" v-on:input="changePhone">
</div>
<div class="wrapper code-wrapper">
<span class="title">验证码</span>
<input class="input code" type="number" placeholder="验证码"
:value="code"
ref="code" v-on:change="changeCode" v-on:input="changeCode">
<div @click="loginCode" class="send">{{codeText}}</div>
</div>
<div class="wrapper btn-wrapper">
<div class="input btn" @click="login">登录</div>
</div>
</div>
</template>
<script>
name: "LoginPhone",
data() {
return {
phone: '', //输入框中的手机号
code: '', //输入框中的验证码
codeText: '获取验证码', //倒计时显示文字
timingBoard: 60, //倒计时数
timer: null, //一个定时器,用来倒数验证码
}
},
methods: {
loginCode() {}, //获取验证码
login() {}, //登录
changePhone() {}, //检查手机号长度
changeCode() {}, //检查验证码长度
}
</script>有了这些已经足够你实现出一个基本的手机号登录界面了,如需完全代码请点击下面gist链接
完整代码参阅: https://gist.github.com/flxxyz/64ceb06a0754d67a771b3e3e7dc94d48
说实话用了这么长时间的vue,都没看过API,这几天重构博客偶然发现Vue.directive,挺厉害的样子
总是看到这里用Vue.use(ElementUi),那里用Vue.use(axios),一直停留在了用的层面,正好我发现编写markdown解析实例的消耗好像有点大,直接处理成指令或许会方便很多(真的方便了很多,少写了一堆方法)
简单描述一下流程吧
渲染文章的组件在挂载的生命周期中,会查询本地记录中是否存在对应的文章,不存在就发起请求线上查找,否则404。
文章为markdown内容,考虑让前端处理直接解析出来(毕竟前端性能过剩233),减少后端逻辑处理负担,一致性什么现在是不需要考虑的。
markdown解析器就用marked,完成逻辑如下
//main.js
import Vue from 'vue'
import App from './App'
import markdown from './markdown';
//注入markdown解析器
Vue.use(markdown.install)
Vue.prototype.$marked = markdown.marked
new Vue({
store,
router,
render: h => h(App)
}).$mount('#app')集成marked制成插件形式暴露
//markdown.js
import marked from 'marked'
import('highlight.js/styles/atom-one-dark.css')
marked.setOptions({
renderer: new marked.Renderer(),
pedantic: false,
gfm: true,
tables: true,
breaks: false,
sanitize: false,
smartLists: true,
smartypants: false,
xhtml: false,
highlight(code) {
return require('highlight.js').highlightAuto(code).value;
},
})
let install = (Vue) => {
if (install.installed) return;
Vue.directive('markdown', {
bind: (el, binding, vnode) => {
el.innerHTML = marked(binding.value)
},
update: (el, binding, vnode) => {
el.innerHTML = marked(binding.value)
}
})
}
export default {
marked,
install,
}在标签上使用v-markdown指令
//Test.vue
<template>
<div>
<div v-if="isNotFound">404</div>
<div v-else v-markdown="article"></div>
</div>
</template>
<script>
const 这是一个查找文章的接口 = function () {
return new Promise((resolve, reject) => {resolve(id)})
}
export default {
name: "Test",
data() {
return {
article: '',
isNotFound: true,
}
},
methods: {
handlerArticle(id) {
//查找本地文章
let a = this.findArticle(id, async (id) => {
return await 这是一个查找文章的接口(id);
})
if (a == null) {
return 404;
}
return a;
},
findArticle(id, callback) {
// let res = '## Test';
let res = null;
if (res === null) {
return callback(id);
}
return res;
}
},
mounted() {
//用id来查找文章
let a = this.handlerArticle(123);
if (a === 404) {
//跳到错误页面
}
//处理loading
this.isNotFound = false;
this.article = a; //将markdown内容直接保存到变量
}
}
</script>完整代码参阅: https://gist.github.com/flxxyz/93e009d32ecd7e0c6785a52571577cd7
u11同学你可以休息一下了
蹭了学生优惠,买了个阿里云轻服务器,5M带宽转国外线路减少丢包概率还不错,ns联机美滋滋,不过据说港服联机服务要出了,不知道联机质量会怎么样
# 打开ip伪装
firewall-cmd --add-masquerade --permanent
# 添加端口协议
firewall-cmd --add-forward-port=port=中转后的端口:proto=tcp:toport=酸酸乳端口:toaddr=酸酸乳地址 --permanent
firewall-cmd --add-forward-port=port=中转后的端口:proto=udp:toport=酸酸乳端口:toaddr=酸酸乳地址 --permanent
# 重载一下
firewall-cmd --reload