定位网站源码-因为一种写作方式,我翻了 vue 源代码,这是 vue 的问题,要不要提一下 pr!
首先我设置了一个计时器定位网站源码,绑定到计时器的样式由上面代码中的一个变量控制,尽管计时器一直在执行
但是,由于值 bg 是一个常量,理论上他的页面背景应该始终显示为红色
有人问定位网站源码,为什么要把它设置为白色?
好吧,这不是重点,可能是因为我们是黄色的。
然而,现实是它在红色和没有颜色之间徘徊,为什么?
问题发现过程
好奇,我想知道的第一件事是我不明白 Vue 风格动态值的绑定
探索 VUE 文档
我曾经是
焦虑并找到了 Vue 文档,我只需要确认两件事:
样式中绑定数据的规则和样式编写骆驼的规则
我们可以在他的官方文件中找到答案
<div :style="[baseStyles, overridingStyles]">
他的绑定朴实无华,当我查看源代码时,我得出结论,数组后面的变量覆盖了前面的变量
源代码如下:
export function normalizeStyle(
value: unknown
): NormalizedStyle | string | undefined {
if (isArray(value)) {
const res: NormalizedStyle = {}
for (let i = 0; i < value.length; i++) {
const item = value[i]
const normalized = isString(item)
? parseStringStyle(item)
: (normalizeStyle(item) as NormalizedStyle)
if (normalized) {
for (const key in normalized) {
res[key] = normalized[key]
}
}
}
return res
} else if (isString(value)) {
return value
} else if (isObject(value)) {
return value
}
}
同样通过上面的源码内容可以发现,他并没有对类似的背景色和背景色做统一的格式处理,虽然这个所谓的 normalizeStyle 是对绑定值做一个集成处理,方便后续绑定中的统一处理循环绑定。
至此,我们首先排除了代码的编写错误,然后我的故障排除方向应该是 vue 源代码中的线索。
所以我首先将问题定位在源代码中的模板解析错误
查看模板分辨率
我们知道 vue 模板的编译结果可以在浏览器中查看,有两种查看方式
编译结果可以直接在 vue-devtools 中查看
图片.png
从源码中我们可以看到,他先调用上面的 normalizeStyle 来处理绑定样式,然后调用 createElementVNode 创建虚拟节点
当然,如果你不喜欢 Vue 提供的不清楚和不清楚的,请不要担心......
我们还可以看到浏览器控制台北部的疲劳
在浏览器中查看
图片.png
如上图所示,在开发环境中,我们可以借助 sourcemap 完美查看整个代码结构,以及编译好的源码,包括他的参考链,他也可以断点!
从上面的代码中,我们可以清楚地看到,这个常量值确实已经编译成功了。
在这种情况下,我开始怀疑这是createElementVNode的问题。
疑难解答 createElementVNode
function createBaseVNode(
type: VNodeTypes | ClassComponent | typeof NULL_DYNAMIC_COMPONENT,
props: (Data & VNodeProps) | null = null,
children: unknown = null,
patchFlag = 0,
dynamicProps: string[] | null = null,
shapeFlag = type === Fragment ? 0 : ShapeFlags.ELEMENT,
isBlockNode = false,
needFullChildrenNormalization = false
) {
const vnode = {
__v_isVNode: true,
__v_skip: true,
type,
props,
key: props && normalizeKey(props),
ref: props && normalizeRef(props),
scopeId: currentScopeId,
slotScopeIds: null,
children,
component: null,
suspense: null,
ssContent: null,
ssFallback: null,
dirs: null,
transition: null,
el: null,
anchor: null,
target: null,
targetAnchor: null,
staticCount: 0,
shapeFlag,
patchFlag,
dynamicProps,
dynamicChildren: null,
appContext: null,
ctx: currentRenderingInstance
} as VNode
if (needFullChildrenNormalization) {
normalizeChildren(vnode, children)
if (__FEATURE_SUSPENSE__ && shapeFlag & ShapeFlags.SUSPENSE) {
; (type as typeof SuspenseImpl).normalize(vnode)
}
} else if (children) {
vnode.shapeFlag |= isString(children)
? ShapeFlags.TEXT_CHILDREN
: ShapeFlags.ARRAY_CHILDREN
}
if (__DEV__ && vnode.key !== vnode.key) {
warn(`VNode created with invalid key (NaN). VNode type:`, vnode.type)
}
if (
isBlockTreeEnabled > 0 &&
!isBlockNode &&
currentBlock &&
(vnode.patchFlag > 0 || shapeFlag & ShapeFlags.COMPONENT) &&
vnode.patchFlag !== PatchFlags.HYDRATE_EVENTS
) {
currentBlock.push(vnode)
}
if (__COMPAT__) {
convertLegacyVModelProps(vnode)
defineLegacyVNodeProperties(vnode)
}
return vnode
}
export { createBaseVNode as createElementVNode }
从上面的代码中我们发现,其实 createElementVNode 主要只做一件事,就是创建虚拟节点,而虚拟节点包含样式信息
效果图如下:
图片.png
从上图中我们可以看到他确实包含两个属性,这意味着这个 vnode 应该包含所有的样式信息,并且没有缺席,那么只能是样式更新的问题
样式更新
说到风格更新,还是要有老规矩,从经过牛家村的山机开始
在样式的更新操作中,补丁功能是无法避免的,以及diff过程,主要过程
这个过程我们就不多说了,聊的人够多了,嘴皮都破了,就这两句话,没什么新鲜事,我主要讲一下diff流程和风格相关的内容,在diff过程中,变化响应处理函数的种类很多,我们的props处理对应的是patchProp函数的代码如下:
export const patchProp: DOMRendererOptions['patchProp'] = (
el,
key,
prevValue,
nextValue,
isSVG = false,
prevChildren,
parentComponent,
parentSuspense,
unmountChildren
) => {
patchStyle(el, prevValue, nextValue)
}
patchProp 函数中还有 patchStyle 函数,专门用来处理内联样式,代码如下:
export function patchStyle(el: Element, prev: Style, next: Style) {
const style = (el as HTMLElement).style
const isCssString = isString(next)
if (next && !isCssString) {
for (const key in next) {
setStyle(style, key, next[key])
}
if (prev && !isString(prev)) {
for (const key in prev) {
if (next[key] == null) {
setStyle(style, key, '')
}
}
}
} else {
const currentDisplay = style.display
if (isCssString) {
if (prev !== next) {
style.cssText = next as string
}
} else if (prev) {
el.removeAttribute('style')
}
if ('_vod' in el) {
style.display = currentDisplay
}
}
}
看到这里,我相信你已经可以一眼看出来了
图片.png
图片.png
根本原因是 Vue 内部没有风格写作来标准化,经过测试,Vue2 也会有这个问题,所以不知道这是不是特别刻意,他不让你这样写
其实按照我的浅薄理解,解决方案很简单,我们只需要把代码标准化为骆驼写,或者连字符写,vue3 源码也给了我们相应的功能
const camelizeRE = /-(w)/g
const camelize = cacheStringFunction(str => {
return str.replace(camelizeRE, (_, c) => (c ? c.toUpperCase() : ''))
})
onst hyphenateRE = /B([A-Z])/g const hyphenate = cacheStringFunction((str: string) => str.replace(hyphenateRE, '-$1').toLowerCase() )
而我们只需要在 normalizeStyle 函数中处理它,代码如下:
if (normalized) {
for (const key in normalized) {
res[hyphenate(key)] = normalized[hyphenate(key)]
}
}
好的,现在
问题解决了,那你需要问灵魂吗?
vue 源代码中是否有故意尝试不解决这个问题?他是用例的选择吗?你能知道吗?
热门推荐
该程序被许多高权威网站使用经典网站源码,如上海分类目录,70dir,360分类信息等。
上次我发的这种源码,只有经典模板经典网站源码,这次上传新版本的模板,外观比较好,如果用同样的程序,可以直接下载导出。
如果有学生想做URL导航或者分类,这个源码是可以看出来的,对应的速率和功能还是很强的,唯一不好的是官方不再更新,全靠自己的美化。不过,相信在座各位的技术还是够硬的,这点美化也不难。接下来,我们来谈谈安装步骤:
类别安装说明:
安装前需要规划服务器和域名。源码中的网站缩略图和登录验证码不显示的问题早已解决。接下来,开始安装教程:
1. 将程序上传到网站的根目录
2. 运行您的域/安装/并按照提示安装程序
3. 登录后台您的域名/系统/登录名.php
4. 设置网站信息
5. 基本完成
模板截图:
后台地址:您的域名/系统/登录名.php帐户密码在安装时刚刚安装
这里单独说明,如果在后台设置了链接显示格式,则需要填写伪静态规则。这是我们在 Apache 环境中的 .htaccess 文件。
源代码:
演示站:
安装教程和伪静态:
如果您在安装和使用过程中有任何疑问,可以留言