Vuejs子组件中的属性值无法绑定到元素属性 [英] Prop value in Vuejs child component not available to bind to element attribute
问题描述
我正在使用Vuetify在Vuejs中开发一个管理应用程序,并且在表单中有三个字段供用户选择十六进制颜色值。为了使用户更容易,我基于此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>
从{vue-color'导入{Chrome}
导出默认值{
道具:{
fieldName:字符串,
initColor:字符串
},
组件:{
'chrome-picker':Chrome
},
data(){
return {
颜色:{
hex:'#000000',
},
colorValue:this.initColor,
displayPicker:false,
}
},已安装
){
this.setColor(this.color ||'#3121e0');
},
方法:{
setColor(color){
this.updateColors(color);
this.colorValue = color;
},
updateColors(color){
if(color.slice(0,1)=='#'){
this.colors = {
十六进制: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)
}
},
手表:{
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;
高度:50像素;
显示:inline-block;
background-color:#EEE;
职位:相对;
}
.color-picker-inner {
width:30px;
高度:30像素;
职位:相对;
top:10像素;
左:13px;
显示:inline-block;
}
.vc-chrome {
position:absolute;
top:0像素;
左:55px;
z-index:9;
}
< / style>
这就是我从父 TenantTemplateEdit.vue调用的方式
< v-layout row>
< v-flex xs4>
< v文本字段
v-bind = fields.alertBackgroundColor
v-model = templateModel.alertBackgroundColor
占位符=#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>
<!-警告文本颜色->
< v-flex xs4>
< v文本字段
v-bind = fields.alertTextColor
v-model = templateModel.alertTextColor
占位符=#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>
我正在努力解决的问题是为<$ c设置初始颜色更改数据时的$ c> span.color-picker-inner 元素。并且 ColorPickerButton
组件是从 TenantTemplateEdit
调用的。我已验证 initColor
道具是否正确传递,并且可以在 ColorPickerButton
中使用,但我没有得到到模板中的 background-color
属性。
要获得<$ c $,我需要更改什么c> background-color 是在初始加载时设置的吗?
如果您纠正了一些错字等(例如 string 而不是 String , v-bind 中没有参数,请清除
这是一个有效的示例(内部颜色随您选择新颜色而变化,并且在初始加载时设置):
https://codesandbox.io/s/p9620jzoy7
我希望我正确理解了您的问题,此代码段对您有所帮助。
我粘贴了代码在这里(公司de已编辑,因此可以在沙盒环境中使用):
// ColorPickerButton.vue
<模板>
< div ref = colorpicker class = color-picker-outer>
< span
class = color-picker-inner
:style = {'background-color':colorValue}
@ click = togglePicker
>< / span>
子级初始化:{{initColor}}
子级颜色:{{colorValue}}
< chrome-picker:value = colors @ input = updateFromPicker v-if = displayPicker />
< / div>
< / template>
< script>
从 vue-color导入{Chrome};
导出默认值{
道具:{
fieldName:字符串,
initColor:字符串
},
分量:{
chrome-picker:Chrome
},
data(){
return {
颜色:{
十六进制:#000000
},
colorValue:this.initColor,
displayPicker:false
};
},
mount(){
//实际上没有这样的东西'this.color'
//在模板中
// this.setColor(this .color ||#3121e0);
},
方法:{
setColor(color){
this.updateColors(color);
this.colorValue = color;
},
updateColors(color){
if(color.slice(0,1)===#){
this.colors = {
十六进制:color
};
}否则if(color.slice(0,4)=== rgba){
var rgba = color.replace(/ ^ rgba?\(| \s + | \) $ / g,).split(,),
十六进制=
# +
(
(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;
}否则{
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);
}
},
手表:{
initColor:function(newVal,oldVal){
console.log(newVal);
this.colorValue = newVal;
}
}
};
< / script>
< style scoped>
div.color-picker-outer {
width:55px;
高度:50像素;
显示:inline-block;
background-color:#EEE;
职位:相对;
}
.color-picker-inner {
width:30px;
高度:30像素;
职位:相对;
top:10像素;
左:13px;
显示:inline-block;
}
.vc-chrome {
position:absolute;
top:0像素;
左:55px;
z-index:9;
}
< / style>
另一个模板:
// TenantTemplateEdit.vue
< template>
< v-layout行>
< v-flex xs4>
< v文本字段
v-bind:field-name = fields.alertBackgroundColor
v-model = templateModel.alertBackgroundColor
placeholder =#4A4A4A
/>
父级:{{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>
<!-警告文本颜色->
< v-flex xs4>
< v文本字段
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>
从 ./ColorPickerButton导入ColorPickerButton;
导出默认值{
组件:{
ColorPickerButton
},
data(){
return {
字段:{
alertBackgroundColor:#00ff00,
alertTextColor:#ff0000
},
templateModel:{
alertBackgroundColor:#00ff00,
alertTextColor:#ff0000
}
};
},
方法:{
getUpdatedColor(colorValue,fieldName){
this.fields [fieldName] = colorValue;
this.templateModel [fieldName] = colorValue;
}
}
};
< / script>
编辑
<我更新了沙箱(以及SO上的代码)以从输入字段开始工作。我认为它可以完成应有的功能。
I am working on an admin app in Vuejs with Vuetify, and I have three fields in a form for a user to select a hex color value. To make it easier for the user, I have implemented a color picker based off of this codepen.
Here is the ColorPickerButton
component:
<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>
and here is how I call it from the parent TenantTemplateEdit.vue
component.
<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>
The issue I'm struggling with is setting the initial color for the span.color-picker-inner
element when the data is changed. and the ColorPickerButton
component is called from TenantTemplateEdit
. I have verified that the initColor
prop is being properly passed and is available in ColorPickerButton
, but what I have is not getting to my background-color
attribute in the template.
What do I need to change to get background-color
set on initial load?
If you correct some typos and such (like string instead of String, no parameters at v-bind, clearing out the mounted() hook in the picker template) in the code, it should work.
Here's a working example (the inner color changes as you pick a new color, and it's set on initial load):
https://codesandbox.io/s/p9620jzoy7
I hope I correctly understood your problem and this snippet helps.
I paste the code here (the code is edited so it can be used in a sandbox environment):
// 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>
The other template:
// 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>
EDIT
I updated the sandbox (and the code here on SO) to work from the input field. I think it does everything it's supposed to do.
这篇关于Vuejs子组件中的属性值无法绑定到元素属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!