track相关知识
-
vue3 深入浅出(连载三)手摸手实现 vue3大家好,我是Mokou,最近一直在做 vue3 相关内容,比如源码解析和mini-vue3的开发。 回顾下前几章的内容,在前几章中主要讲述了以下内容。 新构建工具 vite 的原理和从零开始实现 vue3 使用新姿势 新api:reactive 使用和源码解析 追踪收集 track 实现和源码解析 追踪触发器 trigger 实现和源码解析 响应式核心 effect 与 track、trigger 工作原理和源码解析 好的,这章的目标:从零开始完成一个 Vue3 ! 必须要知道的前置知识 effect 与 track、trigger 工作原理
-
撤销git add操作使用Git的时候,有时候不小心使用git add,添加了不想追踪的文件。也就是track了一些不想track的文件,这个时候需要撤销操作,怎么处理呢?Git 文件状态的生命周期演示还原操作使用git reset命令git set命令效果使用git rm --cached [filename]命令git rm命令效果git rm--cachedUse this option to unstage and remove paths only from the index. Working tree files, whether modified or not, will be left alone.额外在文件未被git track的时候,可以添加.gitignore文件,来指定不想追踪那些文件。gitignore的效果最后简单的介绍了git的一些基本功能
-
Webkit 内核浏览器自定义滚动条样式Webkit 内核浏览器自定义滚动条样式 Webkit在所有浏览器中对于滚动条对自定义支持度最高,也是效果最好的,主要采用带有-webkit-私有前缀伪元素实现 使用示意图 /*1*/ ::-webkit-scrollbar{} /*2*/ ::-webkit-scrollbar-button{} /*3*/ ::-webkit-scrollbar-track{} /*4*/ ::-webkit-scrollbar-track-piece{} /*5*/ ::-webkit-scrollbar-thumb{} /*6*/ ::-webkit-scrollbar-corner{} /*7*/ ::-webkit-scrollbar-resizer{} 如上图所示,用户可以根据自己需要对滚动条各个部分定
-
EasySignSeekBar一个漂亮而强大的自定义view简述最近在工作上的需要,自定义了一个漂亮而强大的自定义view,但不仅仅只是一个SeekBar而已哦,一定要耐心看完。刚开始是不愿意自己去写的,这东西太浪费时间,UI这东西不一定是个技术活,但一定是个细活。浏览了很多自定义控件,都没有符合需要的,最终只能自己开撸。实现了效果后想着看能不能也方便他人,如果其他人有类似的效果,修改下属性配置就可以直接使用,于是就分享出来,取名:EasySignSeekBar 。源码http://www.apkbus.com/thread-598080-1-1.htmlEasySignSeekBar本库主要提供一个漂亮而强大的自定义SeekBar,进度变化由提示牌 (sign)展示,具有强大的属性设置,支持设置section(节点)、mark(标记)、track(轨迹)、thumb(拖动块)、progress(进度)、sign(提示框)等功能主要功能强大的track(轨迹)和second track (选中轨迹)的最小值、最大值、轨迹粗细,颜色等设置;灵活的数字显示支持整数和小数
track相关课程
track相关教程
- 2.2 属性和 effect 关联 怎么才能让属性和这个函数进行关联呢?首先我们要创建一个收集函数(track)用于收集属性 key 和 effect 回调函数的关联,并且只有在 effect 中使用到的 key,更新时才会执行 effect 中的回调,所以我们在收集依赖时需要先判断。function track(target, key) { if (activeEffect === viod 0) { return; }}什么时候进行收集呢?effect 回调函数会默认执行,在获取值的时候对响应式对象上的 key 进行依赖收集,也就是在 createGetter 函数中进行收集。function createGetter() { return function get(target, key, receiver) { const res = Reflect.get(target, key, receiver); if (isSymbol(key)) { return res; } // 依赖收集 track(target, key); if (isObject(res)) { return reactive(res); } return res; };}如何关联呢?就是需要在 target 上的 key 中存放若干个 effect,那这要怎么存放呢?这时我们想到了 WeakMap,创建一个 WeakMap 来保持 target 上的需要关联 effect 的属性。同时,下面的伪代码数据结构是我们希望存放在 WeakMap 中的映射,其中 target 是目标对象。{ target1: { key: [effect, effect] }, target2: { key: [effect, effect] }}在存放 effect 时可能还需要给 effect 加上一些标识,如:id、deps、options 等,后面会用到。Let uid = 0;function createReactiveEffect(fn, options) { const effect = function reactiveEffect() { activeEffect = effect; return fn(); } effect.id = uid++; effect.deps = []; effect.options = opntions; return effect} const targetMap = new WeakMap();function track(target, key) { if (activeEffect === undefined) { return; } // 目标是创建一个映射:{target1: {name: [effect, effect]},target2: {name: [effect, effect]}} let depsMap = targetMap.get(target); // depsMap存放target的值,是一个Map对象 if(!depsMap) { // 如果targetMap中没用target对象,则创建一个。 targetMap.set(target, (depsMap = new Map())); } let dep = depsMap.get(key); // 获取depsMap对象中属性是target上的key值 if(!dep) { depsMap.set(key, (dep = new Set())); // 存放effect的集合 } if(!dep.has(effect)) { dep.add(activeEffect); activeEffect.deps.push(dep); }}上面的代码中,收集目标对象上所有的依赖,在 effect 的回调函数中没有使用到的属性,就不需要进行依赖收集。在执行完创建响应式 effec 函数 createReactiveEffect 后需要把 activeEffect 置为 null。function createReactiveEffect(fn, options) { const effect = function reactiveEffect() { try { activeEffect = effect; return fn(); } finally { activeEffect = null; } } return effect} 上面的代码中 finally 是一定会执行的。在 effect 回调函数中嵌套使用 effect,并且在嵌套的 effect 后还有响应式数据,如果是下面这种写法,state.c = 300 将不会收集。effect(() => { state.a = 100; effect(() => { state.b = 200; }) state.c = 300;})这个时候我们就需要创建一个存放栈的数组(effectStack)来存放 activeEffect,执行完毕后也不用赋值 null 了,通过出栈的形式把最后一个移除,让当前的 activeEffect 值等于 effectStack 最后一个值 effectStack[effectStack.length-1] 。这样我们在执行完创建响应式 effect 函数时,控制权又会交到上一层的 activeEffect 上,这样上面代码中的 state.c=300 就会被收集到第一层的 effect 中去。具体执行代码如下:const effectStack = [];function createReactiveEffect(fn, options) { const effect = function reactiveEffect() { try { activeEffect = effect; effectStack.push(activeEffect); return fn(); } finally { effectStack.pop(); activeEffect = effectStack[effectStack.length - 1]; } } return effect}使用栈的还有一个好处可以防止递归执行,在 effect 如果有数据持续变化是如: state.a++ 这样的逻辑就会形成递归。这时需要处理为只执行一次,增加一个条件判断,如下代码:function createReactiveEffect(fn, options) { const effect = function reactiveEffect() { if (!effectStack.includes(effect)) { // 防止死循环 try { activeEffect = effect; effectStack.push(activeEffect); return fn(); } finally { effectStack.pop(); activeEffect = effectStack[effectStack.length - 1]; } } } return effect}
- 1. 官方定义 grid-template-columns 该属性是基于 网格列. 的维度,去定义网格线的名称和网格轨道的尺寸大小。grid-template-rows 该属性是基于 网格行 的维度,去定义网格线的名称和网格轨道的尺寸大小。repeat() 函数表示轨道列表的重复片段,允许以更紧凑的形式写入大量显示重复模式的列或行。auto-fill和 auto-fit 属性规定如何填充列(是否进行协调)。fr fr 单位被用于在一系列长度值中分配剩余空间,如果多个已指定了多个部分,则剩下的空间根据各自的数字按比例分配。minmax() 定义了一个长宽范围的闭区间, 它与 CSS 网格布局一起使用。grid-auto-columns 指定了隐式创建的网格纵向轨道(track)的宽度grid-auto-rows 用于指定隐式创建的行轨道大小。
- 2. 将修改添加到暂存区 上面的操作我们也看到了,当新增了一个文件之后,使用 "git status" 命令查看文件状态信息时,最后一行内容:nothing added to commit but untracked files present (use “git add” to track)。提示我们没有提交任何内容但是存在未跟踪的文件,括号里面说可以使用 “git add” 命令去使其被跟踪管理。这个 “git add” 命令就是将新做的修改添加到 git 暂存区的,那么我们就来试一下,把上一步新建的文件进行添加:$ git add test2.txt之后再查看下文件状态:$ git statusOn branch masterYour branch is up to date with 'origin/master'.Changes to be committed: (use "git reset HEAD <file>..." to unstage) new file: test2.tx此时,文件 test2.txt 就到了 “Changes to be committed” 的内容下面,也就是将要被提交的修改,因为已经添加到了暂存区,接下来可以进行提交。直到这里,一切都是那么顺滑,不对,顺利!附:演示流程如下:
- 1. 查看文件状态 如果想查看我们的工作目录下的文件处于已跟踪还是未跟踪状态,也就是说我们想看看哪些文件修改了还没告诉 Git,或者一些别的信息,比如当前所处的分支(分支的知识后续会讲)等。就可以用下面的命令:$ git statusOn branch masterYour branch is up to date with 'origin/master'.nothing to commit, working tree clean可以看到,当前所处的分支是 master,并且当前工作目录下没有任何要提交的内容。也就是说,目前工作目录的内容与 Git 管理的内容一样。那么我在当前目录新增一个文件,并写入一些内容之后,我们再看下会发生什么。$ echo 'test status' > test2.txt$ git statusOn branch masterYour branch is up to date with 'origin/master'.Untracked files: (use "git add <file>..." to include in what will be committed) test2.txtnothing added to commit but untracked files present (use "git add" to track)可以看到,已经有未跟踪的内容了,就是 Untracked files 那部分信息。因为我们刚刚并没有添加到暂存区,Git 还不知道。附:演示流程如下:
- 2. 基于 Selenium 完成发票认证 接下来,我们基于 Scrapy 和 Selenium 来完成笔者工作中的一个需求。我们每个月有一笔通信发票的报销,需要使用对自己在营业厅中买的发票进行校验,然后要截图留存。报销的时间有时候是3个月一次,有时候是半年,所以累积下来有不少发票,这些发票都需要校验和截图才能报销。我们应届生刚工作的时候,我们大部分新员工都是手工截图,非常笨拙,且耗时。由于是搞技术的公司,于是有前端人员写了相关的前端插件来自动化截图和生成发票校验文档,然后在公司内广泛应用。我也写了这样一段基于 Selenium 的自动化截图代码,不过代码依赖 chrome 和 webdriver,所以组内的部分人会把发票的起始编号和张数发给我,我运行程序截好图后将图片打包发给他们自己放到 word 文档中去。来看看发票校验的网站的截图如下:广东通信发票校验网站验证的方式非常机械,正是因为机械操作,才给了我们自动化的可能、看上图中的四个输入框,表示的含义分别为:发票代码:固定值;发票号码:通常而言,从移动营业厅拿的通信发票是连续的,这样就可以用 for 循环实现;纳税人识别号:这个是个固定值;发票面额:固定50元。假设我买300元的卡,就会对应6张发票;我们填好每张发票的相应信息,只有一个变量。在查询之前,需要先拖动滑块进行验证,验证通过,再点击查询就可以进行认证。得到了认证结果后,截张图,如此进行下去,直到所有的发票都校验截图完毕。令人欣慰的是这里的滑块验证只需要做一次,得到了相应的认证截图后,每次调整下一张发票的发票号码,在截一张图即可。看下面的做法:104因此,我们得到了这样的机械化动作:打开发票校验页面;输入第一张发票的四个参数,然后拖动滑块到最右端完成校验;截图留存;改动第二个输入框的发票号码,为下一个发票编号,然后直接截图;重复,直到最后一张发票截图成功;对应这样的动作我们翻译成相应的 Selenium 自动化代码如下:"""测试 selenium 工具"""import timeimport randomfrom selenium import webdriverfrom selenium.webdriver.support import expected_conditions as ECfrom selenium.webdriver.support.ui import WebDriverWaitfrom selenium.webdriver.common.by import Byfrom selenium.webdriver import ActionChains# 固定值ticket_code = "144011690802"identification_number = "91440101618652334F"face_value = 50# 起始编号ticket_start_num = 15415104# 发票总数total_count = 10def click_space(driver): """ 点击下空白处,使得输入框失去焦点 """ driver.find_elements_by_xpath('//div[@class="check-main"]/table/tbody/tr[1]/td[1]')[0].click()def fill_input(driver, idx): """ 填充输入框 """ input_value = [ticket_code, idx, identification_number, face_value] table = driver.find_elements_by_xpath('//div[@class="check-main"]/table/tbody')[0] for i in range(1, len(input_value) + 1): input = table.find_elements_by_xpath(f'./tr[{i}]/td[2]/input')[0] input.clear() input.send_keys(input_value[i - 1]) click_space(driver)def get_track(distance): """ 参考文献2代码,模拟人移动鼠标 :distance为传入的总距离 """ # 移动轨迹 track = [] # 当前位移 current = 0 # 减速阈值 mid = distance * 3 / 5 # 计算间隔 t = 0.4 # 初速度 v = 1 while current < distance: if current < mid: # 加速度为一个随机值 a = random.randint(2, 6) else: # 加速度为一个随机负值 a = -1 * random.randint(1, 2) v0 = v # 当前速度 v = v0 + a * t # 移动距离 move = v0 * t + 0.5 * a * t * t # 当前位移 current += move # 加入轨迹 track.append(round(move)) return trackdef move_to_gap(slider, tracks): """ 参考文献2代码 :slider是要移动的滑块,tracks是要传入的移动轨迹 """ action = ActionChains(driver) action.click_and_hold(slider).perform() for x in tracks: ActionChains(driver).move_by_offset(xoffset=x,yoffset=0).perform() time.sleep(0.1) ActionChains(driver).release().perform()# 发票校验地址verify_address = "https://gs.etax-gd.gov.cn/gsyw/service/fpyw/fpcy/index"# 想屏蔽selenium标识,避免被服务端检测到,似乎没起作用options = webdriver.ChromeOptions()options.add_experimental_option("excludeSwitches", ['enable-automation'])driver = webdriver.Chrome(options=options, executable_path="C:/Users/spyinx/AppData/Local/Google/Chrome/Application/chromedriver.exe")driver.maximize_window()# 第一步先去发票查询页面driver.get(verify_address)# 等待滑块出现WebDriverWait(driver, 10).until( EC.visibility_of_element_located((By.ID, 'nc_1_n1z')))# 填充输入框fill_input(driver, ticket_start_num)# 等待几秒后driver.implicitly_wait(5)# 找到滑动按钮,模拟鼠标按下不松开slider = driver.find_element_by_id('nc_1_n1z')move_to_gap(slider, get_track(300))driver.implicitly_wait(2)driver.find_element_by_id("CxBtn").click()# 查询第一个需要滑动滑块driver.get_screenshot_as_file(f"{ticket_start_num}.png")for i in range(1, total_count): ticket_num = ticket_start_num + i fill_input(driver, ticket_num) driver.get_screenshot_as_file(f"{ticket_num}.png") driver.implicitly_wait(1)上面的代码已经做好了详细的注释,请查找相关资料了解 Selenium 提供的相关方法,比如定位页面元素的方法、对页面元素点击(click)、输入框情况 (clear) 以及输入元素(send_keys) 以及鼠标的相关操作方法。下面我们直接来看代码的演示效果,最后的截图也全部得到。105注意:由于这个滑动验证码是接入的阿里滑动验证码插件,具备超强的反爬虫能力,能识别出是浏览器否被 selenium 控制。本次测试重复了无数次,才终于有一次没有出现滑块校验错误,才成功录下此视频。具体的可以搜索大神如何破解阿里的滑动验证码,不过大部分代码已经过时,无法突破验证。总而言之,上面的操作是不是一定程度上能帮助我们减少手工操作,节约了时间成本?如果大家感兴趣的话,可以尝试使用 Selenium 完成京东商城的自动登录操作,这里会有滑动图片缺口补全的校验,会稍微有点复杂,对你们来说也是一个不错的挑战。
- 集群环境搭建 一站式Redis解决方案
track相关搜索
-
tab
table
tableau
tablelayout
table样式
taif
tail
talk
tamcat
tan
target属性
task
tbody
tcl tk
TCP IP
tcp ip协议
tcpdump
tcpip
tcpip协议
tcp连接