Skip to content

Props vs Attributes

Julian Müller edited this page Feb 10, 2023 · 5 revisions

I found this a bit confusing, so I experimented a bit. Here's the lessons learnt:

Using lit and typescript, I declared a property in three different ways:

  1. As an attribute
  @property({attribute: 'litprop-attr'})
  litPropAttr: string = 'default'  
  1. As a property that is not an attribute
  @property({attribute: false})
  litPropNoAttr: string = 'default'
  1. As a regular class member
  noLitPropNoAttr: string = 'default'

Then I loaded the WebComponent into a Vue Component and tried to bind a value to those variables like so:

:litprop-attr="debugVar"
:lit-prop-no-attr="debugVar"
:no-lit-prop-no-attr="debugVar"

And using the prop modifier:

:litprop-attr.prop="debugVar"
:lit-prop-no-attr.prop="debugVar"
:no-lit-prop-no-attr.prop="debugVar"

I first tested whether the binding worked, so if the default value in the WebComponent gets replaced when first rendering it.
Then I tried to trigger updates in the values by changing the value of debugVar in the Vue Component.
Lastly, I tried to set the values explicitly using document.getElementById.
Here's the results of these experiments:

Declaration Type Prop Modifier Used Updating by... Initial Binding Works Updating Works requestUpdate and updated triggered
Attribute - changing debugVar Yes Yes Yes
Property - changing debugVar No No No
Member - changing debugVar No No No
Attribute + changing debugVar No No No
Property + changing debugVar Yes Yes Yes
Member + changing debugVar Yes Yes No
Attribute - direct access Yes Yes Yes
Property - direct access No Yes Yes
Member - direct access No Yes No
Attribute + direct access No Yes Yes
Property + direct access Yes Yes Yes
Member + direct access Yes Yes No

Takeaway:

  1. As expected, using a class member as a property is not a good idea because even though it is reactive when bound with .prop, the lit hooks are never invoked.
  2. Declaring as attribute and not using .prop behaves identical to declaring as property and using .prop, at least in these experiments. The only difference I could observe so far is if I don't use .prop, the variables show up in the HTML tree: image
    Whereas if I do use .prop, they are not there: image
    I am not sure what implications this has, will update this page if I find out ;-) For now I will just always use .prop and set attribute: false.
Clone this wiki locally