Vuejs 子组件中的道具值无法绑定到元素属性
Posted
技术标签:
【中文标题】Vuejs 子组件中的道具值无法绑定到元素属性【英文标题】:Prop value in Vuejs child component not available to bind to element attribute 【发布时间】:2019-09-24 16:30:32 【问题描述】:我正在使用 Vuetify 在 Vuejs 中开发一个管理应用程序,并且我在表单中有三个字段供用户选择十六进制颜色值。为了方便用户,我实现了一个基于this codepen 的颜色选择器。
这里是ColorPickerButton
组件:
<template>
<div ref="colorpicker" class="color-picker-outer">
<span class="color-picker-inner" v-bind:style=" 'background-color': colorValue" @click="togglePicker"></span>
<chrome-picker :value="colors" @input="updateFromPicker" v-if="displayPicker" />
</div>
</template>
<script>
import Chrome from 'vue-color'
export default
props:
fieldName: String,
initColor: string
,
components:
'chrome-picker': Chrome
,
data()
return
colors:
hex: '#000000',
,
colorValue: this.initColor,
displayPicker: false,
,
mounted()
this.setColor(this.color || '#3121e0');
,
methods:
setColor(color)
this.updateColors(color);
this.colorValue = color;
,
updateColors(color)
if(color.slice(0, 1) == '#')
this.colors =
hex: color
;
else if(color.slice(0, 4) == 'rgba')
var rgba = color.replace(/^rgba?\(|\s+|\)$/g,'').split(','),
hex = '#' + ((1 << 24) + (parseInt(rgba[0]) << 16) + (parseInt(rgba[1]) << 8) + parseInt(rgba[2])).toString(16).slice(1);
this.colors =
hex: hex,
a: rgba[3],
,
showPicker()
document.addEventListener('click', this.documentClick);
this.displayPicker = true;
,
hidePicker()
document.removeEventListener('click', this.documentClick);
this.displayPicker = false;
,
togglePicker()
this.displayPicker ? this.hidePicker() : this.showPicker();
,
updateFromInput()
this.updateColors(this.colorValue);
,
updateFromPicker(color)
this.colors = color;
if(color.rgba.a == 1)
this.colorValue = color.hex;
else
this.colorValue = 'rgba(' + color.rgba.r + ', ' + color.rgba.g + ', ' + color.rgba.b + ', ' + color.rgba.a + ')';
,
documentClick(e)
var el = this.$refs.colorpicker,
target = e.target;
if(el !== target && !el.contains(target))
this.hidePicker()
this.$emit('update-color', this.colorValue, this.fieldName)
,
watch:
colorValue(val)
if(val)
this.updateColors(val);
this.$emit('input', val);
//document.body.style.background = val;
</script>
<style scoped>
div.color-picker-outer
width: 55px;
height: 50px;
display: inline-block;
background-color: #EEE;
position: relative;
.color-picker-inner
width: 30px;
height: 30px;
position: relative;
top: 10px;
left: 13px;
display: inline-block;
.vc-chrome
position: absolute;
top: 0px;
left: 55px;
z-index: 9;
</style>
这是我从父组件TenantTemplateEdit.vue
调用它的方式。
<v-layout row>
<v-flex xs4>
<v-text-field
v-bind="fields.alertBackgroundColor"
v-model="templateModel.alertBackgroundColor"
placeholder="#4A4A4A"
/>
</v-flex>
<v-flex xs2>
<ColorPickerButton
v-bind:field-name="'alertBackgroundColor'"
v-bind:init-color="templateModel.alertBackgroundColor"
v-on:update-color="getUpdatedColor">
</ColorPickerButton>
</v-flex>
<!-- Alert Text Color -->
<v-flex xs4>
<v-text-field
v-bind="fields.alertTextColor"
v-model="templateModel.alertTextColor"
placeholder="#4A4A4A"
/>
</v-flex>
<v-flex xs2>
<ColorPickerButton
v-bind:field-name="'alertTextColor'"
v-bind:init-color="templateModel.alertTextColor"
v-on:update-color="getUpdatedColor"
></ColorPickerButton>
</v-flex>
</v-layout>
我正在努力解决的问题是在数据更改时为span.color-picker-inner
元素设置初始颜色。并且ColorPickerButton
组件是从TenantTemplateEdit
调用的。我已验证 initColor
属性已正确传递并且在 ColorPickerButton
中可用,但我没有在模板中访问我的 background-color
属性。
我需要更改什么才能在初始加载时设置background-color
?
【问题讨论】:
如何从 TenantTemplateEdit 传递initColor
?例如::init-color="SomeColorCode"
还是什么?
@click="togglePicker()" 应该是 @click="togglePicker" (forum.vuejs.org/t/…),因为你没有通过函数的任何参数。
你有错误吗?您是否检查过元素并看到该样式确实没有被应用?您是否首先记录 colorValue
以查看它是否具有正确的字符串值?你能在codepen上重现吗? (如果“background-color
属性”是指样式属性)
@ajafari 我更新了上面的代码。
@muka.gergely 谢谢,已修复。
【参考方案1】:
如果你更正了一些拼写错误等(如 string 而不是 String,v-bind 处没有参数,清除 mounted() 钩子在选择器模板中),它应该可以工作。
这是一个工作示例(内部颜色会随着您选择新颜色而变化,并且在初始加载时设置):
https://codesandbox.io/s/p9620jzoy7
我希望我正确理解了您的问题,并且这个 sn-p 对您有所帮助。
我把代码贴在这里(代码经过编辑,可以在沙盒环境中使用):
// ColorPickerButton.vue
<template>
<div ref="colorpicker" class="color-picker-outer">
<span
class="color-picker-inner"
:style=" 'background-color': colorValue"
@click="togglePicker"
></span>
Child init: initColor
Child color: colorValue
<chrome-picker :value="colors" @input="updateFromPicker" v-if="displayPicker"/>
</div>
</template>
<script>
import Chrome from "vue-color";
export default
props:
fieldName: String,
initColor: String
,
components:
"chrome-picker": Chrome
,
data()
return
colors:
hex: "#000000"
,
colorValue: this.initColor,
displayPicker: false
;
,
mounted()
// actually there's no such as 'this.color'
// in this template
// this.setColor(this.color || "#3121e0");
,
methods:
setColor(color)
this.updateColors(color);
this.colorValue = color;
,
updateColors(color)
if (color.slice(0, 1) === "#")
this.colors =
hex: color
;
else if (color.slice(0, 4) === "rgba")
var rgba = color.replace(/^rgba?\(|\s+|\)$/g, "").split(","),
hex =
"#" +
(
(1 << 24) +
(parseInt(rgba[0], 10) << 16) +
(parseInt(rgba[1], 10) << 8) +
parseInt(rgba[2], 10)
)
.toString(16)
.slice(1);
this.colors =
hex: hex,
a: rgba[3]
;
,
showPicker()
document.addEventListener("click", this.documentClick);
this.displayPicker = true;
,
hidePicker()
document.removeEventListener("click", this.documentClick);
this.displayPicker = false;
,
togglePicker()
this.displayPicker ? this.hidePicker() : this.showPicker();
,
updateFromInput()
this.updateColors(this.colorValue);
,
updateFromPicker(color)
this.colors = color;
if (color.rgba.a === 1)
this.colorValue = color.hex;
else
this.colorValue =
"rgba(" +
color.rgba.r +
", " +
color.rgba.g +
", " +
color.rgba.b +
", " +
color.rgba.a +
")";
,
documentClick(e)
var el = this.$refs.colorpicker,
target = e.target;
if (el !== target && !el.contains(target))
this.hidePicker();
this.$emit("update-color", this.colorValue, this.fieldName);
,
watch:
initColor: function(newVal, oldVal)
console.log(newVal);
this.colorValue = newVal;
;
</script>
<style scoped>
div.color-picker-outer
width: 55px;
height: 50px;
display: inline-block;
background-color: #EEE;
position: relative;
.color-picker-inner
width: 30px;
height: 30px;
position: relative;
top: 10px;
left: 13px;
display: inline-block;
.vc-chrome
position: absolute;
top: 0px;
left: 55px;
z-index: 9;
</style>
另一个模板:
// TenantTemplateEdit.vue
<template>
<v-layout row>
<v-flex xs4>
<v-text-field
v-bind:field-name="fields.alertBackgroundColor"
v-model="templateModel.alertBackgroundColor"
placeholder="#4A4A4A"
/>
Parent: templateModel.alertBackgroundColor
</v-flex>
<v-flex xs2>
<ColorPickerButton
v-bind:field-name="'alertBackgroundColor'"
v-bind:init-color="templateModel.alertBackgroundColor"
v-on:update-color="getUpdatedColor"
></ColorPickerButton>
</v-flex>
<!-- Alert Text Color -->
<v-flex xs4>
<v-text-field
v-bind:field-name="fields.alertTextColor"
v-model="templateModel.alertTextColor"
placeholder="#4A4A4A"
/>
</v-flex>
<v-flex xs2>
<ColorPickerButton
v-bind:field-name="'alertTextColor'"
v-bind:init-color="templateModel.alertTextColor"
v-on:update-color="getUpdatedColor"
></ColorPickerButton>
</v-flex>
</v-layout>
</template>
<script>
import ColorPickerButton from "./ColorPickerButton";
export default
components:
ColorPickerButton
,
data()
return
fields:
alertBackgroundColor: "#00ff00",
alertTextColor: "#ff0000"
,
templateModel:
alertBackgroundColor: "#00ff00",
alertTextColor: "#ff0000"
;
,
methods:
getUpdatedColor(colorValue, fieldName)
this.fields[fieldName] = colorValue;
this.templateModel[fieldName] = colorValue;
;
</script>
编辑
我更新了沙箱(以及 SO 上的代码)以在输入字段中工作。我认为它做了它应该做的一切。
【讨论】:
完美!我用你的代码修复了我的代码,它运行良好。感谢您花时间这样做。 我很高兴能帮上忙以上是关于Vuejs 子组件中的道具值无法绑定到元素属性的主要内容,如果未能解决你的问题,请参考以下文章