zoukankan      html  css  js  c++  java
  • LitElement(二)模板编写基本语法

    原文:https://lit-element.polymer-project.org/guide/templates

    1、定义一个渲染模板

    1.1 基本规则

    要用LitElement 组件定义一个模板,必须为你的模板类写一个render方法:

    import { LitElement, html } from 'lit-element';
    
    class MyElement extends LitElement {
      render() {
        return html`<p>template content</p>`;
      }
    }

    这里 html`...` 中 html 是引用的父类函数,用模板字符串包裹原始的HTML标签

    组件的 render 方法可以返回 lit-html 可以渲染的任何内容。通常,它返回单个 TemplateResult 对象(与 html 标记函数返回的类型相同)。

    完整的例子

    import { LitElement, html } from 'lit-element';
    
    class MyElement extends LitElement {
    
      // Implement `render` to define a template for your element.
      render(){
        /**
         * Return a lit-html `TemplateResult`.
         *
         * To create a `TemplateResult`, tag a JavaScript template literal
         * with the `html` helper function.
         */
        return html`
          <div>
            <p>A paragraph</p>
          </div>
        `;
      }
    }
    customElements.define('my-element', MyElement);

    1.2 动态更改模板内容

    我们可以通过捕获加载消息作为属性,并根据事件设置属性来改变模板:update-properties.js

    import { LitElement, html } from 'lit-element';
    
    /**
     * Use this pattern instead.
     */
    class UpdateProperties extends LitElement {
      static get properties(){
        return {
          message: String
        };
      }
      constructor() {
        super();
        this.message = 'Loading';
        this.addEventListener('stuff-loaded', (e) => { this.message = e.detail } );
        this.loadStuff();
      }
      render() {
        return html`
          <p>${this.message}</p>
        `;
      }
      loadStuff() {
        setInterval(() => {
          let loaded = new CustomEvent('stuff-loaded', {
            detail: 'Loading complete.'
          });
          this.dispatchEvent(loaded);
        }, 3000);
      }
    }
    
    customElements.define('update-properties', UpdateProperties);

    该例子中为模板元素绑定了一个加载事件,事件函数模拟3秒后改变元素属性值,从而动态改变模板。这是动态改变模板的方法。

    注意:每一个模板类都必须引用  import { html, LitElement } from 'lit-element'; 就算套用了其他模板也是一样

    2、在模板中使用属性、循环和条件判断

    2.1 属性

    static get properties() {
      return { myProp: String };
    }
    ...
    render() {
      return html`<p>${this.myProp}</p>`;
    }

    通过静态的 get properties() 函数指定属性的类型, 构造函数 constructor() 初始化属性的初始值

    2.2 循环

    html`<ul>
      ${this.myArray.map(i => html`<li>${i}</li>`)}
    </ul>`;

    ES6数组的map方法,为每一个数组元素执行括号中的操作

    2.3 三目运算符

    html`
      ${this.myBool?
        html`<p>Render some HTML if myBool is true</p>`:
        html`<p>Render some other HTML if myBool is false</p>`}
    `;

    完整的例子

    import { LitElement, html } from 'lit-element';
    
    class MyElement extends LitElement {
      static get properties() {
        return {
          myString: { type: String },
          myArray: { type: Array },
          myBool: { type: Boolean }
        };
      }
      constructor() {
        super();
        this.myString = 'Hello World';
        this.myArray = ['an','array','of','test','data'];
        this.myBool = true;
      }
      render() {
        return html`
          <p>${this.myString}</p>
          <ul>
            ${this.myArray.map(i => html`<li>${i}</li>`)}
          </ul>
          ${this.myBool?
            html`<p>Render some HTML if myBool is true</p>`:
            html`<p>Render some other HTML if myBool is false</p>`}
        `;
      }
    }
    
    customElements.define('my-element', MyElement);

    一个包含了 get properties(), constructor(), render() 方法的模板

    3、给模板元素绑定属性值

    您可以插入JavaScript表达式作为HTML文本内容,基本属性,布尔属性,元素属性和事件处理器的占位符。

    • Text content: <p>${...}</p>
    • Attribute: <p id="${...}"></p>
    • Boolean attribute: ?disabled="${...}"
    • Property: .value="${...}"
    • Event handler: @event="${...}"

    3.1 绑定到正文

    html`<div>${this.prop1}</div>`

    3.2 绑定到基本属性

    html`<div id="${this.prop2}"></div>`

    3.3 绑定到布尔类型属性

    html`<input type="text" ?disabled="${this.prop3}">`

    3.4 绑定到元素属性

    html`<input type="checkbox" .value="${this.prop4}"/>`

    3.5 绑定到事件处理程序

    html`<button @click="${this.clickHandler}">pie?</button>`

    完整的例子

    import { LitElement, html } from 'lit-element';
    
    class MyElement extends LitElement {
      static get properties() {
        return {
          prop1: String,
          prop2: String,
          prop3: Boolean,
          prop4: String
        };
      }
      constructor() {
        super();
        this.prop1 = 'text binding';
        this.prop2 = 'mydiv';
        this.prop3 = true;
        this.prop4 = 'pie';
      }
      render() {
        return html`
          <!-- text binding -->
          <div>${this.prop1}</div>
    
          <!-- attribute binding -->
          <div id="${this.prop2}">attribute binding</div>
    
          <!-- boolean attribute binding -->
          <div>
            boolean attribute binding
            <input type="text" ?disabled="${this.prop3}"/>
          </div>
    
          <!-- property binding -->
          <div>
            property binding
            <input type="text" .value="${this.prop4}"/>
          </div>
    
          <!-- event handler binding -->
          <div>event handler binding
            <button @click="${this.clickHandler}">click</button>
          </div>
        `;
      }
      clickHandler(e) {
        console.log(e.target);
      }
    }
    
    customElements.define('my-element', MyElement);

    4、使用slot占位符给模板元素渲染子节点

    4.1 slot标签

    要实现如下形式的渲染,必须通过slot占位符标签实现

    <my-element>
      <p>A child</p>
    </my-element>

    默认情况下,如果元素具有阴影树,则其子元素根本不会渲染。

    要渲染子节点,您的模板需要包含一个或多个<slot>元素,这些元素充当子节点的占位符。

    例如定义如下形式的模板

    render(){
      return html`
        <div>
          <slot></slot>
        </div>
      `;
    }

    就可以在 <slot> 标签的位置渲染子节点

    <my-element>
      <p>Render me</p>
    </my-element>

    这些子项不会在DOM树中移动,但会像它们是<slot>的子项一样呈现。

    任意多个子节点可以填充到一个slot

    <my-element>
      <p>Render me</p>
      <p>Me too</p>
      <p>Me three</p>
    </my-element>

    4.2 使用命名的slot

    要将子节点分配给特定的 slot ,请确保该子节点的 slot 属性与该 slot name 属性匹配:

    render(){
      return html`
        <div>
          <slot name="one"></slot>
        </div>
      `;
    }
    <my-element>
      <p slot="one">Include me in slot "one".</p>
    </my-element>

    命名 slot 仅接受具有匹配 slot 属性的子节点。

    例如:

    import { LitElement, html } from 'lit-element';
    
    class MyElement extends LitElement {
      render(){
        return html`
          <div>
            <slot name="one"></slot>
            <slot name="two"></slot>
          </div>
        `;
      }
    }
    customElements.define('my-element', MyElement);

    one对one,two对two,没有名字的不会被渲染

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
      <script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-bundle.js"></script>
      
      <script type="module" src="./my-element.js"></script>
      <title>lit-element code sample</title>
    </head>
    <body>
        <!-- Assign child to a specific slot -->
    
        <my-element>
          <p slot="two">Include me in slot "two".</p>
        </my-element>
    
        <!-- 
          Named slots only accept children with a matching `slot` attribute. 
          
          Children with a `slot` attribute can only go into a slot with a matching name. 
        -->
    
        <my-element>
          <p slot="one">Include me in slot "one".</p>
          <p slot="nope">This one will not render at all.</p>
          <p>No default slot, so this one won't render either.</p>
        </my-element>
    </body>
    </html>

    5、多个模板组合成页面

    您可以从其他LitElement模板组成新的LitElement模板。在以下示例中,我们通过导入其他元素并在模板中使用它们来组成新的<my-page>模板:

    my-article.js

    import { LitElement, html } from 'lit-element';
    
    class MyArticle extends LitElement {
        render() {
            return html`
            <article>article</article>
            `;
        }
    }
    customElements.define('my-article', MyArticle);

    my-header.js

    import { html, LitElement } from 'lit-element';
    
    class MyHeader extends LitElement {
        render() {
            return html`
            ${this.headerTemplate}
          `;
        }
        get headerTemplate() {
            return html`<header>header</header>`;
        }
    }
    customElements.define('my-header', MyHeader);

    my-footer.js

    import { LitElement, html } from 'lit-element';
    
    class MyFooter extends LitElement {
        render() {
            return html`
            <footer>footer</footer>
            `;
        }
    }
    customElements.define('my-footer', MyFooter);

    用以上三个子模版元素组成页面元素my-page.js

    import { LitElement, html } from 'lit-element';
    
    import './my-header.js';
    import './my-article.js';
    import './my-footer.js';
    
    class MyPage extends LitElement {
        render() {
            return html`
            <my-header></my-header>
            <my-article></my-article>
            <my-footer></my-footer>
        `;
        }
    }
    customElements.define('my-page', MyPage);

    然后配一个 模板元素整合文件,例如 mian.js

    import './my-page.js';

    在页面 my-page.html中引用这个文件

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>lit-element code sample</title>
        <script src="main.js"></script>
    </head>
    
    <body>
        <my-page></my-page>
        <script src="webcomponents-loader.js"></script>
    </body>
    
    </html>

    此时可能有 index.html, my-page.html两个页面, index.js, main.js两个脚本文件,需要同时打包输出,修改rollup,config.js文件,以数组形式输出多个js文件

    import resolve from 'rollup-plugin-node-resolve';
    import babel from 'rollup-plugin-babel';
    
    export default [{
        input: ['src/index.js'],
        output: {
            file: 'build/index.js',
        format: 'es',
            sourcemap: true
        },
        plugins: [
        resolve(),
        babel()
      ],
    },{
        input: ['src/main.js'],
          output: {
              file: 'build/main.js',
          format: 'es',
              sourcemap: true
          },
          plugins: [
          resolve(),
          babel()
        ]
    }];

    修改package.json中的html打包命令

    "scripts": {
        "copyindex": "cp src/*.html build",
        "copywc": "cp -r node_modules/@webcomponents/webcomponentsjs/bundles build && cp node_modules/@webcomponents/webcomponentsjs/webcomponents-loader.js build",
        "build": "rm -rf build && mkdir build && npm run copyindex && npm run copywc && rollup -c",
        "start": "serve build"
      },

    就可以在build下生成两个html文件及其对应的js文件了,其他同理可得

    6、 lit-html

     lit-html作为LitElement的核心,可以使用很多它的其他功能

    npm i lit-element@^2.0.0
    npm i lit-html@^1.0.0

    例如:

    import { LitElement, html } from 'lit-element';
    import { until } from 'lit-html/directives/until.js';
    
    const content = fetch('./content.txt').then(r => r.text());
    
    html`${until(content, html`<span>Loading...</span>`)}`

    读取一个文件内容作为渲染内容

    其他详见文档:https://lit-html.polymer-project.org/guide/template-reference#built-in-directives

  • 相关阅读:
    编程语言 编译型语言与解释型语言及汇编语言
    Alpha冲刺2
    事后诸葛亮
    Alpha阶段项目复审
    PostgreSQL的表膨胀与Vacuum和Vacuum Full
    PostgreSQL查看表膨胀(对所有表进行膨胀率排序)
    python中from __future__ import division/print_function的用法
    【IT企业笔试集】2013年阿里巴巴实习生招聘笔试题目及解答
    【WPF编程】一个未完成的12306本地客户端的源代码
    【深入理解计算机系统第二版】3.55习题
  • 原文地址:https://www.cnblogs.com/jixiaohua/p/11973954.html
Copyright © 2011-2022 走看看