注意:我是Vue的新手,但在发布之前,我已经查阅过文档并寻找其他问题。我找不到答案。我还安装了Vue dev工具来帮助调试,无法解决这个看似简单的问题。
我想制作一个简单的Vue单文件组件进行测试,看看我的汇总捆绑设置是否正常工作(例如,为了确保我对vue组件的理解,模块和导出是正确的。)
所以我的简单组件由两个较小的组件组成 - 一个带有V形按钮或一个V形按钮的按钮。我们的想法是让它位于页面中间,然后单击移动到下一个section
标记。
到目前为止,我的功能非常好(见demo)。
但是,我想将属性传递给两个子组件 - 一个offsetSelector。无论我如何尝试设置属性,我都无法在父级别设置它(例如v-bind:offsetSelector=".navbar"
,:offsetSelector=".navbar"
,offsetSelector=".navbar"
等。
有人可以帮我弄清楚为什么不受约束?
<template>
<div>
<up :offsetSelector="offsetSelector"></up>
<down :offsetSelector="offsetSelector"></down>
</div>
</template>
<script>
import down from './section-down.vue';
import up from './section-up.vue';
export default {
components: { down, up },
props: [ 'offsetSelector' ],
data: function () {
return { }
}
}
</script>
<style scoped>
div {
position: fixed;
top:50%;
margin-left: 10px;
}
div > button {
display: block;
margin-bottom: 10px !important;
}
</style>
<template>
<button type="button" name="button" v-on:click="animateScrollTo">
<i class="fa fa-chevron-down"></i>
</button>
</template>
<script>
export default {
props: [ 'offsetSelector' ],
data: function () {
return {
offset: 0
}
},
computed: {
},
methods: {
setOffset: function() {
this.offset = this.offsetSelector == undefined
? 0
: $(this.offsetSelector).outerHeight() == undefined
? 0
: $(this.offsetSelector).outerHeight()
},
animateScrollTo: function() {
this.setOffset()
var sections = document.querySelectorAll("section")
var current = undefined;
var curOffset = this.offset
console.log('vue-down-offset', curOffset, this.offsetSelector)
sections.forEach(function(s, i){
var winScroll = $(window).scrollTop() - curOffset
var curScroll = $(s).offset().top
if ( winScroll < curScroll && current == undefined)
{ current = s }
})
if (current != undefined) {
$('html, body').animate({
scrollTop: $(current).offset().top - curOffset
}, 1000, function() {});
}
}
}
}
</script>
<style scoped>
button {
background: radial-gradient(rgb(0, 198, 255), rgb(0, 114, 255));
background-color: transparent;
border: transparent 0px solid;
margin: 0;
padding: 0px;
width:32px;
height:32px;
border-radius: 50%;
}
i { font-size: 16px; }
button:focus {
outline: transparent 0px solid;
}
</style>
<template>
<button type="button" name="button" v-on:click="animateScrollTo">
<i class="fa fa-chevron-up"></i>
</button>
</template>
<script>
export default {
props: [ 'offsetSelector' ],
data: function () {
return { offset: 0 }
},
computed: { },
methods: {
setOffset: function() {
this.offset = this.offsetSelector == undefined
? 0
: $(this.offsetSelector).outerHeight() == undefined
? 0
: $(this.offsetSelector).outerHeight()
},
animateScrollTo: function() {
this.setOffset()
var sections = document.querySelectorAll("section")
var current = undefined;
var curOffset = this.offset
console.log('vue-up-offset', curOffset, this.offsetSelector)
sections.forEach(function(s, i){
var winScroll = $(window).scrollTop()
var curScroll = $(s).offset().top - curOffset
if ( winScroll > curScroll)
{ current = s }
})
if (current == undefined) {
current = document.querySelector("body")
}
if (current != undefined) {
$('html, body').animate({
scrollTop: $(current).offset().top - curOffset
}, 1000, function() {});
}
}
}
}
</script>
<style scoped>
button {
background: radial-gradient(rgb(0, 198, 255), rgb(0, 114, 255));
background-color: transparent;
border: transparent 0px solid;
margin: 0;
padding: 0px;
width:32px;
height:32px;
border-radius: 50%;
}
button:focus {
outline: transparent 0px solid;
}
i { font-size: 16px; }
</style>
<style media="screen">
section {
height: 100vh;
}
</style>
<body>
<nav class="navbar navbar-light sticky-top">
<a class="navbar-brand" href="../../">
<img src="../../data/vdsm.svg" alt="logo" style="width:150px;">
<h4 class="lead"> vue components </h4>
</a>
<crumbs id="crumbs"></crumbs>
</nav>
<arrowToSection id="arrowToSection" offset-selector=".navbar"></arrowToSection>
<section style="background-color:#5433FF;"></section>
<section style="background-color:#20BDFF;"></section>
<section style="background-color:#A5FECB;"></section>
<section style="background-color:#86fde8;"></section>
</body>
<script type="text/javascript" src="component.js"></script>
let arrowToSection = vdsm.arrowToSection
new Vue({
el: '#arrowToSection',
template: '<arrowToSection/>',
components: { arrowToSection }
})
可以找到回购here。
两个子组件:
我正在处理的组件:
组件演示:
答案 0 :(得分:2)
我还没有完全阅读您的存储库,但从我可以看到的答案可以在这里找到:https://vuejs.org/v2/guide/components-props.html
HTML属性名称不区分大小写,因此浏览器会解释 任何大写字符为小写。这意味着当你使用时 in-DOM模板,camelCased道具名称需要使用他们的kebab-cased (连字符分隔)等价物:
道具列表中的道具基本上是camelCase
,但在html属性中它是kebap-case
。我希望有帮助:)
答案 1 :(得分:1)
实际上,答案非常简单:你不在你的arrowToSection
组件上添加任何道具。虽然在你的身体中有一个令人困惑的名为<arrowToSection>
的元素,但它上面没有安装arrowToSection组件 - 至少不能直接安装。您可以在component.js
中创建的匿名Vue实例中创建arrowToSection组件,此处为:template: '<arrowToSection/>'
。你没有传递任何道具。
要修复它,你需要在这里传递道具:
let arrowToSection = vdsm.arrowToSection
new Vue({
el: '#arrowToSection',
template: '<arrowToSection :offsetSelector="'.navbar'" />',
components: { arrowToSection }
})
接下来,您可能会问“为什么不向此匿名元素添加道具,并使用在HTML中设置的值”。答案是,道具是在Vue组件之间传递值的方式。外部HTML不是Vue组件,您不能从那里传递道具。您放在#arrowToSection
元素上的属性只是普通属性(整个元素被替换,参数丢失,顺便说一句)。
稍后注意:This example in documentation显示从HTML元素中明显读取的属性。这似乎与我的实验有点矛盾。如果您使用完整的v-bind:prop="..."
表示法而不是:prop="..."
速记,则传递道具可能会有效。
propsData
如果您真的想使用道具,可以使用propsData:
let arrowToSection = vdsm.arrowToSection
new Vue({
el: '#arrowToSection',
props: ['offsetSelector'],
propsData: {
offsetSelector: '.navbar',
},
template: '<arrowToSection :offsetSelector="offsetSelector" />',
components: { arrowToSection }
})
如你所见,这是非常人为的,没有意义。但是,您并不真正需要中间组件,因此,至少在实践中,您可以这样使用propsData
:
let arrowToSection = vdsm.arrowToSection
new Vue(Object.assign({}, arrowToSection, {
el: '#arrowToSection',
propsData: {
offsetSelector: '.navbar',
},
}))
免责声明:我不确定正式支持使用这种方式的组件。可能不是。但它确实有效。