分类 学习 下的文章 - 浮川的小窝
首页
休闲直播
4K壁纸
统计
更多
关于
留言
归档
搜 索
1
emby+alist3+cloudDriver2 emby无法播放网盘资源问题
163 阅读
2
HelloWorld!
154 阅读
3
前端算法整理
146 阅读
4
关于服务器配置反代隐藏端口中遇到的问题
141 阅读
5
maptalks 一些基础api的再封装(待解耦改装纯方法类)
121 阅读
生活
学习
随笔
吐槽
小秘密
小故事
登录
/
注册
搜 索
SnowLove
累计撰写
69
篇文章
累计收到
5
条评论
首页
栏目
生活
学习
随笔
吐槽
小秘密
小故事
页面
休闲直播
4K壁纸
统计
关于
留言
归档
用户登录
登录
注册
找到
45
篇与
学习
相关的结果
2024-07-18
使用防抖节流犯的低级错误
场景是这样的 有一个v3拖拉组件组 当拖动时会回调一个方法 进行整体布局的计算最最初是这样写的methods: { drag_handleBackLayout(newLayout, height) { if (this.gridState.resizing) { throttle(() => { this.drag_changeBackGroundGridRows(height) }, 50)() } debounce(() => { this.saveDisabled = false if (!this.gridState.resizing) this.drag_changeBackGroundGridRows(height) }, 100)() }, }发现毛用没有 函数根本没有起到作用 :@(吐血倒地)然后尝试使用方案2 methods: { ... // 移动、拉伸卡片时重新计算背景网格数据 drag_handleBackLayout(newLayout, height) { // 执行防抖函数 this.drag_debounceForResize() // 执行节流函数 this.drag_debounceForComputed() } ... }开始时我采用了最笨但是管用的写法 data() { return { // 初始化节流函数 drag_debounceToComputed: this.drag_debounceForComputed(), // 初始化防抖函数 drag_debounceToResize: this.drag_debounceForResize() } }, methods: { // 防抖函数 drag_debounceForResize() { return throttle(this.drag_changeBackGroundGridRows, 50) }, // 节流函数 drag_debounceForComputed() { return debounce(() => { if (!resizing) this.drag_changeBackGroundGridRows(height) // 对比新旧数据是否相同 管理工作台保存按钮是否禁用 this.saveDisabled = this.template_compareLayoutData(newLayout, oldLayout) // 保存localStorage信息 并根据状态渲染背景网格 localStorage.setItem('personalComptsList', JSON.stringify(newLayout)) }, 5); }, drag_handleBackLayout(newLayout, height) { // 执行防抖函数 this.drag_debounceToResize(height) // 执行节流函数 this.drag_debounceToComputed() } }这种方式没问题使用闭包创建了属性 整个生命周期只会调用一次初始化后的这个节流函数 但是经过我时间加搜索 发现可以简化下逻辑 用更易懂的写法来编写然后尝试使用方案3methods:{ // 移动、拉伸卡片时重新计算背景网格数据 drag_handleBackLayout(newLayout, height) { this.drag_debounceForResize(height) // 执行节流函数 this.drag_debounceForComputed({ height, newLayout, resizing, oldLayout }) }, // 防抖函数 // 保证防抖节流函数在整个生命周期中返回同一个函数 // 注:使用匿名函数 并且无需使用bind绑定this methods声明的方法vue会自动编定到this上 // 使用箭头函数会找不到this 箭头函数是被创建时的上下文确认this 那this指向的是函数drag_handleBackLayout drag_debounceForResize: throttle(function (height) { this.drag_changeBackGroundGridRows(height) }, 50), // 节流函数 drag_debounceForComputed: debounce(function() { this.saveDisabled = this.template_compareLayoutData(newLayout, oldLayout) }, 5), }注:使用匿名函数 并且无需使用bind绑定this methods声明的方法vue会自动编定到this上使用箭头函数会找不到this 箭头函数是被创建时的上下文确认this 那this指向的是函数drag_handleBackLayout
2024年07月18日
28
0
0
2024-03-14
ServiceWorker 缓存策略
项目中用到了ServiceWorker 在离线环境中能够加载出最新的文件缓存 避免直接大白瓶或显示404无法访问;在首次首页加载后,也将大部分资源缓存下来,增加后续网站渲染速度,增加用户体验 使用过程中遇到了一个坑 :@(内伤)const plugins = [ new GenerateSW({ cacheId: 'hwork-portal', swDest: 'service-worker.js', sourcemap: false, clientsClaim: true, skipWaiting: true, cleanupOutdatedCaches: true, // maximumFileSizeToCacheInBytes: 2621440, // 2.5Mb,默认值是 2097152(2Mb) runtimeCaching: [{ handler: 'CacheFirst', options: { cacheName: 'js' }, urlPattern: () => { const pathname = url.pathname || '' if (pathname.includes('xxx')) { const file = pathname.split('?')[0] || '' const fileType = file.split('.')[1] || '' if (fileType === 'js') { return true } } } }, { handler: 'CacheFirst', options: { cacheName: 'css' }, urlPattern: () => { const pathname = url.pathname || '' if (pathname.includes('xxx')) { const file = pathname.split('?')[0] || '' const fileType = file.split('.')[1] || '' if (fileType === 'css') { return true } } } }, { handler: 'StaleWhileRevalidate', options: { cacheName: 'images' }, urlPattern: () => { const pathname = url.pathname || '' if (pathname.includes('xxx')) { const file = pathname.split('?')[0] || '' const fileType = file.split('.')[1] || '' if (['webp', 'png', 'jpg'].includes(fileType)) { return true } } } }] }),上面是webpack中的部分plugins配置 由于项目使用的是微前端 所以最上级应用中配置了sw.js 加载二级应用时 发现了一个很奇怪的现象 js存在缓存的情况下是正常的 当有缓存时直接返回缓存值 但是css就很奇怪了 有缓存 但是sw还是又重新发起了一遍fetch请求 然后我就一通找啊找 :@(吐血倒地) :@(吐血倒地) 最后经过部门老大的提示 发现是二级应用打包的时候 base路径的三级域名并没有跟最上级应用一样 至于不同域名下js为啥能加载出来 目前没有找到原因 但是改过打包后 情况就正常了特此记录一下
2024年03月14日
35
0
0
2023-12-31
vue2源码学习
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> html,body{ width: 100%; height: 100%; margin: 0; padding: 0; } </style> </head> <body> <div id="app"></div> <script src="../dist/vue.js"></script> <script> Vue.component("my",{ render(h){ return h('div','我是组件测试组件渲染流程') } }) let vm = new Vue({ el:"#app", render(h){ return h('my') } }) </script> </body> </html>流程 // (一)创建全局组件 /* src/core/global-api/assets.js */ 1.definition = this.options._base.extend(definition) // 执行 2.this.options[type + 's'][id] = definition // 在vue实例 options上绑定组件名称 /* src/core/global-api/extend.js */ 1.Vue.extend (){ // ... return Sub } // 执行extend方法并返回Sub 2.const Sub = function VueComponent (options) { this._init(options) } Sub.options = mergeOptions( Super.options, extendOptions ) // 创建sub子类并合并vue函数上定义的各种方法 // (二)创建vue对象 (一)创建全局组件 /* src/core/instance/index.js */ 1.function Vue (options) { this._init(options) } // 创建vue对象并执行_init方法 /* src/core/instance/init.js */ 2.Vue.prototype._init = function (options?: Object) { // ... initLifecycle(vm) // 绑定父子关系 initEvents(vm) // 初始化时间 initRender(vm) // 初始化渲染 callHook(vm, 'beforeCreate') // 生命周期 initInjections(vm) // inject initState(vm) // data属性监听 响应式 initProvide(vm) // provide callHook(vm, 'created') // 生命周期 // ... if (vm.$options.el) { vm.$mount(vm.$options.el) } } // 初始化方法 响应式等 vm.$mount执行挂载 /* src/platforms/web/entry-runtime-with-compiler.js */ 3.Vue.prototype.$mount = function ( el?: string | Element, hydrating?: boolean ): Component { const = compileToFunctions(template, { outputSourceRange: process.env.NODE_ENV !== 'production', shouldDecodeNewlines, shouldDecodeNewlinesForHref, delimiters: options.delimiters, comments: options.comments }, this) options.render = render options.staticRenderFns = staticRenderFns return mount.call(this, el, hydrating) } // 重写Vue.prototype.$mount方法 解析template模板 绑定到this上 执行原$mount方法 /* src/platforms/web/runtime/index.js */ 4.Vue.prototype.$mount = function ( el?: string | Element, hydrating?: boolean ): Component { el = el && inBrowser ? query(el) : undefined return mountComponent(this, el, hydrating) } // 执行mountComponent /* src/core/instance/lifecycle.js */ 5.export function mountComponent ( vm: Component, el: ?Element, hydrating?: boolean ): Component { callHook(vm, 'beforeMount') updateComponent = () => { vm._update(vm._render(), hydrating) } new Watcher(vm, updateComponent, noop, { before () { if (vm._isMounted && !vm._isDestroyed) { callHook(vm, 'beforeUpdate') } } }, true /* isRenderWatcher */) } // 创建组件渲染Watcher /* src/core/observer/watcher.js */ 6.export default class Watcher { constructor (){ if (typeof expOrFn === 'function') { this.getter = expOrFn } this.value = this.lazy ? undefined : this.get() } get () { pushTarget(this) let value const vm = this.vm try { value = this.getter.call(vm, vm) } catch (e) { if (this.user) { handleError(e, vm, `getter for watcher "$"`) } else { throw e } } finally { if (this.deep) { traverse(value) } popTarget() this.cleanupDeps() } return value } } // 渲染watcher获取 获取回调 updateComponent = () => 执行 /* src/core/instance/render.js */ 7.Vue.prototype._render = function (): VNode { vnode = render.call(vm._renderProxy, vm.$createElement) } // 执行render(h)h为$createElement方法创建vnode /* src/core/vdom/create-element.js */ 8.export function createElement ( context: Component, tag: any, data: any, children: any, normalizationType: any, alwaysNormalize: boolean ): VNode | Array<VNode> { return _createElement(context, tag, data, children, normalizationType) } // 创建vnode元素 export function _createElement ( context: Component, // vue实例 tag?: string | Class<Component> | Function | Object, data?: VNodeData, children?: any, normalizationType?: number ): VNode | Array<VNode> { let Ctor if (typeof tag === 'string') { else if ((!data || !data.pre) && isDef(Ctor = resolveAsset(context.$options, 'components', tag))) // 获取全局组件绑定在vue函数上的全局组件 { // component vnode = createComponent(Ctor, data, context, children, tag) // 创建vnode } } }// 创建Ctor和vnode元素 /* src/core/vdom/create-component.js */ 9.export function createComponent ( Ctor: Class<Component> | Function | Object | void, // 子类my 合并了vue上的¥options data: ?VNodeData, context: Component, // vue实例对象 children: ?Array<VNode>, tag?: string ): VNode | Array<VNode> | void { const baseCtor = context.$options._base //_base等于vue函数 Vue (options) // extract props const propsData = extractPropsFromVNodeData(data, Ctor, tag) const listeners = data.on // replace with listeners with .native modifier // so it gets processed during parent component patch. data.on = data.nativeOn // install component management hooks onto the placeholder node installComponentHooks(data) // 创建一个包裹住my组件的父容器组件 vue-component-1-my const vnode = new VNode( `vue-component-$$` : ''}`, data, undefined, undefined, undefined, context, , asyncFactory ) else if (isDef(vnode)) { if (isDef(ns)) applyNS(vnode, ns) if (isDef(data)) registerDeepBindings(data) return vnode } } // 创建包裹my子组件的父组件vue-component-1-my的vnode元素 // 查看图1 返回第7步 /* src/core/instance/render.js */ 10.Vue.prototype._render = function (): VNode { return vnode } // 返回vue-component-1-my vnode // 返回第5步 updateComponent /* src/core/instance/lifecycle.js */ 11.Vue.prototype._update = function (vnode: VNode, hydrating?: boolean) { const vm: Component = this // 这个vm应为vue创建的的实例对象 if (!prevVnode) { // initial render vm.$el = vm.__patch__(vm.$el, vnode, hydrating, false /* removeOnly */) } // 更新页面 } /* src/core/vdom/patch.js */ 12. return function patch (oldVnode, vnode, hydrating, removeOnly) { const isRealElement = isDef(oldVnode.nodeType) if (isRealElement) { oldVnode = emptyNodeAt(oldVnode) // oldVnode = #app元素赋值 } // create new node createElm( vnode, insertedVnodeQueue, // extremely rare edge case: do not insert if old element is in a // leaving transition. Only happens when combining transition + // keep-alive + HOCs. (#4590) oldElm._leaveCb ? null : parentElm, nodeOps.nextSibling(oldElm) ) } function createElm ( vnode, // vue-component-1-my insertedVnodeQueue, // [] parentElm, // body dom元素 refElm, nested, ownerArray, index ) { if (createComponent(vnode, insertedVnodeQueue, parentElm, refElm)) { return } } function createComponent (vnode, insertedVnodeQueue, parentElm, refElm) { if (isDef(i = i.hook) && isDef(i = i.init)) { i(vnode, false /* hydrating */) }// 执行组件 hooks生命周期 (init,prepatch,insert,destroy)中的init } /* src/core/vdom/create-component.js */ 13.const componentVNodeHooks = { init (vnode: VNodeWithData, hydrating: boolean): ?boolean { else { const child = vnode.componentInstance = createComponentInstanceForVnode( vnode, activeInstance ) child.$mount(hydrating ? vnode.elm : undefined, hydrating) } }, } export function createComponentInstanceForVnode ( vnode: any, parent: any, ): Component { const options: InternalComponentOptions = { _isComponent: true, _parentVnode: vnode, parent } // check inline-template render functions const inlineTemplate = vnode.data.inlineTemplate return new vnode.componentOptions.Ctor(options) } // 执行全局组件my的this._init(options)方法 // 返回(一)创建全局组件 第2步 查看图二options参数的值 // 再次执行(二)创建vue对象 第2步 执行完后回到第13步 child.$mount(hydrating ? vnode.elm : undefined, hydrating) // 再次执行4、5、6步后 返回第12步 // 其中第五步vm._update(vm._render(), hydrating) // vm._render()返回my组件的vnode // vm._update执行最终页面dom渲染 /* src/core/instance/lifecycle.js */ Vue.prototype._update = function (vnode: VNode, hydrating?: boolean) { const vm: Component = this if (!prevVnode) { // initial render vm.$el = vm.__patch__(vm.$el, vnode, hydrating, false /* removeOnly */) } else { // updates vm.$el = vm.__patch__(prevVnode, vnode) } restoreActiveInstance() if (prevEl) { prevEl.__vue__ = null } if (vm.$el) { vm.$el.__vue__ = vm } // if parent is an HOC, update its $el as well if (vm.$vnode && vm.$parent && vm.$vnode === vm.$parent._vnode) { vm.$parent.$el = vm.$el } } // 执行__patch__ 更新页面 将最终真实#app 下render函数中的 // 内容转换为真实dom赋值给vm.$el /* src/core/vdom/patch.js */ 14.return function patch (oldVnode, vnode, hydrating, removeOnly) { createElm(vnode, insertedVnodeQueue) return vnode.elm } function createElm ( vnode, insertedVnodeQueue, parentElm, refElm, nested, ownerArray, index ) { // ... vnode.elm = vnode.ns ? nodeOps.createElementNS(vnode.ns, tag) : nodeOps.createElement(tag, vnode) // 创建my组件 vnode中的elm属性 = dom元素 createChildren(vnode, children, insertedVnodeQueue) // 递归创建my组件中的子元素标签(已转换为vnode) insert(parentElm, vnode.elm, refElm) // 递归插入到子元素的父级elm中 }// 将my组件嵌套的vode中的elm创建出来 // 返回到patch return vnode.elm // 返回到第13步_update // 返回到6步 value = this.getter.call(vm, vm) // 返回到第5步 mountComponent // 返回到第4步 runtime/index.js Vue.prototype.$mount // 返回到第3步 entry-runtime-with-compiler.js Vue.prototype.$mount // 返回到第13步 componentVNodeHooks // 返回到第9步 vdom/create-component.js createComponent function initComponent (vnode, insertedVnodeQueue) { if (isDef(vnode.data.pendingInsert)) { insertedVnodeQueue.push.apply(insertedVnodeQueue, vnode.data.pendingInsert) vnode.data.pendingInsert = null } vnode.elm = vnode.componentInstance.$el if (isPatchable(vnode)) { invokeCreateHooks(vnode, insertedVnodeQueue) setScope(vnode) } else { registerRef(vnode) insertedVnodeQueue.push(vnode) } } // 将组件elm插入页面中 // 返回第12步 createElm // 流程结束
2023年12月31日
5
0
0
2023-11-02
二次封装省市区组件
最新正在搭一个系统,用的h5纯原生开发的就没使用框架 也不想引用现成的ui框架 踌躇满志 :@(坐等) 磨拳擦掌 :@(欢呼) 力排众议 :@(深思) 直接选择自己手写 然后完犊子了 :@(脸红) :@(脸红) :@(脸红) 工期赶任务中 有思路知道怎么实现但是这个手啊就是敲不下去 遂又 垂头丧气 :@(小怒) 不自量力 :@(吐血倒地) 唯唯诺诺 :@(喜极而泣) 的光速打脸 遇到下拉框联动省市区的时候傻眼了麻爪了 网上一顿搜 没有合适的组件库 一度想要引入element然后直接vue完事了 但是最终还是选择了multiple-select.js 不过这个库依赖jquery 退而求其次 那就原生 jquery混写呗 下面是代码 处理过的省市区数据CITY_CODE.js<link rel="stylesheet" href="https://unpkg.com/multiple-select@1.6.0/dist/multiple-select.min.css"> <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.7.1/jquery.min.js"></script> <script src="https://unpkg.com/multiple-select@1.6.0/dist/multiple-select.min.js"></script> <script src="https://snowlove.synology.me:5106/usr/uploads/2023/11/1528140937.js"></script> <style> .city-code_wapper.city-code_wapper_citycode .multiple-select.city-code_wapper_citycode .multiple-select:last-child.city-code_wapper_citycode button.city-code_wapper_citycode button span.city-code_wapper_address.city-code_wapper_address label.city-code_wapper_address input.city-code_wapper .area,.city-code_wapper .city.city-code_wapper .ms-drop.from_input.from_input:focus </style> <div class="city-code_wapper"> <div class="city-code_wapper_citycode"> <select class="province multiple-select" placeholder="省"></select> <select class="city multiple-select" placeholder="市"> <option>市</option> </select> <select class="area multiple-select" placeholder="区"> <option>区</option> </select> </div> <div class="city-code_wapper_address"> <label>详细地址:</label> <input type="text"class="from_input detailed-address" name="address"/> </div> </div> <script> // 模板解析有问题 无发放到template中 只能抽出js单独引入 var selectParams = [] // 根据parentId获取所有子元素 const getDataByParentId = (data,parentId) => { return data.filter(item => item.parentId === parentId) } // 设置省市区数据 const updateCityCodeData = () => { window.postMessage({ type:'cityCodeMsg', newCityCode:selectParams.map(item=>item.text || item), cityCodeOriginal:selectParams }) } // 清空省市下拉数据 const clearCityOrArea = (type) => { const cityEle = $('.city'), areaEle = $('.area'), addressEle = $('.detailed-address') switch (type) { case 'city': cityEle.multipleSelect('refreshOptions', { data:[] }) break; case 'area': areaEle.multipleSelect('refreshOptions', { data:[] }) break; case 'address': addressEle.val('') break; default: cityEle.multipleSelect('refreshOptions', { data:[] }) areaEle.multipleSelect('refreshOptions', { data:[] }) addressEle.val('') break; } } // 加载jqery 多选框元素 $(function() { const provinceEle = $('.province') let initFlag = [1,0,0] provinceEle.multipleSelect({ selectAll: false, name:'province', data:Province, placeholder:'省', showClear:true, onClick: function (province) { // 清空市区数据 const cityEle = $('.city') if(!initFlag[1]){ cityEle.multipleSelect({ selectAll: false, name:'city', placeholder:'市', data:getDataByParentId(City,province.value), onClick: function (city) { const areaEle = $('.area') // console.log('areaEle',areaEle) if(!initFlag[2]){ areaEle.multipleSelect({ selectAll: false, name:'area', placeholder:'区', data:getDataByParentId(Area,city.value), onClick: function (area) { // console.log('areaEle onClick',areaEle) selectParams[2] = area updateCityCodeData() }, }) initFlag[2] = 1 } else areaEle.multipleSelect('refreshOptions', { data:getDataByParentId(Area,city.value), }) // console.log('areaEle',areaEle) selectParams[1] = city clearCityOrArea('address') updateCityCodeData() }, }) initFlag[1] = 1 } else cityEle.multipleSelect('refreshOptions', { data:getDataByParentId(City,province.value), }) selectParams = [province] if(initFlag[2]) clearCityOrArea('area') clearCityOrArea('address') // 发送消息到上层 清空已选择数据 updateCityCodeData() }, onClear: function () { selectParams = [] if(initFlag[1]) clearCityOrArea('city') if(initFlag[2]) clearCityOrArea('area') clearCityOrArea('address') updateCityCodeData() // console.log('clear') } }) // 每次组件创建 初始化数据 provinceEle.multipleSelect('setSelects', []) updateCityCodeData() // 获取详细地址 $('.detailed-address').blur(function(){ selectParams[3] = $(this).val() || '' updateCityCodeData() }) }) </script> .city-code_wapper.city-code_wapper_citycode .multiple-select.city-code_wapper_citycode .multiple-select:last-child.city-code_wapper_citycode button.city-code_wapper_citycode button span.city-code_wapper_address.city-code_wapper_address label.city-code_wapper_address input.city-code_wapper .area,.city-code_wapper .city.city-code_wapper .ms-drop .from_input{ width: 100%; border: 1px solid #c8c9cc; border-radius: 4px; padding: 5px 10px; box-sizing: border-box; outline: none; /* 去掉描边 */ color: #606266; } .from_input:focus { color: #303133; } 市 区 详细地址: // 模板解析有问题 无发放到template中 只能抽出js单独引入 var selectParams = [] // 根据parentId获取所有子元素 const getDataByParentId = (data,parentId) => { return data.filter(item => item.parentId === parentId) } // 设置省市区数据 const updateCityCodeData = () => { window.postMessage({ type:'cityCodeMsg', newCityCode:selectParams.map(item=>item.text || item), cityCodeOriginal:selectParams }) } // 清空省市下拉数据 const clearCityOrArea = (type) => { const cityEle = $('.city'), areaEle = $('.area'), addressEle = $('.detailed-address') switch (type) { case 'city': cityEle.multipleSelect('refreshOptions', { data:[] }) break; case 'area': areaEle.multipleSelect('refreshOptions', { data:[] }) break; case 'address': addressEle.val('') break; default: cityEle.multipleSelect('refreshOptions', { data:[] }) areaEle.multipleSelect('refreshOptions', { data:[] }) addressEle.val('') break; } } // 加载jqery 多选框元素 $(function() { const provinceEle = $('.province') let initFlag = [1,0,0] provinceEle.multipleSelect({ selectAll: false, name:'province', data:Province, placeholder:'省', showClear:true, onClick: function (province) { // 清空市区数据 const cityEle = $('.city') if(!initFlag[1]){ cityEle.multipleSelect({ selectAll: false, name:'city', placeholder:'市', data:getDataByParentId(City,province.value), onClick: function (city) { const areaEle = $('.area') // console.log('areaEle',areaEle) if(!initFlag[2]){ areaEle.multipleSelect({ selectAll: false, name:'area', placeholder:'区', data:getDataByParentId(Area,city.value), onClick: function (area) { // console.log('areaEle onClick',areaEle) selectParams[2] = area updateCityCodeData() }, }) initFlag[2] = 1 } else areaEle.multipleSelect('refreshOptions', { data:getDataByParentId(Area,city.value), }) // console.log('areaEle',areaEle) selectParams[1] = city clearCityOrArea('address') updateCityCodeData() }, }) initFlag[1] = 1 } else cityEle.multipleSelect('refreshOptions', { data:getDataByParentId(City,province.value), }) selectParams = [province] if(initFlag[2]) clearCityOrArea('area') clearCityOrArea('address') // 发送消息到上层 清空已选择数据 updateCityCodeData() }, onClear: function () { selectParams = [] if(initFlag[1]) clearCityOrArea('city') if(initFlag[2]) clearCityOrArea('area') clearCityOrArea('address') updateCityCodeData() // console.log('clear') } }) // 每次组件创建 初始化数据 provinceEle.multipleSelect('setSelects', []) updateCityCodeData() // 获取详细地址 $('.detailed-address').blur(function(){ selectParams[3] = $(this).val() || '' updateCityCodeData() }) })
2023年11月02日
17
0
0
2023-10-18
上古技术也还是很能打的
闲来无事搭了个门户网站的demo架子 因为seo的缘故不能使用框架(因为追求简单的几个业务面 感觉搭个架子太沉了) 所以用了挺老的技术 :@(害羞) :@(害羞) :@(害羞)gulp + art-template + web-template + js原生感觉比较符合我的需求 因为咩去找现成的门户网站参照做案例 就随便写写画画 封装了一些基础组件(我肖某人今生最爱的事情之一就是封装封装封装组件!!)下面偷懒做的适配(就根本没做骗谁呢? :@(中指):@(中指):@(中指) )移动端兼容我贼垃圾就没做 过阵子好好学学 :@(脸红) :@(脸红) .box{ position: relative; overflow: auto; margin-bottom: 30px; } .box > div{ background: url(https://snowlove.synology.me:5106/usr/uploads/2023/10/2416764179.jpg); width: 768px; height: 1024px; background-size: cover; background-repeat: no-repeat; position: relative; z-index: 1; } .box > iframe{ position: absolute; top: 210px; left: 185px; z-index: 2; border-radius: 16px; } @media screen and (max-width: 1000px) { .box{ position: relative; overflow: hidden; margin-bottom: 30px; } .box > div{ background: url(https://snowlove.synology.me:5106/usr/uploads/2023/10/2416764179.jpg); width: 85vw; height: 50vh; transform: scale3d(1.6, 1.3, 1.8); background-size: 100% 100%; background-repeat: no-repeat; position: relative; z-index: 1; top: -5vw; } .box > iframe{ position: absolute; top: 6vw; left: 5vw; z-index: 2; border-radius: 16px; width: 75vw; } } let Agents = ['Android', 'iPhone', 'SymbianOS', 'Windows Phone', 'iPad', 'iPod']; let getArr = Agents.filter(i => window.navigator.userAgent.includes(i)) let iframe = document.querySelector('.box>iframe') if(getArr[0]){ iframe.style.height = `$px` } iframe.onload = function(){ //iframe加载完立即发送一条消息 iframe.contentWindow.postMessage(,'*'); }
2023年10月18日
16
0
0
1
2
3
...
9