$30 off During Our Annual Pro Sale. View Details »

The State of Web Components

Shogo Sensui
September 24, 2017

The State of Web Components

2017年9月24日に開催された HTML5 Conference 2017 の「The State of Web Components」のセッション資料です。

Shogo Sensui

September 24, 2017
Tweet

More Decks by Shogo Sensui

Other Decks in Technology

Transcript

  1. )5.-$POGFSFODF

    4IPHP4FOTVJBLB!DI
    5IF4UBUFPG8FC$PNQPOFOUT

    View Slide

  2. !DI

    View Slide

  3. ‣ 4IPHP4FOTVJ
    ‣ ؎ٝة٦طحزדכDIדׅ
    ‣ $ZCFS"HFOU *OD
    ‣ 8FC*OJUJBUJWF$FOUFS
    ‣ 4PGUXBSF&OHJOFFS
    ‣ 8FC䪮遭Ⰻ菙ָ㥨ֹדׅ
    ‣ 044崞⹛׮׃גתׅ

    View Slide

  4. 馄鸞劤ָ⳿תׅ
    涪㡰✮㹀

    View Slide

  5. 8IZ8FC$PNQPOFOUT

    View Slide

  6. )5.-$44
    8FCꟚ涪罏

    View Slide

  7. 8FCחֶֽ׷鿇ㅷךꨇ׃ׁ
    ‣ )5.-ה$44חأ؝٦فָ㶷㖈׃זְ
    ‣ 铣׫鴥׿׌$44ך䕦갟眔㔲ָ鎘׶濼׸זְ
    ‣ せ⵸瑞꟦ָ遼瑱׃זְ״ֲծ䌢ח䠐陎ׅ׷䗳銲ָ֮׷
    ‣ ⡲׏׋鿇ㅷ׾ⱄⵃ欽׃חְֻ
    ‣ )5.-$44+BWB4DSJQU׾תה׭׷➬穈׫ָזְ
    ‣ תה׭׋鿇ㅷ׾ꂁ䋒ׅ׷ؒ؝ءأذيָזַ׏׋

    View Slide

  8. نةٝ׾⡲׷חכ˘
    GBODZCVUUPO

    View Slide


  9. fancy button

    button {
    background: #0086b3;
    color: white;
    padding: 1em;
    border-radius: 0.5em;
    border: none;
    }
    )5.-ה$44׾剅ֽל0,

    View Slide

  10. GBODZCVUUPO

    View Slide

  11. GBODZCVUUPO
    GBODZCVUUPO

    View Slide


  12. fancy button


    fancy button

    button {
    color: white;
    padding: 1em;
    border-radius: 0.5em;
    border: none;
    }
    button.a {
    background: #0086b3;
    }
    button.b {
    background: #008080;
    }

    View Slide

  13. GBODZCVUUPO
    GBODZCVUUPO

    View Slide

  14. GBODZCVUUPO
    GBODZCVUUPO
    GBODZCVUUPO

    View Slide

  15. GBODZCVUUPO
    GBODZCVUUPO
    GBODZCVUUPO
    PWBM
    TRVBSF

    View Slide

  16. fancy button


    fancy button


    fancy button


    oval


    border-radius: 0.5em;
    border: none;
    }
    button.a {
    background: #0086b3;
    }
    button.b {
    background: #008080;
    }
    button.oval {
    ...
    }

    View Slide

  17. GBODZCVUUPO
    GBODZCVUUPO
    GBODZCVUUPO
    PWBM
    TRVBSF

    View Slide


  18. fancy button


    fancy button


    fancy button

    oval
    square

    View Slide

  19. 4IBEPX%0. $VTUPN&MFNFOUT
    5FNQMBUFT )5.-*NQPSUT
    ˟׍׳׏ה⵸תד

    View Slide

  20. ˟䎃猧植㖈
    4IBEPX%0. $VTUPN&MFNFOUT
    5FNQMBUFT &4.PEVMFT

    View Slide

  21. 4IBEPX%0.

    View Slide

  22. 4IBEPX%0.הכ
    ‣ )5.-ծ$44ծ+BWB4DSJQUך䕦갟眔㔲׾ꣲ㹀ׅ׷
    ‣ مأزהז׷銲稆חTIBEPX3PPU׾欰װ׃ծ׉ך⚥ד饯ֿ׷ֿה׾4IBEPX
    %0.ⰻח殅׭׷
    ‣ 4IBEPX%0.㢩鿇ַ׵ך䕦갟׾ꣲ㹀ׅ׷
    ‣ TIBEPX3PPUפך،ؙإأ׾ꣲ㹀涸ח׃ծ䮶׷莸ְ׾䬐⥂ׅ׷
    ‣ TIBEPX3PPUפ،ؙإأדֹ׷PQFOٌ٦سהծ黪倖ׅ׷DMPTFEٌ٦سָ֮׷

    View Slide

  23. const button = document.querySelector('button');
    const shadowRoot = button.attachShadow({
    mode: 'open' // or 'close'
    });
    // readonly property
    console.log(button.shadowRoot);
    4IBEPX%0.ך欰װ׃倯

    View Slide

  24. GBODZCVUUPO
    ⢽ִלְֲֲֿنةٝ

    View Slide


  25. fancy button

    ֲֿ剅ֽ׋׵ءٝفٕ˘
    <br/>button {<br/>background: #0086b3;<br/>color: white;<br/>padding: 1em;<br/>border-radius: 0.5em;<br/>border: none;<br/>}ɹ<br/>

    View Slide


  26. #shadow-root
    fancy button

    <br/>button {<br/>background: #0086b3;<br/>color: white;<br/>padding: 1em;<br/>border-radius: 0.5em;<br/>border: none;<br/>}<br/>



    View Slide


  27. #shadow-root
    fancy button

    <br/>button {<br/>background: #0086b3;<br/>color: white;<br/>padding: 1em;<br/>border-radius: 0.5em;<br/>border: none;<br/>}ɹ<br/>



    View Slide


  28. #shadow-root
    fancy button

    <br/>button {<br/>background: #0086b3;<br/>color: white;<br/>padding: 1em;<br/>border-radius: 0.5em;<br/>border: none;<br/>}<br/>



    4DPQFE

    View Slide

  29. $VTUPN&MFNFOUT

    View Slide

  30. $VTUPN&MFNFOUTהכ
    ‣ 杝荈ך)5.-銲稆׾㹑鎉ׅ׷
    ‣ )5.-ד㹑鎉涸חⵃ欽דֹ׷
    ‣ %0."1*׾鸐ׄגㄏ⟀涸חⵃ欽דֹ׷
    ‣ ⟣䠐ך䮶׷莸ְ׾㹀纏ׅ׷
    ‣ 㹀纏ׁ׸׋ٓ؎ؿ؟؎ؙٕ׾ؿحؙׅ׷

    View Slide

  31. class FancyButton extends HTMLElement {
    constructor() { ... }
    connectedCallback() { ... }
    disconnectedCallback() { ... }
    attributeChangedCallback() { ... }
    adoptedCallback() { ... }
    }
    ؕأةي銲稆ٓ؎ؿ؟؎ؙٕ

    View Slide

  32. 䖞勻ך8FC鿇ㅷךⱄⵃ欽
    ‣ 鿇ㅷ׾圓䧭ׅ׷)5.-׾鎸鶢ׅ׷
    ‣ $44ח״׷أة؎ؚٔٝ׾黝欽ׅ׷
    ‣ $44ؿ؋؎ٕ׾ٗ٦سׅ׷ծTUZMF銲稆׾剅ֻծFUD
    ‣ +BWB4DSJQUח״׷䮶׷莸ְ׾黝欽ׅ׷
    ‣ +BWB4DSJQUؿ؋؎ٕ׾ٗ٦سׅ׷ծTDSJQU銲稆׾剅ֻծFUD

    View Slide

  33. GBODZCVUUPO
    نةٝ׾⢪ְ׋ְ˘

    View Slide

  34. .fancy {
    background: #0086b3;
    color: white;
    padding: 1em;
    border-radius: 0.5em;
    border: none;
    }
    CVUUPODTT

    View Slide

  35. CVUUPOKT
    document
    .querySelector('.fancy')
    .addEventListener('click', () => {
    //...
    });

    View Slide


  36. fancy button

    JOEFYIUNM

    View Slide


  37. ...

    fancy button

    ...

    穈׫さ׻ׇג⢪ֲ

    View Slide

  38. View Slide

  39. class FancyButton extends HTMLElement {
    connectedCallback() {
    this.innerHTML = `
    button { … }
    fancy button
    `;
    }
    }
    customElements
    .define('fancy-button', FancyButton);

    View Slide


  40. fancy button

    GBODZCVUUPO
    GBODZCVUUPO׾⢪ִ׷

    View Slide


  41. <br/>button {<br/>background: #0086b3;<br/>color: white;<br/>padding: 1em;<br/>border-radius: 0.5em;<br/>border: none;<br/>}<br/>

    fancy button


    /PUTDPQFE

    View Slide

  42. 4IBEPX%0.

    $VTUPN&MFNFOUT

    View Slide

  43. class FancyButton extends HTMLElement {
    connectedCallback() {
    this.innerHTML = `
    button { … }
    fancy button
    `;
    }
    }
    customElements
    .define('fancy-button', FancyButton);

    View Slide

  44. class FancyButton extends HTMLElement {
    connectedCallback() {
    this.shadowRoot.innerHTML = `
    button { … }

    `;
    }
    }
    customElements
    .define('fancy-button', FancyButton);

    View Slide


  45. <br/>button {<br/>background: #0086b3;<br/>color: white;<br/>padding: 1em;<br/>border-radius: 0.5em;<br/>border: none;<br/>}<br/>

    fancy button


    View Slide


  46. #shadow-root
    <br/>button {<br/>background: #0086b3;<br/>color: white;<br/>padding: 1em;<br/>border-radius: 0.5em;<br/>border: none;<br/>}<br/>



    fancy button

    4DPQFE

    View Slide

  47. 5FNQMBUFT

    View Slide

  48. 5FNQMBUFTהכ
    ‣ ꬊ崞䚍ז)5.-銲稆׾㹑鎉ׅ׷
    ‣ ذٝفٖ٦زה׃ג)5.-銲稆׾䪔ִ׷
    ‣ 䖞勻ךعحؙ涸ז،فٗ٦ث׾ׇ׆ח幥׬

    View Slide


  49. This is an image


    4FOEBSFRVFTU

    View Slide

  50. <br/><p>This is an image</p><br/><img src="foo.jpg" alt=""><br/>
    &WBMXJUIJOOFS)5.-

    View Slide


  51. This is an image


    *OFSU✨

    View Slide

  52. 4IBEPX%0.

    $VTUPN&MFNFOUT

    5FNQMBUFT

    View Slide

  53. class FancyButton extends HTMLElement {
    connectedCallback() {
    this.shadowRoot.innerHTML = `
    button { … }

    `;
    }
    }
    customElements
    .define('fancy-button', FancyButton);

    View Slide


  54. button { … }


    <br/>class FancyButton extends HTMLElement {<br/>// ...<br/>}<br/>customElements<br/>.define('fancy-button', FancyButton);<br/>

    View Slide

  55. rel="import"
    href="fancy-button.html">

    fancy button

    View Slide

  56. )5.-*NQPSUT…
    IUUQTHJUIVCDPNXDXFCDPNQPOFOUTJTTVFTJTTVFDPNNFOU

    View Slide

  57. )5.-.PEVMFT…
    IUUQTHJTUHJUIVCDPN5BLBZPTIJ,PDIJGEDFEGECCEBGFGF

    View Slide

  58. import fancy from './fancy.html' as HTMLTemplateElement;
    export class FancyButton extends HTMLElement {
    connectedCallback() {
    this.attachShadow({
    mode: 'open'
    }).appendChild(fancy.content.cloneNode(true));
    }
    }

    View Slide

  59. &4.PEVMFT

    View Slide

  60. &4.PEVMFTהכ
    ‣ &4.PEVMFTךـٓؐؠ㹋鄲
    ‣ TDSJQUUZQFˑNPEVMF˒ד+BWB4DSJQUؿ؋؎ٕ׾ٗ٦سׅ׷
    ‣ TDSJQUOPNPEVMFדꬊ㼎䘔橆㞮׾罋䣁ׅ׷
    ‣ &4.PEVMFTך/PEFKT㹋鄲
    ‣ NKT׾&4.PEVMFTך+BWB4DSJQUؿ؋؎ٕה׃גٗ٦سׅ׷

    View Slide

  61. export default class FancyButton {
    ...
    }
    GBODZCVUUPOKT

    View Slide

  62. import React from 'react';
    import ReactDOM from 'react-dom';
    import PropTypes from 'prop-types';
    import FancyButton from './fancy-button.js';
    JOEFYKT

    View Slide

  63. <br/>import FancyButton from './fancy-button.js';<br/>customElements<br/>.define('fancy-button', FancyButton);<br/>

    View Slide

  64. 4IBEPX%0.

    $VTUPN&MFNFOUT

    &4.PEVMFT

    View Slide

  65. class FancyButton extends HTMLElement {
    connectedCallback() {
    this.attachShadow({
    mode: 'open'
    }).innerHTML = `
    button { … }

    `;
    }
    }
    customElements
    .define('fancy-button', FancyButton);

    View Slide

  66. export default
    class FancyButton extends HTMLElement {
    connectedCallback() {
    this.attachShadow({
    mode: 'open'
    }).innerHTML = `
    button { … }

    `;
    }
    }

    View Slide


  67. fancy button

    <br/>import FancyButton from './fancy-button.js';<br/>customElements<br/>.define('fancy-button', FancyButton);<br/>

    View Slide

  68. 8FCחֶֽ׷鿇ㅷךꨇ׃ׁ
    ‣ )5.-ה$44חأ؝٦فָ㶷㖈׃זְ
    ‣ 铣׫鴥׿׌$44ך䕦갟眔㔲ָ鎘׶濼׸זְ
    ‣ せ⵸瑞꟦ָ遼瑱׃זְ״ֲծ䌢ח䠐陎ׅ׷䗳銲ָ֮׷
    ‣ ⡲׏׋鿇ㅷ׾ⱄⵃ欽׃חְֻ
    ‣ )5.-$44+BWB4DSJQU׾תה׭׷➬穈׫ָזְ
    ‣ תה׭׋鿇ㅷ׾ꂁ䋒ׅ׷ؒ؝ءأذيָזַ׏׋

    View Slide

  69. 4IBEPX%0.
    $VTUPN&MFNFOUT
    &4.PEVMFT
    OQNZBSO
    8FCחֶֽ׷鿇ㅷךꨇ׃ׁ
    ‣ )5.-ה$44חأ؝٦فָ㶷㖈׃זְ
    ‣ 铣׫鴥׿׌$44ך䕦갟眔㔲ָ鎘׶濼׸זְ
    ‣ せ⵸瑞꟦ָ遼瑱׃זְ״ֲծ䌢ח䠐陎ׅ׷䗳銲ָ֮׷
    ‣ ⡲׏׋鿇ㅷ׾ⱄⵃ欽׃חְֻ
    ‣ )5.-$44+BWB4DSJQU׾תה׭׷➬穈׫ָזְ
    ‣ תה׭׋鿇ㅷ׾ꂁ䋒ׅ׷ؒ؝ءأذيָזַ׏׋

    View Slide

  70. 1PMZNFS4VNNJU
    JO$PQFOIBHFO

    View Slide


  71. #PXFSJTEFQSFDBUFE

    View Slide

  72. 6TFOQNZBSO

    View Slide

  73. // fancy-button v1.0.0
    customElements
    .define('fancy-button', FancyButton);
    // fancy-button v1.1.0
    customElements
    .define('fancy-button', FancyButton);
    ZBSO׾⢪ֲץֹ椚歋


    ⣛㶷ٌآُ٦ٕ׾ؿٓحزזخٔ٦ד鍑寸דֹ׷✨

    View Slide

  74. ‣ #SPXTFS4VQQPSU
    ‣ "DDFTTJCJMJUZ
    ‣ -PBE1FSGPSNBODF
    ‣ 3FOEFS1FSGPSNBODF

    View Slide

  75. 8FC$PNQPOFOUTTBOECPY
    IUUQTDIHJUIVCJPXFCDPNQPOFOUTTBOECPY

    View Slide

  76. ‣ #SPXTFS4VQQPSU
    ‣ "DDFTTJCJMJUZ
    ‣ -PBE1FSGPSNBODF
    ‣ 3FOEFS1FSGPSNBODF

    View Slide




  77. $VTUPN&MFNFOUTW
    4IBEPX%0.W
    5FNQMBUFT
    &4.PEVMFT
    ✅ ✅
    ✅ ✅
    ✅ ✅
    ✅ ✅





    䎃猧ـٓؐؠ؟ه٦ز

    View Slide

  78. 8FC$PNQPOFOUT
    JT
    BWBJMBCMFOPX
    PO
    UIFNPCJMFXFC✨

    View Slide

  79. View Slide

  80. :PV5VCFJTCVJMU
    POUIFUPQPG1PMZNFS

    View Slide

  81. View Slide

  82. 6TFXFCDPNQPOFOUTKT
    ‣ $VTUPN&MFNFOUTWךهٔؿ؍ٕ
    ‣ 4IBEZ%0.4IBEPX%0.ך%0."1*هٔؿ؍ٕ
    ‣ 4IBEZ$444IBEPX%0.ךأة؎ٕꟼ鸬هٔؿ؍ٕ
    ‣ )5.-*NQPSUT

    View Slide

  83. 8IZ4IBEZ%0.
    ‣ %0.خٔ٦ך،ؙإ؟׾ⵖ䖴ׅ׷ךָꨇ׃ְ
    ‣ ぐ珏%0."1*װ/PEF-JTUךؒىُٖ٦زָꨇ׃ְ
    ‣ EPDVNFOUCPEZ瘝ך،ؙإ؟׾♳剅ֹדֹזְ
    ‣ ؝٦سꆀָ花㣐חז׷♳ծػؿؓ٦وٝأח׮䕦갟ׅ׷
    ‣ 4IBEZ%0."1*׾➜׃ג،ؙإأׇׁ׷
    ‣ 㸜㹀䚍׾⥂׍אאծػؿؓ٦وٝأ׾⳿ׅ

    View Slide

  84. View Slide

  85. 8FC$PNQPOFOUT
    JTBMTP
    BWBJMBCMFOPX
    PO
    UIFEFTLUPQXFC

    View Slide

  86. ‣ #SPXTFS4VQQPSU
    ‣ "DDFTTJCJMJUZ
    ‣ -PBE1FSGPSNBODF
    ‣ 3FOEFS1FSGPSNBODF

    View Slide

  87. "DDFTTJCJMJUZ
    ‣ 4IBEPX%0.ך)5.-׾،ؙإءـٕח
    ‣ 鸐䌢ך%0.ず圫חծإوٝذ؍ؙأ׾䠐陎ׅ׷
    ‣ )5.-׌ֽד♶⼧ⴓז㜥さכծ8"*"3*"ד؟ه٦زׅ׷
    ‣ 孡חז׷ךכأ؝٦فⰻפך،ؙإأ
    ‣ 4IBEPX%0.ָꪪ⳿ׁ׸גְ׷׌ֽ
    ‣ ،ؙإءؽٔذ؍ָ⡚ְ؝ٝه٦طٝز׾⢪ֲ㜥さכ˘

    View Slide


  88. #shadow-root
    fancy button

    <br/>button {<br/>background: #0086b3;<br/>color: white;<br/>padding: 1em;<br/>border-radius: 0.5em;<br/>border: none;<br/>}<br/>



    &YQPTFE

    View Slide


  89. #shadow-root
    fancy button

    <br/>div {<br/>background: #0086b3;<br/>color: white;<br/>padding: 1em;<br/>border-radius: 0.5em;<br/>border: none;<br/>}<br/>



    &YQPTFE

    View Slide

  90. ‣ #SPXTFS4VQQPSU
    ‣ "DDFTTJCJMJUZ
    ‣ -PBE1FSGPSNBODF
    ‣ 3FOEFS1FSGPSNBODF

    View Slide

  91. -PBE1FSGPSNBODF
    ‣ TDSJQUח״׷؝ٝه٦طٝزךٗ٦س
    ‣ ؙٔؒأز侧כ)551ד֮׸ל孡ח׃ֺׅזֻג葺ְ
    ‣ ؝ٝه٦طٝزך+BWB4DSJQUؿ؋؎ٕכNJOJGZׅ׷
    ‣ UZQFˑNPEVMF˒㾩䚍ח״׷EFGFSٗ٦س
    ‣ ؔفءّٝדBTZOD㾩䚍׾➰♷דֹ׷

    View Slide

  92. TDSJQUח״׷ぐ珏ٗ٦س
    IUUQTIUNMTQFDXIBUXHPSHNVMUJQBHFTDSJQUJOHIUNMUIFTDSJQUFMFNFOU

    View Slide

  93. ثُ٦صؚٝه؎ٝز
    ‣ ٔا٦أ׾㙵׭鴥׬ךַٍؗحءُׅ׷ךַ
    ‣ 㙵׭鴥׫כ剑׮傍ֻٖٝتׁؚٔٝ׸׉ֲ׌ָծⴱ劍ٗ٦سָ曯暨חז׷
    ‣ ׉׸״׶כ$BDIF$POUSPMقحتװ4FSWJDF8PSLFSזודٍؗحءُ׃׋ְ
    ‣ ⴱ劍ٗ٦س׾傍׭׋ְ
    ‣ MJOLSFMˑQSFMPBE˒ד"5'חꟼ׻׷ٔا٦أ׾ٗ٦س׃גֶֻ
    ‣ 如㔐鼂獳ח䗳銲זٔا٦أכMJOLSFMˑQSFGFUDI˒דٗ٦س׃גֶֻ

    View Slide

  94. ‣ #SPXTFS4VQQPSU
    ‣ "DDFTTJCJMJUZ
    ‣ -PBE1FSGPSNBODF
    ‣ 3FOEFS1FSGPSNBODF

    View Slide

  95. 3FOEFS1FSGPSNBODF
    ‣ -JHIU%0.ה4IBEPX%0.ך䊴
    ‣ 4IBEPX%0.׉ך׮ךךכـٓؐؠ㹋鄲ך剑黝⻉ח㨻י״ֲ
    ‣ ׋ע׿㣐䊴כזְ⦐➂ך✮䟝דׅ
    ‣ 7JSUVBM%0.ח״׷䊴ⴓ䲽歗ך⡭㖑
    ‣ ➙תד鸐׶3FBDUזוך7JFXٓ؎ـٓٔה穈׫さ׻ׇ׷
    ‣ 8FC$PNQPOFOUTⰻד䊴ⴓ䲽歗׾㹋倵ׅ׷

    View Slide

  96. import React from 'react';
    export default
    class Button extends React.Component {
    handleClick(e) {
    if (this.props.onClick) {
    this.props.onClick(e);
    }
    }
    render() {
    const handleClick = this.handleClick.bind(this);
    return (

    {this.props.children}

    );
    }
    }

    View Slide

  97. 1PMZNFS-BCTMJUIUNM
    ‣ 5BHHFE5FNQMBUF-JUFSBMדUFNQMBUF׾⢪ֲ➬穈׫
    ‣ IUNMAAדذٝفٖ٦ز׾⡲׶ծSFOEFS
    ד)5.-׾欰䧭ׅ׷
    ‣ SFOEFS
    ד床ׅ⹛涸ז鿇ⴓך׫׾䊴ⴓ䲽歗ׅ׷

    View Slide

  98. const helloTemplate = (name) => html`Hello ${name}!`;
    // renders Hello Steve! to the document body
    render(helloTemplate('Steve'), document.body);
    // updates to Hello Kevin!, but only updates the ${name} part
    render(helloTemplate('Kevin'), document.body);

    View Slide

  99. import { html, render } from './lit-html.js';
    export default class IconButton extends HTMLElement {
    connectedCallback() {
    this.attachShadow({
    mode: 'open'
    });
    render(this.template, this.shadowRoot);
    }
    get template() {
    return html`
    ...




    `;
    }
    };

    View Slide

  100. תה׭
    ‣ 8FC$PNQPOFOUTחꟼׅ׷ぐ珏➬圫ָ㸜㹀׃גֹ׋
    ‣ ـٓؐؠ㹋鄲׮滠㹋ח鹌׫ծ暴חٌغ؎ٕ8FCדכه
    ٔؿ؍ٕז׃ד⢪ִ׷
    ‣ ➙⢪׏גְ׷䪮遭أةحؙח׮《׶鴥׿דְֽ׷
    ‣ ـٓؐؠⰻ鿇Ⳣ椚ך剑黝⻉׮䖉׍אאծطحزٙ٦ؙ
    ꟼ鸬כ㛇劤ח屟׏׋ثُ٦صؚٝד0,

    View Slide

  101. :PVBSFSFBEZUPVTF
    8FC$PNQPOFOUT✨

    View Slide

  102. 5IBOLZPV
    !DI
    "DI

    View Slide