现在,借助 Apollo Elements,构建互联组件变得轻而易举。您只需提供一个 GraphQL 文档和一个用于处理模板的自定义元素类,即可开始使用。
import{ApolloQuery,html}from'@apollo-elements/lit-apollo';// A component that uses ApolloSubscription to update// when users go on or offline.import'./user-online-status.js';import'./loading-spinner.js';/**
* `<user-profile-page>` Shows a user's profile, as well as a list
* of their friends which display's each one's online status via a
* GraphQL subscription.
* @extends ApolloQuery
*/classUserProfilePageextendsApolloQuery{render(){const{loading,data}=this;return ((loading||!data)?html`<loading-spinner></loading-spinner>`!data.user?:html`<login-form></login-form>`:html`
<h1>Hello, ${data.user.name}</h1>
<profile-image src="${data.user.avatar}"></profile-image>
<h2>Who's Online?</h2>
<dl>${data.user.friends.map(({id,name})=>html`
<dt>${name}</dt>
<dd><user-online-status id="${id}"></user-online-status></dd>
`)}</dl>
`);}updated(){// get the currently logged-in user's id from the `@client` query.const{id}=this.id;// setting variables updates the query.if (id)this.variables={id};}}customElements.define('user-profile-page',UserProfilePage);
Apollo Elements 源于 [此处应填写项目名称] lit-apollo,但我并不满足于只支持一个组件类。版本 0 发布后进行了更名和品牌重塑,并支持lit-element[此处应填写组件名称] GluonElement、[此处应填写组件名称] 和 [此处应填写组件名称]。hybrids它还包含一些Polymer风格的双向绑定元素,因此您可以使用{{data}}语法在模板中公开 Apollo 状态。
但我们的目标是为开发者提供更多选择。如果以上选项都不符合您的需求,Apollo Elements 还提供了类混入(class mixin),让您可以快速上手任何类似原生组件的类,甚至如果您愿意,还可以使用传统的自定义类HTMLElement。
import{ApolloMutationMixin}from'@apollo-elements/mixins';importgqlfrom'graphql-tag';constmutation=gql`
mutation SendMessage($message: String!) {
sendMessage(message: $message) {
message
date
}
}
`;consttemplate=document.createElement('template');template.innerHTML=`
<style>
:host([error]) #input {
border: 1px solid red;
}
details {
display: none;
}
:host([error]) details {
display: block;
}
</style>
<label>Message<input id="input"/></label>
<details>
<summary>Error!</summary>
<span id="error"></span>
</details>
`;classChatInputextendsApolloMutationMixin(HTMLElement){getinput(){returnthis.shadowRoot&&this.shadowRoot.getElementById('input');}constructor(){super();this.mutation=mutation;this.onKeyup=this.onKeyup.bind(this);this.attachShadow({mode:'open'})this.shadowRoot.appendChild(template.content.cloneNode(true))this.input.addEventListener('keyup',this.onKeyup)}onKeyup({key,target:{value:message}}){if (key!=='Enter')return;this.variables={message};this.mutate();}// Override implementation of `onCompleted` if desired.// Alternatively, use a setter.onCompleted({message,date}){this.input.value='';}// Override implementation of `onError` if desired.// Alternatively, use a setter.onError(error){this.setAttribute('error',error);this.shadowRoot.getElementById('error').textContent=`Error when sending message: ${error}`;}}