- Ringkasan
- Contoh sederhana
- Detail
- Status
- Menginisialisasi status dengan amp-state
- Me-refresh status
- Mengubah status dengan AMP.setState()
- Mengubah histori dengan AMP.pushState()
- Ekspresi
- Perbedaan dengan JavaScript
- Contoh
- Fungsi yang diizinkan
- Menentukan makro dengan amp-bind-macro
- Binding
- Atribut khusus elemen
- Debugging
- Peringatan
- Error
- Men-debug Status
- Lampiran
- Spesifikasi <amp-state>
- Pengelompokan XHR
- Atribut
- Penggabungan mendalam dengan AMP.setState()
- Menghapus variabel
- Tata bahasa ekspresi
amp-bind
Description
Allows elements to mutate in response to user actions or data changes via data binding and simple JS-like expressions.
Required Scripts
<script async custom-element="amp-bind" src="https://cdn.ampproject.org/v0/amp-bind-0.1.js"></script>
Contoh
Menambahkan interaktivitas kustom dengan data binding dan ekspresi.
Skrip yang Diperlukan | <script async custom-element="amp-bind" src="https://cdn.ampproject.org/v0/amp-bind-0.1.js"></script> |
Contoh | |
Tutorial | Membuat halaman AMP yang interaktif |
Ringkasan
Komponen amp-bind
memungkinkan Anda untuk menambahkan interaktivitas stateful kustom ke halaman AMP melalui data binding dan ekspresi yang mirip JS.
Contoh sederhana
Pada contoh berikut, menge-tap tombol akan mengubah teks elemen <p>
dari "Hello World" menjadi "Hello amp-bind".
<p [text]="'Hello ' + foo">Hello World</p>
<button on="tap:AMP.setState({foo: 'amp-bind'})">Say "Hello amp-bind"</button>
amp-bind
tidak mengevaluasi ekspresi saat halaman dimuat. Ini berarti elemen visual harus diberi status default dan tidak mengandalkan amp-bind
untuk render awal. Bagaimana cara kerjanya?
amp-bind
memiliki tiga komponen utama:
- Status: Status JSON lingkup dokumen yang dapat berubah. Pada contoh di atas, status masih kosong sebelum tombol di-tap. Setelah tombol di-tap, statusnya menjadi
{foo: 'amp-bind'}
. - Ekspresi: Merupakan ekspresi mirip JavaScript yang dapat merujuk ke state. Contoh di atas memiliki ekspresi tunggal,
'Hello ' + foo
, yang menggabungkan literal string'Hello '
dan variabel statusfoo
. Ada batas 100 operand yang dapat digunakan dalam sebuah ekspresi. - Binding: Merupakan atribut khusus dari bentuk
[properti]
yang menautkan properti elemen ke sebuah expression. Contoh di atas memiliki binding tunggal,[text]
, yang akan mengubah<p>
teks elemen setiap kali nilai ekspresi berubah.
amp-bind
memerlukan penanganan khusus untuk memastikan kecepatan, keamanan, dan performa di halaman AMP.
Contoh yang sedikit lebih rumit
<!-- Store complex nested JSON data in <amp-state> elements. -->
<amp-state id="myAnimals">
<script type="application/json">
{
"dog": {
"imageUrl": "/img/dog.jpg",
"style": "greenBackground"
},
"cat": {
"imageUrl": "/img/cat.jpg",
"style": "redBackground"
}
}
</script>
</amp-state>
<p [text]="'This is a ' + currentAnimal + '.'">This is a dog.</p>
<!-- CSS classes can also be added or removed with [class]. -->
<p class="greenBackground" [class]="myAnimals[currentAnimal].style">
Each animal has a different background color.
</p>
<!-- Or change an image's src with the [src] binding. -->
<amp-img width="300" height="200" src="/img/dog.jpg" [src]="myAnimals[currentAnimal].imageUrl">
</amp-img>
<p><button on="tap:AMP.setState({currentAnimal: 'cat'})">Set to Cat</button>
Ketika tombol ditekan:
- Status diubah dengan
currentAnimal
yang ditetapkan ke'cat'
. -
Ekspresi yang bergantung pada
currentAnimal
dievaluasi:'This is a ' + currentAnimal + '.'
=>'This is a cat.'
myAnimals[currentAnimal].style
=>'redBackground'
myAnimals[currentAnimal].imageUrl
=>/img/cat.jpg
-
Binding yang bergantung pada ekspresi yang telah diubah akan diubah:
- Teks elemen
<p>
pertama akan berbunyi "This is a cat.". - Atribut
class
elemen<p>
kedua akan menjadi "redBackground". - Elemen
amp-img
akan menampilkan gambar seekor kucing.
- Teks elemen
Detail
Status
Setiap dokumen AMP yang menggunakan amp-bind
memiliki data JSON lingkup dokumen yang dapat diubah, atau status.
Menginisialisasi status dengan amp-state
Status amp-bind
dapat diinisialisasi dengan komponen amp-state
:
<amp-state id="myState">
<script type="application/json">
{
"foo": "bar"
}
</script>
</amp-state>
Ekspresi dapat merujuk variabel status melalui sintaks titik. Dalam contoh ini, myState.foo
akan mengevaluasi "bar"
.
- JSON turunan elemen
<amp-state>
memiliki ukuran maksimal 100 KB. - Elemen
<amp-state>
juga dapat menentukan URL CORS, bukan skrip JSON turunan. Lihat Apendiks untuk mengetahui detailnya.
Me-refresh status
Tindakan refresh
didukung oleh komponen ini dan dapat digunakan untuk me-refresh konten status.
<amp-state id="amp-state" ...></amp-state>
<!-- Clicking the button will refresh and refetch the json in amp-state. -->
<button on="tap:amp-state.refresh"></button>
Mengubah status dengan AMP.setState()
Tindakan AMP.setState()
menggabungkan literal objek ke dalam status. Misalnya, saat tombol di bawah ditekan, AMP.setState()
akan menggabungkan secara mendalam literal objek dengan status.
<!-- Like JavaScript, you can reference existing
variables in the values of the object literal. -->
<button on="tap:AMP.setState({foo: 'bar', baz: myAmpState.someVariable})"></button>
Secara umum, objek bertingkat akan digabungkan hingga kedalaman maksimal 10. Semua variabel, termasuk yang diperkenalkan oleh amp-state
, dapat diganti.
Jika dipicu oleh peristiwa tertentu, AMP.setState()
juga dapat mengakses data terkait peristiwa di properti event
.
<!-- The "change" event of this <input> element contains
a "value" variable that can be referenced via "event.value". -->
<input type="range" on="change:AMP.setState({myRangeValue: event.value})">
Mengubah histori dengan AMP.pushState()
Tindakan AMP.pushState()
mirip dengan AMP.setState()
kecuali tindakan ini juga mendorong entri baru ke tumpukan histori browser. Memunculkan entri histori ini (misalnya dengan menavigasi mundur) akan memulihkan nilai variabel sebelumnya yang ditetapkan oleh AMP.pushState()
.
Misalnya:
<button on="tap:AMP.pushState({foo: '123'})">Set 'foo' to 123</button>
- Menge-tap tombol tersebut akan menetapkan variabel
foo
ke 123 dan mengirimkan entri histori baru. - Menavigasi mundur akan memulihkan
foo
ke nilai sebelumnya, "bar" (setara dengan memanggilAMP.setState({foo: 'bar'})
.
Ekspresi
Ekspresi mirip dengan JavaScript dengan beberapa perbedaan penting.
Perbedaan dengan JavaScript
- Ekspresi hanya dapat mengakses status dokumen penampungnya.
- Ekspresi tidak memiliki akses ke elemen global seperti
window
ataudocument
. - Hanya operator dan fungsi yang diizinkan yang dapat digunakan.
- Fungsi, class, dan loop kustom secara umum tidak diizinkan. Fungsi panah diizinkan sebagai parameter, misalnya
Array.prototype.map
. - Indeks array melebihi batas dan variabel yang tidak ditentukan akan menampilkan
null
, bukanundefined
atau memunculkan error. - Ekspresi tunggal saat ini dibatasi 50 operand untuk menjaga performa. Harap hubungi kami jika alokasi ini tidak memadai untuk kasus penggunaan Anda.
Implementasi dan tata bahasa lengkap ekspresi dapat dilihat di bind-expr-impl.jison dan bind-expression.js.
Contoh
Berikut adalah semua ekspresi yang valid:
1 + '1' // 11
1 + (+'1') // 2
!0 // true
null || 'default' // 'default'
Fungsi yang diizinkan
Jenis objek | Fungsi | Contoh |
---|---|---|
Array 1 | concat filter includes indexOf join lastIndexOf map reduce slice some sort (not-in-place)splice (not-in-place) | // Returns [1, 2, 3]. [3, 2, 1].sort() // Returns [1, 3, 5]. [1, 2, 3].map((x, i) => x + i) // Returns 6. [1, 2, 3].reduce((x, y) => x + y) |
Number | toExponential toFixed toPrecision toString | // Returns 3. (3.14).toFixed() // Returns '3.14'. (3.14).toString() |
String | charAt charCodeAt concat indexOf lastIndexOf slice split substr substring toLowerCase toUpperCase | // Returns 'abcdef'. abc'.concat('def') |
Math 2 | abs ceil floor max min random round sign | // Returns 1. abs(-1) |
Object 2 | keys values | // Returns ['a', 'b']. keys({a: 1, b: 2}) // Returns [1, 2]. values({a: 1, b: 2} |
Global 2 | encodeURI encodeURIComponent | // Returns 'Hello%20world'. encodeURIComponent('Hello world') |
1Fungsi panah parameter tunggal tidak dapat menggunakan tanda kurung, misalnya gunakan x => x + 1
bukan (x) => x + 1
. Selain itu, sort()
dan splice()
akan menampilkan salinan termodifikasi, bukan mengoperasikan in-place.
2Fungsi statis tidak di-namespace, misalnya gunakan abs(-1)
, bukan Math.abs(-1)
.
Menentukan makro dengan amp-bind-macro
Fragmen ekspresi amp-bind
dapat digunakan kembali dengan menentukan amp-bind-macro
. Elemen amp-bind-macro
memungkinkan Anda menentukan ekspresi yang memerlukan nol atau lebih argumen dan merujuk ke status saat ini. Makro dapat dipanggil seperti fungsi dengan merujuk nilai atribut id
-nya dari mana saja dalam dokumen Anda.
<amp-bind-macro id="circleArea" arguments="radius" expression="3.14 * radius * radius"></amp-bind-macro>
<div>
The circle has an area of <span [text]="circleArea(myCircle.radius)">0</span>.
</div>
Makro juga dapat memanggil makro lain yang ditentukan sebelum makro itu sendiri. Makro tidak dapat memanggil dirinya sendiri secara berulang.
Binding
Binding adalah atribut khusus dari bentuk [property]
yang menautkan properti sebuah elemen ke sebuah ekspresi. Sintaks alternatif yang kompatibel dengan XML juga dapat digunakan dalam bentuk data-amp-bind-property
.
Ketika status berubah, ekspresi dievaluasi ulang dan properti elemen terikat akan diubah dengan hasil ekspresi baru.
amp-bind
mendukung data binding di empat jenis status elemen:
Jenis | Atribut | Detail |
---|---|---|
Node.textContent | [text] | Didukung pada sebagian besar elemen teks. |
Class CSS | [class] | Hasil ekspresi harus berupa string yang dipisahkan spasi. |
Atribut hidden | [hidden] | Harus berupa ekspresi boolean. |
Ukuran elemen AMP | [width] [height] | Mengubah lebar dan/atau tinggi elemen AMP. |
Atribut khusus elemen | Bervariasi |
Catatan tentang binding:
- Demi keamanan, binding ke
innerHTML
tidak diizinkan. - Semua binding atribut dibersihkan dari nilai yang tidak aman (misalnya
javascript:
). - Hasil ekspresi boolean mengalihkan atribut boolean. Misalnya:
<amp-video [controls]="expr"...>
. Saatexpr
dievaluasi ketrue
, elemen<amp-video>
memiliki atributcontrols
. Saatexpr
dievaluasi kefalse
, atributcontrols
akan dihapus. - Karakter tanda kurung
[
dan]
dalam nama atribut dapat menyulitkan saat menulis XML (misalnya XHTML, JSX) atau menulis atribut melalui DOM API. Dalam kasus ini, gunakan sintaks alternatifdata-amp-bind-x="foo"
, bukan[x]="foo"
.
Atribut khusus elemen
Hanya binding ke komponen dan atribut berikut yang diizinkan:
Komponen | Atribut | Perilaku |
---|---|---|
<amp-brightcove> | [data-account] [data-embed] [data-player] [data-player-id] [data-playlist-id] [data-video-id] | Mengubah video Brightcove yang ditampilkan. |
<amp-carousel type=slides> | [slide] * | Mengubah indeks slide yang sedang ditampilkan. Lihat contoh. |
<amp-date-picker> | [min] [max] | Menetapkan tanggal paling awal yang dapat dipilih Menetapkan tanggal paling akhir yang dapat dipilih |
<amp-google-document-embed> | [src] [title] | Menampilkan dokumen pada URL yang diubah. Mengubah judul dokumen. |
<amp-iframe> | [src] | Mengubah URL sumber iframe. |
<amp-img> | [alt] [attribution] [src] [srcset] | Saat melakukan binding ke [src] , pastikan Anda juga melakukannya ke [srcset] agar binding berfungsi pada cache.Lihat atribut amp-img yang terkait. |
<amp-lightbox> | [open] * | Mengaktifkan tampilan lightbox. Tips: Gunakan on="lightboxClose: AMP.setState(...)" untuk mengubah variabel ketika lightbox ditutup. |
<amp-list> | [src] | Jika ekspresi berupa string, mengambil dan merender JSON dari URL string. Jika ekspresi berupa objek atau array, merender data ekspresi. |
<amp-selector> | [selected] *[disabled] | Mengubah elemen turunan terpilih saat ini yang diidentifikasi oleh nilai atribut option -nya. Mendukung daftar dipisahkan koma yang memuat nilai untuk beberapa pilihan. Lihat contoh. |
<amp-state> | [src] | Mengambil JSON dari URL baru dan menggabungkannya ke dalam status yang ada. Perhatikan bahwa perubahan berikut akan mengabaikan elemen <amp-state> untuk mencegah siklus. |
<amp-video> | [alt] [attribution] [controls] [loop] [poster] [preload] [src] | Melihat atribut amp-video yang terkait. |
<amp-youtube> | [data-videoid] | Mengubah video YouTube yang ditampilkan. |
<a> | [href] | Mengubah link. |
<button> | [disabled] [type] [value] | Melihat atribut tombol yang terkait. |
<details> | [open] | Melihat atribut detail yang terkait. |
<fieldset> | [disabled] | Mengaktifkan atau menonaktifkan fieldset. |
<image> | [xlink:href] | Melihat atribut gambar yang terkait. |
<input> | [accept] [accessKey] [autocomplete] [checked] [disabled] [height] [inputmode] [max] [maxlength] [min] [minlength] [multiple] [pattern] [placeholder] [readonly] [required] [selectiondirection] [size] [spellcheck] [step] [type] [value] [width] | Melihat atribut input yang terkait. |
<option> | [disabled] [label] [selected] [value] | Melihat atribut opsi yang terkait. |
<optgroup> | [disabled] [label] | Melihat atribut optgroup yang terkait |
<select> | [autofocus] [disabled] [multiple] [required] [size] | Melihat atribut pilih yang terkait. |
<source> | [src] [type] | Melihat atribut sumber yang terkait. |
<track> | [label] [src] [srclang] | Melihat atribut track yang terkait. |
<textarea> | [autocomplete] [autofocus] [cols] [disabled] [maxlength] [minlength] [placeholder] [readonly] [required] [rows] [selectiondirection] [selectionend] [selectionstart] [spellcheck] [wrap] | Melihat atribut textarea yang terkait. |
*Menunjukkan atribut yang dapat diikat yang tidak memiliki pasangan yang tidak dapat diikat.
Debugging
Jalankan pengujian dalam mode pengembangan (dengan fragmen URL #development=1
) untuk menandai peringatan dan error selama pengembangan dan untuk mengakses fungsi debug khusus.
Peringatan
Dalam mode pengembangan, amp-bind
akan mengeluarkan peringatan saat nilai default atribut terikat tidak cocok dengan hasil awal ekspresi yang terkait. Hal ini dapat membantu mencegah mutasi tak terduga yang disebabkan oleh perubahan pada variabel status lainnya. Contoh:
<!-- The element's default class value ('def') doesn't match the expression result for [class] ('abc'),
so a warning will be issued in development mode. -->
<p class="def" [class]="abc"></p>
Dalam mode pengembangan, amp-bind
juga akan mengeluarkan peringatan saat menghilangkan referensi ke properti atau variabel yang tidak ditentukan. Hal ini juga dapat membantu mencegah mutasi tak terduga akibat hasil ekspresi null
. Contoh:
<amp-state id="myAmpState">
<script type="application/json">
{ "foo": 123 }
</script>
</amp-state></p>
<!-- The amp-state#myAmpState does not have a `bar` variable, so a warning
will be issued in development mode. -->
<p [text]="myAmpState.bar">Some placeholder text.</p>
Error
Ada beberapa jenis error runtime yang mungkin ditemui ketika bekerja dengan amp-bind
.
Jenis | Pesan | Saran |
---|---|---|
Binding tidak valid | Binding to [someBogusAttribute] on <P> is not allowed. | Gunakan hanya binding yang disetujui. |
Error sintaks | Expression compilation error in... | Verifikasi ekspresi dari kesalahan ketik. |
Fungsi tidak diizinkan | alert is not a supported function. | Gunakan hanya fungsi yang diizinkan. |
Hasil yang dibersihkan | "javascript:alert(1)" is not a valid result for [href]. | Hindari protokol URL atau ekspresi dilarang yang akan menggagalkan Validator AMP. |
Pelanggaran CSP | Refused to create a worker from 'blob:...' because it violates the following Content Security Policy directive... | Tambahkan default-src blob: ke Kebijakan Keamanan Konten asal. amp-bind mendelegasikan pekerjaan penting ke Pekerja Web khusus untuk memastikan performa yang baik. |
Men-debug Status
Gunakan AMP.printState()
untuk mencetak status saat ini ke konsol.
Lampiran
Spesifikasi <amp-state>
Elemen amp-state
dapat berisi elemen <script>
turunan ATAU atribut src
yang berisi URL CORS ke endpoint JSON jarak jauh, tetapi tidak keduanya.
<amp-state id="myLocalState">
<script type="application/json">
{
"foo": "bar"
}
</script>
</amp-state>
<amp-state id="myRemoteState" src="https://data.com/articles.json">
</amp-state>
Pengelompokan XHR
AMP mengelompokkan XMLHttpRequest (XHR) ke endpoint JSON, artinya, Anda dapat menggunakan satu permintaan data JSON sebagai sumber data untuk banyak konsumen (misalnya beberapa elemen <amp-list>
) di sebuah halaman AMP. Sebagai contoh, jika elemen amp-list
membuat XHR ke sebuah endpoint, sementara XHR sedang dalam periode tayang, semua XHR berikutnya ke endpoint yang sama tidak akan terpicu dan sebaliknya akan menampilkan hasil dari XHR pertama.
Atribut
src | URL endpoint jarak jauh yang akan menampilkan JSON yang akan mengubah amp-state . Harus berupa layanan HTTP CORS. Atribut src memungkinkan semua substitusi variabel URL standar. Lihat Panduan Substitusi untuk informasi selengkapnya. Endpoint harus mengimplementasikan persyaratan yang ditentukan dalam spesifikasi permintaan CORS di AMP.
|
credentials (opsional) | Menentukan opsi credentials seperti yang ditentukan oleh Fetch API.
include . Jika nilai ini ditetapkan, respons harus mengikuti panduan keamanan CORS AMP. |
Penggabungan mendalam dengan AMP.setState()
Ketika AMP.setState()
dipanggil, amp-bind
akan menggabungkan secara mendalam literal objek yang disediakan dengan status saat ini. Semua variabel dari literal objek akan ditulis ke status secara langsung kecuali untuk objek bertingkat, yang akan digabung secara berulang. Primitive dan array dalam status akan selalu ditimpa oleh variabel dengan nama yang sama dalam literal objek.
Perhatikan contoh berikut:
{
<!-- State is empty -->
}
<button on="tap:AMP.setState({employee: {name: 'John Smith', age: 47, vehicle: 'Car'}})"...></button>
<button on="tap:AMP.setState({employee: {age: 64}})"...></button>
Saat tombol pertama ditekan, status akan berubah menjadi:
{
employee: {
name: 'John Smith',
age: 47,
vehicle: 'Car',
}
}
Saat tombol kedua ditekan, amp-bind
secara berulang akan menggabungkan argumen literal objek, {employee: {age: 64}}
, ke dalam status yang ada.
{
employee: {
name: 'John Smith',
age: 64,
vehicle: 'Car',
}
}
employee.age
telah diubah, tetapi kunci employee.name
dan employee.vehicle
tidak berubah.
Perhatikan bahwa amp-bind
akan memunculkan error jika Anda memanggil AMP.setState()
dengan literal objek yang berisi referensi melingkar.
Menghapus variabel
Hapus variabel status yang ada dengan menetapkan nilainya ke null
di AMP.setState()
. Dimulai dengan status dari contoh sebelumnya, menekan:
<button on="tap:AMP.setState({employee: {vehicle: null}})"...></button>
akan mengubah status menjadi:
{
employee: {
name: 'John Smith',
age: 48,
}
}
Demikian juga menekan:
<button on="tap:AMP.setState({employee: null})"...></button>
akan mengubah status menjadi:
{
<!-- State is empty -->
}
Tata bahasa ekspresi
Tata bahasa mirip BNF untuk ekspresi amp-bind
:
expr:
operation
| invocation
| member_access
| '(' expr ')'
| variable
| literal
operation:
!' expr
| '-' expr
| '+' expr
| expr '+' expr
| expr '-' expr
| expr '*' expr
| expr '/' expr
| expr '%' expr
| expr '&&' expr
| expr '||' expr
| expr '<=' expr
| expr '<' expr
| expr '>=' expr
| expr '>' expr
| expr '!=' expr
| expr '==' expr
| expr '?' expr ':' expr
invocation:
expr '.' NAME args
args:
(' ')'
| '(' array ')'
;
member_access:
expr member
;
member:
.' NAME
| '[' expr ']'
variable:
NAME
;
literal:
STRING
| NUMBER
| TRUE
| FALSE
| NULL
| object_literal
| array_literal
array_literal:
[' ']'
| '[' array ']'
array:
expr
| array ',' expr
object_literal:
{' '}'
| '{' object '}'
object:
key_value
| object ',' key_value
key_value:
expr ':' expr
Anda telah membaca dokumen ini belasan kali, tetapi belum semua pertanyaan Anda terjawab? Mungkin orang lain merasakan hal yang sama. Berinteraksilah dengan mereka di Stack Overflow.
Kunjungi Stack Overflow Menemukan bug atau ada fitur yang kurang?Proyek AMP sangat menganjurkan partisipasi dan kontribusi Anda! Kami berharap Anda akan terus ambil bagian dalam komunitas sumber terbuka kami, tetapi kami juga menerima kontribusi satu kali untuk topik tertentu yang Anda minati.
Kunjungi GitHub