刚学 vue,感觉离入门到放弃不远了😂😂😂 太难了,看好几遍 cn.vuejs.org 中的那坨 guide,还是没明白用 Vue 一把梭到底能解决什么 G 点。。。
回到 v-once 这个指令,我就想在页面里面输出一行行带当前时间的 log,不知道是不是缺陷还是我写的有毛病:
//循环的 obj 里面没有额外存时间,也拒绝存时间( idx 是倒序索引,妥协加上的)
<div v-for="obj in logs" :key="obj.idx">
<template v-once>[{{ getTime() }}]</template> //无效,每个周期都会进行一次计算导致节点发生变更,
//导致所有已显示的日志都会被重新计算成当前时间
<span v-once>[{{ getTime() }}]</span> //有效,但需要多输出一个标签(细思极恐)
我们会发现 template + v-once 并不会起反应,v-once 的文档里也并没有写和 template 结合有什么效果。
但是,没有对比就没有伤害,看 v-if 文档:
> 如果元素是 <template> ,将提出它的内容作为条件块。
# 在 <template> 元素上使用 v-if 条件渲染分组
因为 v-if 是一个指令,所以必须将它添加到一个元素上。但是如果想切换多个元素呢?此时可以把一个 <template> 元素当做不可见的包裹元素,并在上面使用 v-if。最终的渲染结果将不包含 <template> 元素。
这算不算在赤裸裸的歧视 v-if 是一个另类😂 细思这也许是个什么缺陷,或者这就是别人写的代码该有的样子。
那么问题来了,v-once 这个目测也算是非常重要的指令,为什么就不能学学 v-if 特殊对待一下;或者说类似我这种类似静态方法的调用有别的手段? 静态方法,嗯,还是无参的静态方法(例子里面不要指望我会去额外存储一份时间,其他类似的结果会变化的方法调用估计也会产生此类问题)😂
太难学了,不容易入门,再不学好就要被扫地出门了😂
写了一段demo,稳定复现这个问题: http://jsrun.pro/qcWKp/edit?v=2 点开运行
反复修改不在v-for里面的 < template v-once> 和在v-for 里面的 < template v-once> 表现完全不一致。感觉应该可以实锤不是bug就是恶意的feature 😢😢😢
另外附:完全新手入门vue,遇到困难总是会有的,不过先入门还是要的,遇到麻烦直接就放弃就不太好了。不过,仅阅读https://cn.vuejs.org/v2/guide/ (阅读的纯文本,不含外链 和 video),完全搭建不出能运行的实用环境(不是学习测试,是实战,要写实际逻辑代码的),这个是事实,里面起步 明确写到 请注意我们不推荐新手直接使用 vue-cli , 我新学也不爱去用生成工具,手写配置对学习更有益。然后你会发现整篇guide 就没有写 .vue 文件该要怎么个规范去写,需要什么样的环境才能编译成js在浏览器运行。
你以为有了vue-loader就够了,实际上还要vue-template-compiler,文档有没有告诉你?没有。仅有css-loader还不够,你还要style-loader,编译es6 额外要dependencie babel,有这些才能搭建起基本的编译环境。我还是通过问别人 和 另外运行vue-cli得到有效的配置分析后 才搞定环境配置,新手手写也许是哪里路子不对。
这只是一个我目前学习中遇到的最大麻烦,其他小问题通篇找不到答案就更多了,实际遇到的时候才会发现并不是特别友好。
1
rabbbit 2019-12-03 03:05:28 +08:00
|
2
xiangyuecn OP @rabbbit 原来是要这样写才没问题😂😂,不过嵌入到 v-for 里面立马暴露出问题,测试代码: http://jsrun.pro/qcWKp/edit?v=2
运行效果蔚为壮观,看样子不是我的写法有问题就是 vue 有 bug😂 |
3
xiangyuecn OP 测试发现,外面再完全单独的套一层标签就能生效
<span><template v-once>[{{ getTime() }}]</template></span> 还不如回到原点 <span v-once>[{{ getTime() }}]</span> 还是需要多输出一个标签(细思极恐),难道不是 bug,是 feature ???😂 |
4
TangMonk 2019-12-03 04:57:42 +08:00 via iPhone
@xiangyuecn 刚起床?
|
5
xiangyuecn OP @TangMonk 还没下班😊
|
6
Terry05 2019-12-03 09:48:05 +08:00
vuejs 的 guide 已经写得这么好了,get 不到点的话放弃吧
|
7
dk7952638 2019-12-03 10:04:50 +08:00
感觉 vue 的 guide 都看不懂,确实不适合 code 了
|
8
guolaopi 2019-12-03 10:09:56 +08:00
f12 看了下,
<div> <template>{{msg}}</template> </div> 被直接渲染成了 <div> {{msg}} </div> 所以我觉得 v-once 应该写在 div 上。 <div v-once> <span v-once>{{ getTime() }}</span> {{ obj.msg }} <template >{{ getTime() }}</template> {{ obj.msg }} </div> 这样就实现了你想要的效果。 我也是正在学 vue,关于 template 不是很懂,我理解他并不是一个标签,而是把一些内容包括起来,然后直接渲染。 好像 w3c 有 template 相关标准啥的,LZ 可以深入了解一下 |
9
xiangyuecn OP @Terry05 @dk7952638 哈哈,发现两个老实人,你们说的也都是事实。
不过,两位大佬能不能看一下 我写的这个这个问题的复现代码,帮我解解惑,为啥会产生这种现象,code url: http://jsrun.pro/qcWKp/edit?v=2 |
10
Curtion 2019-12-03 11:36:04 +08:00
是这个问题吗? https://github.com/vuejs/vue/issues/8021,看来这个问题要从 VNode 中找答案,可惜我的水平不够
|
11
angel001ma 2019-12-03 11:53:11 +08:00
是有什么问题,我看代码和效果是一致的,v-once 是只渲染一次,之后绑定值变动不会重新渲染
请按问题描述,实际效果,预期效果分点写出来 |
12
xiangyuecn OP @angel001ma 你用的啥浏览器运行的是一致的?
不在 v-for 里面的 <template v-once>{{ getTime() }}</template> 是不会随着周期发生任何变化 但 v-for 里面的 <template v-once>{{ getTime() }}</template> 会变化,不符合 v-once 语义 通过使用标签 或 额外套一层标签 可修复;但是要在代码里额外去多写一个标签,比如多套一层 span,问题就在这里 |
13
marcong95 2019-12-03 12:10:24 +08:00
v-once 这个东西,好像还真没怎么用过的样子。API 里面对 v-once 的描述如下:
Render the element and component once only. 你在<template>里面用了一个 v-once,但是<template>这个东西并不是一个确定的元素或者组件,可能没有一个 VNode 与之对应,v-once 作为一个 directive 也挂不上去,所以无法实现 render only once 这个功能。但是当你在外面套一个元素之后,就可以用外面这个元素的 VNode 对应当作上文的“the element and component”了。 审查元素可以看到你写的 <template v-once>[{{ getTime() }}]</template> {{ obj.msg }} template 里面渲染的内容跟后面的 obj.msg 构成了同一个 TextNode,所以这个 TextNode 的由于有 obj.msg 的部分,所以其实不应该只渲染一次。所以 v-once 可能就被忽略了。这个可能需要研究一下<template>的行为了,但是 vue 的文档似乎没说。而且也不知道应不应该用 W3C 的东西套上去。 ----------------------------------------------- 我当初学 vue 其实感受跟你的 append 其实很一致,guide 啃完一遍了,想从头开始写个 demo 看看,连 JS 的入口都不知道怎么写,找了各种脚手架看到自动生成的代码,才发现了有 new Vue({ el: '#app', render: h => h(App) }) 这种写法才豁然开朗。Official Guide 对 Vue 本身的描写是足够了,但是对如何构成一个完整的应用还是有一定的欠缺,可能这不是 Vue.js Official Guide 应该描写的部分,但是适当引导一下可能会比较好。 |
14
nxy006 2019-12-03 12:14:55 +08:00
@xiangyuecn
v-once 的语义是,创建成功后不会被重新渲染。 V-for 外面你创建了一个元素,且被初始值渲染。 在 V-for 里,你在不断创建新的内容,新内容里的值取自创建时候的值。 你可能混淆了 “创建” 和 “创建后重新渲染” 的意思。 |
15
nxy006 2019-12-03 12:19:09 +08:00
@xiangyuecn 因此,v-once 的表达是正常的,不管在 v-for 里面还是外面,一旦创建,它的值都不会再发生改变。至于你在创建时具有不同的值,与 v-once 无关。
|
16
angel001ma 2019-12-03 12:28:01 +08:00
@xiangyuecn 明白你的意思了,确实 vue 文档没对 template 加 v-once 出现的效果做解释,原因可能是#13,具体要看 template v-once 会怎么渲染
|
17
x66 2019-12-03 12:52:20 +08:00
赞同,看完 guide 不知所措,然后还是靠重新去看视频,看 vue-cli 来实战,官方文档对初学者太不友好了。
|
18
Sendya 2019-12-03 13:03:20 +08:00 via Android
后端猿看了两小时就开始写业务了,好像没什么问题。不过独立学习 webpack 时间比学 vue 时间更长 ( ̄へ ̄)
|
19
azh7138m 2019-12-03 13:16:25 +08:00
@nxy006
如果不是 bug,那为啥 <span v-once>[{{ getTime() }}]</span> {{ obj.msg }} <template v-once>[{{ getTime() }}]</template> {{ obj.msg }} 这两种写法会有差异? |
20
xiangyuecn OP |
21
xiangyuecn OP @nxy006 #14 #15 嗯嗯,感谢你的解答😊。但目测你应该没有理解我的问题,请看一下#20 楼这幅图,你就明白了,一个不在 v-for 里,一个在 v-for 里,代码基本相同,但表现不一样。
|
22
nxy006 2019-12-03 14:13:19 +08:00
@azh7138m 确实,试了一下里面放变量也有一样的效果,是有点不对劲。从没写过 v-for 里套 template v-once 的代码,等晚上有时间了再查一下。=_=
一般不会写 <template v-once> 这种结构,如果需要应该写成 <template><div v-once> 结构。虽然没研究过这种规范具体是为什么,结果来看还是有道理的。 |
23
santom 2019-12-03 14:38:05 +08:00
<div><div><span>[6.738]</span> 日志
[58.447] 日志 |||| <span>[6.738]</span> 日志 </div></div> 这是渲染之后的实际 dom temeplate 标签作为无意义标签,我记得之前好像是为了布局优化去除很多无意义包裹层标签(其他层面不太了解),才允许在 temeplate 标签里可以不放置顶级标签的 。 在此之前 loader 解析时会直接抛错。 所以现在渲染结构中“[]”里面想渲染一次,此处添加的 v-once 应该是需要作用到实质标签上。 具体 v-if 为何效果不同,不太了解了 可能和楼上说的 VNode 及渲染解析有关系吧 |
24
rabbbit 2019-12-03 16:44:06 +08:00
|
25
xiangyuecn OP @Curtion #10 不是#8021 这个问题,它是 component 组件中的 template 属性,我的是 template 标签,完全不一样。
不过有个 vuejs 的 Contribution 同样拿这个问题来怼我,欢迎来观战,看我怎么用中式英语来怼死他,https://github.com/vuejs/vue/issues/10892 |
26
crs0910 2019-12-05 11:00:52 +08:00
@xiangyuecn #25 那个人没有怼你啦。你也不要因此影响自己心情,感觉已经和他对立起来了。
建议弄个最小的 demo 再提一次 issue 就好了,你那个 demo 搞的有点复杂了。 |
27
xiangyuecn OP @crs0910 哈哈,谢谢你啦😊。可能是我在 #25 用“怼”这个词不当,我并没有针对那个协作者,只是觉得他们处理 issue 的有欠妥当。那个 demo 我是把发现的问题和没有问题的对比代码都写进去了,也没多少,应该不好精简了。
|
28
gz911122 2019-12-05 11:45:45 +08:00
另外附:完全新手入门 vue,遇到困难总是会有的,不过先入门还是要的,遇到麻烦直接就放弃就不太好了。不过,仅阅读 https://cn.vuejs.org/v2/guide/ (阅读的纯文本,不含外链 和 video ),完全搭建不出能运行的实用环境(不是学习测试,是实战,要写实际逻辑代码的),这个是事实,里面起步 明确写到 请注意我们不推荐新手直接使用 vue-cli , 我新学也不爱去用生成工具,手写配置对学习更有益。然后你会发现整篇 guide 就没有写 .vue 文件该要怎么个规范去写,需要什么样的环境才能编译成 js 在浏览器运行。
你以为有了 vue-loader 就够了,实际上还要 vue-template-compiler,文档有没有告诉你?没有。仅有 css-loader 还不够,你还要 style-loader,编译 es6 额外要 dependencie babel,有这些才能搭建起基本的编译环境。我还是通过问别人 和 另外运行 vue-cli 得到有效的配置分析后 才搞定环境配置,新手手写也许是哪里路子不对。 这点深有同感 |