点亮元素 属性 也传递了另一个 function/class
lit element property passing too another function/class
我目前正在学习如何使用 lit-elements,而且我也是网络开发的新手。我正在尝试制作一个蓝牙自定义元素,它根据蓝牙设备是否连接来更改按钮文本和颜色。
在我的 litelement 中,我创建了另一个名为 BTLE 的 class,所有蓝牙都在其中处理。
但是我不知道如何将 litelement 属性 传递给这个 BTLE class。
当 BTLE class 注意到连接或断开连接时,我希望我的按钮重新呈现。
如果我通过 constuctor 通过 BTLE class 传递 属性 并更改 属性 按钮不会重新呈现。如果我更改 litelement class 中的 属性 它会重新呈现。
我在我的 litelement class 中创建了一个回调函数作为解决方法。所以蓝牙 class 是这样创建的:
this.bluetoothGatt = new BTLEclass(this.bluetoothDevice, this, this.bluetoothCallback);
然后在蓝牙中 class 构造函数看起来像:
constructor(bluetoothDevice: any, callingClass: any, callbackfunction: any) {
this.bluetoothDevice = bluetoothDevice;
this.state = BluetoothGattState.Disconnected;
this.callback = callingClass;
this.callbackfunction = callbackfunction;
}
回调是这样调用的:
this.callbackfunction.call(this.callback,this.connectionStr);
以及 litelement 内部的回调:
bluetoothCallback(constr:string)
{
this.connectedStr = constr;
}
属性 里面的 litelement:
@property() connectedStr: string = 'connect';
可以用,但是很丑!
有没有办法让 BTLE class 成为 litelement class 的朋友(就像在 C++ 中一样),这样我就可以直接在 BTLE class 中更改它(并且按钮会重新渲染)
或者在 javascript/litelement/webcomponents 中有更好的方法吗?
我应该为这样的事情使用 MobX 吗?
使用 LitElement 解决此问题的惯用方法是让 BTLE 对象在其状态发生变化时发出事件,并让其他关心其状态的对象(如自定义元素)监听这些事件。
在 Web 应用程序中执行此操作的最简单方法是使 BTLE class 扩展 EventTarget,这将使其成为 addEventListener
、dispatchEvent
等。方法。然后,您的自定义元素将调用 addEventListener
以开始侦听,而不是将回调函数传递给 BTLE 构造函数。当 BTLE 对象的状态改变时,它不会调用 this.callbackFunction(...)
,而是调用 this.dispatchEvent(new Event('state-change'))
(例如)。
为此,您的自定义元素需要定义自定义 getter 和 setter,以便它知道其 bluetoothGatt
属性 何时更改,因为它需要在新的 BTLE 上调用 addEventListener
。这是最复杂的部分,因此我强烈建议阅读 LitElement 文档中的 "Configure property accessors" 部分。
在下面的代码片段中,您可以看到一个实际示例:
const { LitElement, html } = litElement;
const BluetoothGattState = { Disconnected: 0, Connected: 1 };
// A simple app to test our custom element
class MyApp extends LitElement {
render() {
// Pass the BTLE object to `<bt-indicator>` as a property
return html`
<bt-indicator .bluetoothGatt=${new BTLE()}></bt-indicator>
`;
}
}
customElements.define('my-app', MyApp);
// Our <bt-indicator> custom element
class BtIndicator extends LitElement {
static get properties() {
return {
bluetoothGatt: { type: Object },
btState: { type: Number },
};
}
constructor() {
super();
this._bluetoothGatt = null;
this._handleBtGattStateChange = this._handleBtGattStateChange.bind(this);
}
render() {
return html`Bluetooth status: ${
this.btState === BluetoothGattState.Connected ? '✅' : ''
}`;
}
// A custom setter that calls addEventListener whenever the bluetoothGatt
// property changes
set bluetoothGatt(obj) {
const oldObj = this._bluetoothGatt;
if (oldObj) {
// Remove event listener from old BTLE
oldObj.removeEventListener('state-change', this._handleBtGattStateChange);
}
if (obj) {
this._bluetoothGatt = obj;
this.btState = obj.state;
// Add event listener to new BTLE
obj.addEventListener('state-change', this._handleBtGattStateChange);
} else {
this._bluetoothGatt = null;
}
// Tell LitElement the property changed so it can re-render
this.requestUpdate('bluetoothGatt', oldObj);
}
get bluetoothGatt() {
return this._bluetoothGatt;
}
_handleBtGattStateChange(evt) {
// update this.btState when the BTLE's stage changes
this.btState = evt.target.state;
}
}
customElements.define('bt-indicator', BtIndicator);
// BTLE as a simple EventTarget -- connects/disconnects every 1000ms and
// dispatches 'state-change'
class BTLE extends EventTarget {
constructor() {
super();
this.setState(BluetoothGattState.Disconnected);
setInterval(() => {
this.setState(this.state === BluetoothGattState.Disconnected ? BluetoothGattState.Connected : BluetoothGattState.Disconnected);
}, 1000);
}
setState(val) {
this.state = val;
this.dispatchEvent(new Event('state-change'));
}
}
<script src="https://bundle.run/lit-element@2.2.1"></script>
<my-app><my-app>
我目前正在学习如何使用 lit-elements,而且我也是网络开发的新手。我正在尝试制作一个蓝牙自定义元素,它根据蓝牙设备是否连接来更改按钮文本和颜色。
在我的 litelement 中,我创建了另一个名为 BTLE 的 class,所有蓝牙都在其中处理。 但是我不知道如何将 litelement 属性 传递给这个 BTLE class。 当 BTLE class 注意到连接或断开连接时,我希望我的按钮重新呈现。 如果我通过 constuctor 通过 BTLE class 传递 属性 并更改 属性 按钮不会重新呈现。如果我更改 litelement class 中的 属性 它会重新呈现。
我在我的 litelement class 中创建了一个回调函数作为解决方法。所以蓝牙 class 是这样创建的:
this.bluetoothGatt = new BTLEclass(this.bluetoothDevice, this, this.bluetoothCallback);
然后在蓝牙中 class 构造函数看起来像:
constructor(bluetoothDevice: any, callingClass: any, callbackfunction: any) {
this.bluetoothDevice = bluetoothDevice;
this.state = BluetoothGattState.Disconnected;
this.callback = callingClass;
this.callbackfunction = callbackfunction;
}
回调是这样调用的:
this.callbackfunction.call(this.callback,this.connectionStr);
以及 litelement 内部的回调:
bluetoothCallback(constr:string)
{
this.connectedStr = constr;
}
属性 里面的 litelement:
@property() connectedStr: string = 'connect';
可以用,但是很丑! 有没有办法让 BTLE class 成为 litelement class 的朋友(就像在 C++ 中一样),这样我就可以直接在 BTLE class 中更改它(并且按钮会重新渲染)
或者在 javascript/litelement/webcomponents 中有更好的方法吗? 我应该为这样的事情使用 MobX 吗?
使用 LitElement 解决此问题的惯用方法是让 BTLE 对象在其状态发生变化时发出事件,并让其他关心其状态的对象(如自定义元素)监听这些事件。
在 Web 应用程序中执行此操作的最简单方法是使 BTLE class 扩展 EventTarget,这将使其成为 addEventListener
、dispatchEvent
等。方法。然后,您的自定义元素将调用 addEventListener
以开始侦听,而不是将回调函数传递给 BTLE 构造函数。当 BTLE 对象的状态改变时,它不会调用 this.callbackFunction(...)
,而是调用 this.dispatchEvent(new Event('state-change'))
(例如)。
为此,您的自定义元素需要定义自定义 getter 和 setter,以便它知道其 bluetoothGatt
属性 何时更改,因为它需要在新的 BTLE 上调用 addEventListener
。这是最复杂的部分,因此我强烈建议阅读 LitElement 文档中的 "Configure property accessors" 部分。
在下面的代码片段中,您可以看到一个实际示例:
const { LitElement, html } = litElement;
const BluetoothGattState = { Disconnected: 0, Connected: 1 };
// A simple app to test our custom element
class MyApp extends LitElement {
render() {
// Pass the BTLE object to `<bt-indicator>` as a property
return html`
<bt-indicator .bluetoothGatt=${new BTLE()}></bt-indicator>
`;
}
}
customElements.define('my-app', MyApp);
// Our <bt-indicator> custom element
class BtIndicator extends LitElement {
static get properties() {
return {
bluetoothGatt: { type: Object },
btState: { type: Number },
};
}
constructor() {
super();
this._bluetoothGatt = null;
this._handleBtGattStateChange = this._handleBtGattStateChange.bind(this);
}
render() {
return html`Bluetooth status: ${
this.btState === BluetoothGattState.Connected ? '✅' : ''
}`;
}
// A custom setter that calls addEventListener whenever the bluetoothGatt
// property changes
set bluetoothGatt(obj) {
const oldObj = this._bluetoothGatt;
if (oldObj) {
// Remove event listener from old BTLE
oldObj.removeEventListener('state-change', this._handleBtGattStateChange);
}
if (obj) {
this._bluetoothGatt = obj;
this.btState = obj.state;
// Add event listener to new BTLE
obj.addEventListener('state-change', this._handleBtGattStateChange);
} else {
this._bluetoothGatt = null;
}
// Tell LitElement the property changed so it can re-render
this.requestUpdate('bluetoothGatt', oldObj);
}
get bluetoothGatt() {
return this._bluetoothGatt;
}
_handleBtGattStateChange(evt) {
// update this.btState when the BTLE's stage changes
this.btState = evt.target.state;
}
}
customElements.define('bt-indicator', BtIndicator);
// BTLE as a simple EventTarget -- connects/disconnects every 1000ms and
// dispatches 'state-change'
class BTLE extends EventTarget {
constructor() {
super();
this.setState(BluetoothGattState.Disconnected);
setInterval(() => {
this.setState(this.state === BluetoothGattState.Disconnected ? BluetoothGattState.Connected : BluetoothGattState.Disconnected);
}, 1000);
}
setState(val) {
this.state = val;
this.dispatchEvent(new Event('state-change'));
}
}
<script src="https://bundle.run/lit-element@2.2.1"></script>
<my-app><my-app>