amp-bind
Description
사용자 작업 또는 데이터 변경에 따라 데이터 결합 및 JS와 같은 단순한 식을 통해 요소의 변경을 허용합니다.
Required Scripts
<script async custom-element="amp-bind" src="https://cdn.ampproject.org/v0/amp-bind-0.1.js"></script>
데이터 결합 및 식과 함께 맞춤형 상호작용을 추가합니다.
필수 스크립트 | <script async custom-element="amp-bind" src="https://cdn.ampproject.org/v0/amp-bind-0.1.js"></script> |
예 | |
가이드 | 대화형 AMP 페이지 만들기 |
개요
amp-bind
구성요소를 사용하면 데이터 결합 및 JS와 유사한 식을 통해 AMP 페이지에 맞춤형 스테이트풀(stateful) 상호작용을 추가할 수 있습니다.
간단한 예
이 예에서는 버튼을 누르면 <p>
요소의 텍스트가 'Hello World'에서 '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
는 페이지 로드 시 식을 평가하지 않습니다. 즉, 시각적 요소에 기본 상태를 제공해야 하며 초기 렌더링에 amp-bind
를 사용하지 않아야 합니다. 기본 원리
amp-bind
에는 세 가지 주요 구성요소가 있습니다.
- 상태: 문서 범위의 변경 가능한 JSON 상태. 위의 예에서, 버튼을 누르기 전에는 상태가 비어 있습니다. 버튼을 누른 후의 상태는
{foo: 'amp-bind'}
입니다. - 식: 상태 를 참조할 수 있는 자바스크립트 같은 식입니다. 위의 예에는 단일 식인
'Hello ' + foo
가 있는데, 여기에서는 문자열 리터럴'Hello '
와 상태 변수foo
를 연결합니다. 하나의 식에 사용할 수 있는 피연산자는 100개로 제한됩니다. - 결합: 요소의 속성을 식 에 연결하는
[property]
양식의 특수한 속성입니다. 위의 예에는 단일 결합인[text]
가 있는데, 이것은 식의 값이 변경될 때마다<p>
요소의 텍스트를 업데이트합니다.
amp-bind는 AMP 페이지에서 속도, 보안 및 성능을 보장하기 위해 특별한 주의를 기울입니다.
약간 더 복잡한 예
<!-- 복잡한 중첩 JSON 데이터를 <amp-state> 요소에 저장하세요. -->
<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 + '.'">이것은 개입니다.</p>
<!-- [class]를 사용하여 CSS 클래스를 추가 또는 제거할 수도 있습니다. -->
<p class="greenBackground" [class]="myAnimals[currentAnimal].style">
각 동물의 배경색이 다릅니다.
</p>
<!-- 또는 [src] 결합으로 이미지의 src를 변경하세요. -->
<amp-img width="300" height="200" src="/img/dog.jpg" [src]="myAnimals[currentAnimal].imageUrl">
</amp-img>
<button on="tap:AMP.setState({currentAnimal: 'cat')">'Cat'으로 설정</button>
버튼을 누르면:
- 상태 는
'cat'
으로 정의된currentAnimal
로 업데이트됩니다. -
currentAnimal
에 의존하는 식 이 평가됩니다.'This is a ' + currentAnimal + '.'
=>'This is a cat.'
myAnimals[currentAnimal].style
=>'redBackground'
myAnimals[currentAnimal].imageUrl
=>/img/cat.jpg
-
변경된 식에 의존하는 결합 이 업데이트됩니다.
- 첫 번째
<p>
요소의 텍스트에는 "This is a cat."이 표시됩니다. - 두 번째
<p>
요소의class
속성은 "redBackground"가 됩니다. amp-img
요소는 고양이의 이미지를 보여줍니다.
- 첫 번째
세부정보
상태
amp-bind
를 사용하는 각 AMP 문서에는 문서 범위의 변경 가능한 JSON 데이터 또는 상태 가 있습니다.
amp-state
로 상태 초기화
amp-bind
의 상태는 amp-state
구성요소로 초기화할 수 있습니다.
<amp-state id="myState">
<script type="application/json">
{
"foo": "bar"
}
</script>
</amp-state>
식은 도트 구문을 통해 상태 변수를 참조할 수 있습니다. 이 예에서 myState.foo
는 "bar"
로 평가됩니다.
<amp-state>
요소의 하위 JSON은 최대 크기가 100KB입니다.<amp-state>
요소는 하위 JSON 스크립트 대신 CORS URL을 지정할 수도 있습니다. 자세한 내용은 부록을 참조하세요.
상태 새로 고침
refresh
작업은 이 구성요소에서 지원되며 상태의 내용을 새로 고치는 데 사용할 수 있습니다.
<amp-state id="amp-state" ...></amp-state>
<!-- 버튼을 클릭하면 amp-state의 json에 대한 새로고침 및 다시 가져오기가 수행됩니다. -->
<button on="tap:amp-state.refresh"></button>
AMP.setState()
로 상태 업데이트
AMP.setState()
작업은 개체 리터럴을 상태로 병합합니다. 예를 들어, 아래의 버튼을 누르면 AMP.setState()
는 개체 리터럴을 상태와 심층 병합합니다.
<!-- 자바스크립트와 마찬가지로 개체 리터럴
값에서 기존 변수를 참조할 수 있습니다. -->
<button on="tap:AMP.setState({foo: 'bar', baz: myAmpState.someVariable})"></button>
일반적으로 중첩된 개체는 최대 깊이 10까지 병합됩니다. amp-state
에 의해 추가된 변수를 포함하여 모든 변수를 재정의할 수 있습니다.
특정 이벤트에 의해 트리거되면 AMP.setState()
는 event
속성에 대한 이벤트 관련 데이터에 액세스할 수 있습니다.
<!-- 이 <input> 요소의 "change" 이벤트는 "event.value"를
통해 참조할 수 있는 "value" 변수를 포함합니다. -->
<input type="range" on="change:AMP.setState({myRangeValue: event.value})">
```
# `AMP.pushState()`로 기록 수정 <a name="modifying-history-with-amppushstate"></a>
브라우저 기록 스택에 새 항목을 푸시한다는 점을 제외하면 [`AMP.pushState()`](../../../documentation/guides-and-tutorials/learn/amp-actions-and-events.md#target-amp) 작업은 `AMP.setState()`와 유사합니다. 이 기록 항목을 표시하면(예: 뒤로 이동) `AMP.pushState()`에 의해 설정된 변수의 이전 값이 복원됩니다.
예:
```html
<button on="tap:AMP.pushState({foo: '123'})">Set 'foo' to 123</button>
- 버튼을 누르면 변수
foo
가 123으로 설정되고 새로운 기록 항목이 푸시됩니다. - 뒤로 이동하면
foo
가 이전 값인 'bar'로 복원됩니다(AMP.setState({foo: 'bar'} 호출과 동일)
.
식
식은 자바스크립트와 비슷하지만 몇 가지 중요한 차이점이 있습니다.
자바스크립트와의 차이점
- 식은 포함 문서의 상태에만 액세스할 수 있습니다.
- 식은
window
또는document
와 같은 전역에 액세스하지 않습니다. - 화이트리스트에 있는 함수 및 연산자만 사용할 수 있습니다.
- 맞춤형 함수, 클래스 및 루프는 일반적으로 허용되지 않습니다. 화살표 함수는 매개변수로서 허용됩니다(예:
Array.prototype.map
). - 정의되지 않은 변수 및 범위를 벗어난 배열-색인은
undefined
대신null
을 반환하거나 오류를 일으킵니다. - 성능을 위해 현재 단일 식의 피연산자는 50개로 제한됩니다. 이 개수가 사용 사례로 불충분한 경우 Google에 문의하세요.
식 문법과 구현의 전체 내용은 bind-expr-impl.jison 및 bind-expression.js에서 찾아볼 수 있습니다.
예
다음은 모두 유효한 식입니다.
1 + '1' // 11
1 + (+'1') // 2
!0 // true
null || 'default' // 'default'
화이트리스트에 있는 함수
개체 유형 | 함수 | 예 |
---|---|---|
Array 1 | concat filter includes indexOf join lastIndexOf map reduce slice some sort (제자리 아님)splice (제자리 아님) | // [1, 2, 3] 반환. [3, 2, 1].sort() // [1, 3, 5] 반환. [1, 2, 3].map((x, i) => x + i) // 6 반환. [1, 2, 3].reduce((x, y) => x + y) |
Number | toExponential toFixed toPrecision toString | // 3 반환. (3.14).toFixed() // '3.14' 반환. (3.14).toString() |
String | charAt charCodeAt concat indexOf lastIndexOf slice split substr substring toLowerCase toUpperCase | // 'abcdef' 반환. abc'.concat('def') |
Math 2 | abs ceil floor max min random round sign | // 1 반환. abs(-1) |
Object 2 | keys values | // ['a', 'b'] 반환. keys({a: 1, b: 2}) // [1, 2] 반환. values({a: 1, b: 2} |
Global 2 | encodeURI encodeURIComponent | // 'Hello%20world' 반환. encodeURIComponent('Hello world') |
1단일 매개변수 화살표 함수에는 괄호를 사용할 수 없습니다. 예를 들어 (x) => x + 1
대신 x => x + 1
을 사용하세요. 또한 sort()
및 splice()
는 제자리에서 연산되는 대신 수정된 사본을 반환합니다.
2상태 함수에는 네임스페이스가 없습니다. 예를 들어 Math.abs(-1)
대신 abs(-1)
을 사용하세요.
amp-bind-macro
로 매크로 정의
amp-bind-macro
를 정의하면 amp-bind
식의 부분들을 재사용할 수 있습니다. amp-bind-macro
요소를 사용하면 0개 이상의 인수를 사용하고 현재 상태를 참조하는 식을 정의할 수 있습니다. 문서의 어디서나 id
속성 값을 참조하여 매크로를 함수처럼 호출할 수 있습니다.
<amp-bind-macro id="circleArea" arguments="radius" expression="3.14 * radius * radius"></amp-bind-macro>
<div>
원의 면적은 <span [text]="circleArea(myCircle.radius)">0</span>입니다.
</div>
매크로는 또한 먼저 정의된 다른 매크로를 호출할 수 있습니다. 그러나 자신을 재귀적으로 호출할 수는 없습니다.
결합
결합 은 요소의 속성을 식에 연결하는 [property]
양식의 특수한 속성입니다. data-amp-bind-property
양식의 XML 호환 구문을 대안으로 사용할 수도 있습니다.
상태 가 변경되면 식이 재평가되고, 결합된 요소의 속성이 새로운 식의 결과로 업데이트됩니다.
amp-bind
는 네 가지 유형의 요소 상태에서 데이터 결합을 지원합니다.
유형 | 속성 | 세부정보 |
---|---|---|
Node.textContent | [text] | 대부분의 텍스트 요소에서 지원됩니다. |
CSS 클래스 | [class] | 식 결과는 공백으로 구분된 문자열이어야 합니다. |
hidden 속성 | [hidden] | 부울 식이어야 합니다. |
AMP 요소의 크기 | [width] [height] | AMP 요소의 너비 및/또는 높이를 변경합니다. |
요소별 속성 | 다양함 |
결합에 대한 참고 사항:
- 보안상의 이유로
innerHTML
에 대한 결합은 허용되지 않습니다. - 모든 속성 결합은 안전하지 않은 값(예:
javascript:
)에 대해 보안 확인이 수행됩니다. - 부울 식 결과는 부울 속성을 전환합니다. 예:
<amp-video [controls]="expr"...>
.expr
이true
로 평가되면<amp-video>
요소는controls
속성을 갖게 됩니다.expr
이false
로 평가되면controls
속성이 제거됩니다. - 속성 이름의 대괄호
[
및]
는 XML(예: XHTML, JSX)을 작성하거나 DOM API를 통해 속성을 작성할 때 문제가 될 수 있습니다. 이 경우[x]="foo"
대신 대체 구문data-amp-bind-x="foo"
를 사용하세요.
요소별 속성
다음 구성요소 및 속성에 대한 결합만 허용됩니다.
구성요소 | 속성 | 동작 |
---|---|---|
<amp-brightcove> | [data-account] [data-embed] [data-player] [data-player-id] [data-playlist-id] [data-video-id] | 표시된 Brightcove 동영상을 변경합니다. |
<amp-carousel type=slides> | [slide] * | 현재 표시된 슬라이드 색인을 변경합니다. 예를 참조하세요. |
<amp-date-picker> | [min] [max] | 선택 가능한 가장 빠른 날짜를 설정합니다. 선택 가능한 가장 최근 날짜를 설정합니다. |
<amp-google-document-embed> | [src] [title] | 업데이트된 URL에 문서를 표시합니다. 문서의 제목을 변경합니다. |
<amp-iframe> | [src] | iframe의 소스 URL을 변경합니다. |
<amp-img> | [alt] [attribution] [src] [srcset] | [src] 에 결합할 때 캐시에서 결합이 작동하도록 하려면 [srcset] 에도 결합해야 합니다.해당하는 amp-img 속성을 참조하세요. |
<amp-lightbox> | [open] * | 라이트박스의 표시를 전환합니다. 팁: 라이트박스가 닫힐 때 변수를 업데이트하려면 on="lightboxClose: AMP.setState(...)" 를 사용하세요. |
<amp-list> | [src] | 식이 문자열이면 문자열 URL에서 JSON을 가져와서 렌더링합니다. 식이 개체 또는 배열이면 식 데이터를 렌더링합니다. |
<amp-selector> | [selected] *[disabled] | 현재 선택한 하위 요소(option 속성 값으로 식별된)를 변경합니다. 다중 선택을 위해 쉼표로 구분된 값 목록을 지원합니다. 예를 참조하세요. |
<amp-state> | [src] | JSON을 새 URL에서 가져와서 기존 상태에 병합합니다. 다음 업데이트는 사이클을 방지하기 위해 <amp-state> 요소를 무시합니다. |
<amp-video> | [alt] [attribution] [controls] [loop] [poster] [preload] [src] | 해당하는 amp-video 속성을 참조하세요. |
<amp-youtube> | [data-videoid] | 표시된 YouTube 동영상을 변경합니다. |
<a> | [href] | 링크를 변경합니다. |
<button> | [disabled] [type] [value] | 해당하는 button 속성을 참조하세요. |
<details> | [open] | 해당하는 details 속성을 참조하세요. |
<fieldset> | [disabled] | fieldset를 사용하거나 사용하지 않도록 설정합니다. |
<image> | [xlink:href] | 해당하는 image 속성을 참조하세요. |
<input> | [accept] [accessKey] [autocomplete] [checked] [disabled] [height] [inputmode] [max] [maxlength] [min] [minlength] [multiple] [pattern] [placeholder] [readonly] [required] [selectiondirection] [size] [spellcheck] [step] [type] [value] [width] | 해당하는 input 속성을 참조하세요. |
<option> | [disabled] [label] [selected] [value] | 해당하는 option 속성을 참조하세요. |
<optgroup> | [disabled] [label] | 해당하는 optgroup 속성을 참조하세요. |
<select> | [autofocus] [disabled] [multiple] [required] [size] | 해당하는 select 속성을 참조하세요. |
<source> | [src] [type] | 해당하는 source 속성을 참조하세요. |
<track> | [label] [src] [srclang] | 해당하는 track 속성을 참조하세요. |
<textarea> | [autocomplete] [autofocus] [cols] [disabled] [maxlength] [minlength] [placeholder] [readonly] [required] [rows] [selectiondirection] [selectionend] [selectionstart] [spellcheck] [wrap] | 해당하는 textarea 속성을 참조하세요. |
*결합할 수 없는 대상이 없는 결합 가능한 속성을 나타냅니다.
디버깅
개발 중 경고 및 오류를 강조 표시하고 특수 디버깅 기능에 액세스하려면 개발 모드(URL에 #development=1
포함)에서 테스트합니다.
경고
개발 모드에서, 결합된 속성의 기본값이 해당하는 식의 초기 결과와 일치하지 않으면 amp-bind
는 경고를 표시합니다. 이는 다른 상태 변수의 변경에 따른 의도하지 않은 변형의 발생을 방지하는 데 도움이 될 수 있습니다. 예:
<!-- 요소의 기본 클래스 값('def')이 [class] ('abc')의 식 결과와 일치하지 않으므로 개발 모드에서 경고가 발생합니다. -->
<p class="def" [class]="'abc'"></p>
개발 모드에서, 정의되지 않은 변수 또는 속성을 역참조할 경우에도 amp-bind
는 경고를 표시합니다. 이것 또한 null
식 결과에 따른 의도하지 않은 변형의 발생을 방지하는 데 도움이 될 수 있습니다. 예:
<amp-state id="myAmpState">
<script type="application/json">
{ "foo": 123 }
</script>
</amp-state></p>
<!-- amp-state#myAmpState에 `bar` 변수가 없으므로 개발 모드에서 경고가 발생합니다. -->
<p [text]="myAmpState.bar">일부 자리표시자 텍스트.</p>
오류
amp-bind
로 작업할 때 발생할 수 있는 몇 가지 유형의 런타임 오류가 있습니다.
유형 | 메시지 | 제안 |
---|---|---|
잘못된 결합 | <P>의 [someBogusAttribute]에 대한 결합은 허용되지 않습니다. | 화이트리스트에 있는 결합만 사용합니다. |
구문 오류 | ...에 식 컴파일 오류 | 식에 오타가 있는지 확인합니다. |
화이트리스트에 없는 기능 | 경고는 지원되는 기능이 아닙니다. | 화이트리스트에 있는 기능만 사용합니다. |
검사를 거친 결과 | 'javascript:alert(1)'은 [href]에 대한 유효한 결과가 아닙니다. | AMP 유효성 검사 도구에서 실패할 식 또는 금지된 URL 프로토콜을 사용하지 않습니다. |
CSP 위반 | 다음과 같은 콘텐츠 보안 정책 지침을 위반했기 때문에 'blob:...'에서 작업자 생성이 거부되었습니다... | default-src blob: 을 원본의 콘텐츠 보안 정책에 추가합니다. 성능 보장을 위해 amp-bind 는 값비싼 작업을 전담 웹 작업자에게 위임합니다. |
디버깅 상태
현재 상태를 콘솔에 인쇄하려면 AMP.printState()
를 사용합니다.
부록
<amp-state>
사양
amp-state
에는 하위 <script>
요소 또는 원격 JSON 엔드포인트에 대한 CORS URL을 포함하는 src
속성을 포함할 수 있지만, 둘을 모두 포함할 수는 없습니다.
<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>
XHR 배치
AMP는 여러 JSON 엔드포인트에 대해 XMLHttpRequest(XHR)를 배치 처리합니다. 즉, AMP 페이지에서 여러 소비자(예: 여러 amp-state
요소)에 대해 데이터 소스로 단일 JSON 데이터 요청을 사용할 수 있습니다. 예를 들어 amp-state
요소가 엔드포인트에 대해 XHR을 만드는 경우 XHR이 실행 중인 동안에는 동일한 엔드포인트에 대한 모든 후속 XHR이 트리거되지 않으며 대신 첫 번째 XHR에서 결과가 반환됩니다.
속성
src | 이 amp-state 를 업데이트할 JSON을 반환하는 원격 엔드포인트의 URL. CORS HTTP 서비스여야 합니다. src 속성은 모든 표준 URL 변수 대체를 허용합니다. 자세한 정보는 대체 가이드를 참조하세요. 엔드포인트는 AMP의 CORS 요청 사양에 지정된 요구사항을 구현해야 합니다.
|
credentials(선택사항) | Fetch API에 지정된 대로 credentials 옵션을 정의합니다.
include 의 값을 전달하세요. 이 값이 설정된 경우 응답에서는 AMP CORS 보안 지침을 따라야 합니다. |
AMP.setState()
를 이용한 심층 병합
AMP.setState()
가 호출되면 amp-bind
는 제공된 개체 리터럴을 현재 상태와 심층 병합합니다. 개체 리터럴의 모든 변수는 재귀적으로 병합되는 중첩된 개체를 제외하고 상태에 직접 기록됩니다. 상태의 프리미티브와 배열을 개체 리터럴에 있는 동일한 이름의 변수가 항상 덮어씁니다.
다음 예를 참조하세요.
{
<!-- 상태는 비어 있음 -->
}
<button on="tap:AMP.setState({employee: {name: 'John Smith', age: 47, vehicle: 'Car'}})"...></button>
<button on="tap:AMP.setState({employee: {age: 64}})"...></button>
첫 번째 버튼을 누르면 상태가 다음과 같이 변경됩니다.
{
employee: {
name: 'John Smith',
age: 47,
vehicle: 'Car',
}
}
두 번째 버튼을 누르면 amp-bind
는 개체 리터럴 인수 {employee: {age: 64}}
를 기존 상태에 병합합니다.
{
employee: {
name: 'John Smith',
age: 64,
vehicle: 'Car',
}
}
employee.age
는 업데이트되었지만 employee.name
및 employee.vehicle
키는 변경되지 않았습니다.
순환 참조가 포함된 개체 리터럴과 함께 AMP.setState()
를 호출하면 amp-bind
에서 오류가 발생합니다.
변수 제거
AMP.setState()
에서 값을 null
로 설정하여 기존 상태 변수를 제거합니다. 이전 예제의 상태에서 시작하여 다음을 누릅니다.
<button on="tap:AMP.setState({employee: {vehicle: null}})"...></button>
상태가 다음으로 변경됩니다.
{
employee: {
name: 'John Smith',
age: 48,
}
}
마찬가지로:
<button on="tap:AMP.setState({employee: null})"...></button>
상태가 다음으로 변경됩니다.
{
<!-- 상태는 비어 있음 -->
}
식 문법
amp-bind
식에 대한 BNF와 유사한 문법:
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
이 문서를 수십 번 읽었음에도 여전히 궁금한 점이 남아 있나요? 다른 개발자들도 같은 심정일지 모릅니다. Stack Overflow에서 소통해 보세요.
Stack Overflow로 이동 버그나 누락된 기능을 발견하셨나요?AMP 프로젝트는 여러분의 참여와 기여를 적극 환영합니다! 오픈 소스 커뮤니티를 통해 지속적으로 활동해 주셔도 좋지만 관심 있는 주제에 한 번만 기여하셔도 큰 도움이 됩니다.
GitHub로 이동하기