Reference Attributes
In qingkuai, reference attributes are a syntax for passing variable references by prefixing attribute names with &
(e.g., &value). They allow you to establish reference relationships between attributes and external variables in templates, enabling direct read/write access to attribute values from outside, thus achieving flexible data linkage and state transfer.
JavaScript itself doesn't support pass-by-reference, but qingkuai implements a mechanism similar to references (pointers) in languages like C, C++, and Go. Using reference attributes, variables can be explicitly "passed by reference" into elements or components, allowing you to share and manipulate the same state source across multiple contexts. This mechanism is concise yet powerful, enhancing expressiveness and control in template state management. Observe this pseudocode to understand the difference between pass-by-reference and pass-by-value:
let number = 10
function passByValue(n) {
// In pass-by-value, n is a copy of number,
// they occupy two separate memory locations,
// modifying n won't affect the original number value.
n = n + 1
}
function passByReference(n) {
// * is the dereference operator, and it is used to:
// Reads the value at the memory location pointed to by pointer n,
// increments it by 1, then writes the result back to that location.
*n = *n + 1
}
passByValue(number)
console.log(number) // 10
// & is the address-of operator, and it is used to:
// Gets the memory address of variable number,
// and passes it as an argument to passByReference.
passByReference(&number)
console.log(number) // 11
Accessing DOM Elements
When you need to access the DOM element corresponding to a regular tag in templates, you can add the &dom
attribute to that element:
- js
- ts
<lang-ts>
import { onAfterMount } from "qingkuai"
let div!: HTMLDivElement
onAfterMount(() => console.log(div))
</lang-ts>
<div &dom={div}></div>
<lang-ts>
import { onAfterMount } from "qingkuai"
let div: HTMLDivElement
onAfterMount(() => console.log(div!))
</lang-ts>
<div &dom={div}></div>
onAfterMount
is qingkuai's callback method after component mounting and rendering completes, part of the component lifecycle.
&dom
attribute values are strictly typed - e.g. HTMLDivElement for div
tags, HTMLParagraphElement for p
elements. You can also use the base class HTMLElement.
Like dynamic attributes, when reference attribute names match variable names, the interpolation block can be omitted, making these two syntaxes equivalent:
<div &dom></div>
<div &dom={dom}></div>
class
or for
attributes.
Form Input Handling
For forms, we often need to synchronize input field contents with corresponding variables in embedded scripts. Typically, we might use dynamic value
attributes in input
elements and listen for user input to update variables:
- js
- ts
<lang-js>
let inputValue = "Initial value"
</lang-js>
The inputValue is: {inputValue} <br />
<input
type="text"
!value={inputValue}
@input={inputValue = $args.target.value}
/>
<lang-ts>
let inputValue = "Initial value"
</lang-ts>
The inputValue is: {inputValue} <br />
<input
type="text"
!value={inputValue}
@input={inputValue = ($args.target as HTMLInputElement).value}
/>
Instead of the somewhat cumbersome approach above, we can achieve this more concisely using &value
reference attributes:
<lang-js>
let inputValue = "Initial value"
</lang-js>
The inputValue is: {inputValue} <br />
<input
type="text"
&value={inputValue}
/>
Valid Reference Attribute Values
Like other languages supporting pass-by-reference, reference attribute values must be addressable
and non-constant. You can roughly understand them as expressions that can appear on the left side of an assignment:
<!-- Valid values -->
<p &dom={identifier}></p>
<p &dom={arr[index]}></p>
<p &dom={obj.property}></p>
<!-- Invalid values -->
<p &dom={test()}></p>
<p &dom={arr?.[index]}></p>
<p &dom={obj?.property}></p>
<p &dom={condition ? v1: v2}></p>