vue 에서 발생 한 구덩이 의 변화 검출 문제(배열 관련)
예 1
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vue</title>
<script src="https://unpkg.com/[email protected]/dist/vue.js"></script>
<style>
li:hover {
cursor: pointer;
}
</style>
</head>
<body>
<div class="wrap">
<ul>
<li v-for="item,index in items" v-on:click="handle(index)">
<span>{{item.name}}</span>
<span>{{numbers[index]}}</span>
</li>
</ul>
</div>
<script>
var vm = new Vue({
el: ".wrap",
data: {
numbers: [],
items: [
{name: 'jjj'},
{name: 'kkk'},
{name: 'lll'},
]
},
methods: {
handle: function (index) {
// WHY: ,view , console
if (typeof(this.numbers[index]) === "undefined" ) {
this.numbers[index] = 1;
} else {
this.numbers[index]++;
}
}
}
});
</script>
</body>
</html>
이곳 의 실현 목적 은 매우 명확 하 다.나 는 li 를 클릭 할 때 존재 여 부 를 먼저 검 측 하고 싶다.당연히 존재 하지 않 기 때문에 값 을 1 로 설정 하고 다시 클릭 하면 숫자 를 누적 시킨다.그러나 문 제 는 클릭 한 후에 숫자 가 view 층 에서 업데이트 되 지 않 았 고 console 인쇄 를 통 해 데이터 가 확실히 업데이트 되 었 다 는 것 입 니 다.다만 view 층 에서 제때에 감지 되 지 않 았 습 니 다.저 는 vue 가 실 현 될 때 데이터 가 양 방향 으로 연결 되 었 으 니 model 층 이 변화 한 후에 왜 view 층 에서 업데이트 되 지 않 았 습 니까?
우선,나 는 이것 이 배열 의 문제 인지 아 닌 지 를 고려 했다.그래서 나 는 다음 과 같은 예 를 테스트 했다.
예 2
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vue</title>
<script src="https://unpkg.com/[email protected]/dist/vue.js"></script>
<style>
li:hover {
cursor: pointer;
}
</style>
</head>
<body>
<div class="wrap">
<ul>
<li v-for="item,index in items" v-on:click="handle(index)">
<span>{{item.name}}</span>
<span>{{numbers[index]}}</span>
</li>
</ul>
</div>
<script>
var vm = new Vue({
el: ".wrap",
data: {
numbers: [],
items: [
{name: 'jjj'},
{name: 'kkk'},
{name: 'lll'},
]
},
methods: {
handle: function (index) {
// , view
this.items[index].name += " success";
}
}
});
</script>
</body>
</html>
이때,내 가 다시 테스트 할 때,이곳 의 모델 층 에 변화 가 생 겼 을 때,view 층 은 제때에 효과적으로 업 데 이 트 될 수 있다 는 것 을 발견 하 였 다.배열 은 왜 안 되 지?
그래서 문서 의 하 찮 은 곳 에서 다음 과 같은 설명 을 찾 았 습 니 다.
그 중에서 가장 중요 한 말 은-대상 이 응답 식 이 라면 속성 이 생 성 된 후에 도 응답 식 이 고 보기 업 데 이 트 를 촉발 하 는 것 입 니 다.이 방법 은 Vue 가 속성 이 추 가 된 제한 을 감지 하지 못 하 는 것 을 피 하 는 데 사 용 됩 니 다.
그러면 Vue 에서 속성 이 추가 되 는 것 을 감지 할 수 없 는 상황 은 무엇 일 까요? 참고 링크 에 의 하면 우 리 는 문서 에서 좋 은 설명 을 보 았 다.심층 응답 식 원리
우선,우 리 는 Vue 가 데이터 의 양 방향 연결 을 어떻게 실현 하 는 지 알 아야 합 니 다!
일반 JavaScript 대상 을 Vue 인 스 턴 스 의 data 옵션 에 전달 합 니 다.Vue 는 이 대상 의 모든 속성 을 옮 겨 다 니 며 Object.defineProperty 를 사용 하여 이 속성 을 모두 getter/setter 로 변환 합 니 다.Object.defineProperty 는 ES5 만 지원 하고 shim 이 불가능 한 특성 입 니 다.이것 이 바로 Vue 가 IE8 과 더 낮은 버 전의 브 라 우 저 를 지원 하지 않 는 이유 입 니 다.
지식 보충:
접근 기 속성 은 데이터 값 을 포함 하지 않 습 니 다.getter 함수 와 setter 함 수 를 포함 합 니 다.접근 기 속성 을 읽 을 때 getter 함 수 를 호출 합 니 다.이 함 수 는 유효한 값 을 되 돌려 줍 니 다.기록 접근 기 속성 은 setter 함 수 를 호출 하고 새 값 을 입력 합 니 다.이 함 수 는 데 이 터 를 어떻게 처리 할 지 결정 합 니 다.
접근 기 속성 은 직접 정의 할 수 없습니다.Object.defineProperty()로 정의 해 야 합 니 다.
다음은 하나의 예 이다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vue</title>
</head>
<body>
<script>
var book={
_year:2004,
edition:1
};
Object.defineProperty(book,"year",{
get:function(){
return this._year;
},
set:function(newValue){
if(newValue>2004){
this._year=newValue;
this.edition+=newValue-2004;
}
}
});
console.log(book.year); // 2004 get
book.year=2005; // set
console.log(book.edition); // 2
</script>
</body>
</html>
이 예 는 접근 기 속성 을 잘 이해 할 수 있 을 것 이다.따라서 대상 아래 의 방문 기 속성 값 이 바 뀌 면(vue 는 속성 을 모두 방문 기 속성 으로 바 꿉 니 다.전에 언급 했 습 니 다)set 함 수 를 호출 합 니 다.이때 vue 는 이 set 함 수 를 통 해 변 화 를 추적 하고 관련 함 수 를 호출 하여 view 그림 의 업 데 이 트 를 실현 할 수 있 습 니 다.
모든 구성 요소 인 스 턴 스 는 해당 하 는 watcher 인 스 턴 스 대상 이 있 습 니 다.구성 요소 가 렌 더 링 하 는 과정 에서 속성 을 의존 으로 기록 한 다음 의존 항목 의 setter 가 호출 될 때 watcher 에 게 다시 계산 하 라 고 알려 주 고 관련 구성 요 소 를 업데이트 합 니 다.
즉,렌 더 링 과정 에서 대상 속성의 getter 함 수 를 호출 한 다음 에 getter 함 수 는 wather 대상 에 게 이 성명 을 의존 으로 알 리 고 의존 한 후에 대상 속성 이 변화 하면 setter 함 수 를 호출 하여 watcher 에 게 알 리 고 watcher 는 구성 요 소 를 다시 렌 더 링 하여 업 데 이 트 를 완성 합 니 다.
OK!원 리 를 알 게 된 이상 우 리 는 왜 이전 배열 의 문제 가 발생 했 는 지 더 알 수 있 을 것 이다!
변화 검출 문제
현대 자 바스 크 립 트 브 라 우 저의 제한 을 받 았 습 니 다.사실은 Object.observe()방법 이 지원 되 지 않 아서 Vue 에서 대상 의 추가 나 삭 제 를 감지 할 수 없습니다.그러나 Vue 는 인 스 턴 스 를 초기 화 할 때 속성 에 대해 setter/getter 전환 과정 을 실 행 했 기 때문에 속성 은 대상 에 있어 야 Vue 를 전환 시 킬 수 있 습 니 다.
그래서 앞의 예 에 대해 이해 할 수 없습니다.-배열 에서 index 는 모두 속성 이 라 고 볼 수 있 습 니 다.우리 가 속성 을 추가 하고 값 을 부여 할 때 Vue 는 대상 의 속성 추가 나 삭 제 를 감지 할 수 없 지만 추가 하거나 삭 제 했 기 때문에 우 리 는 console 을 통 해 변 화 를 볼 수 있 기 때문에 응답 식 을 할 수 없습니다.두 번 째 예 에서 우 리 는 기 존의 속성 을 바탕 으로 수정 한 것 이다.이런 속성 들 은 처음에 Vue 에 의 해 인 스 턴 스 를 초기 화 할 때 setter/getter 의 전환 과정 을 실 행 했 기 때문에 그들의 수정 은 효과 적 이 고 model 의 데 이 터 는 실시 간 으로 view 층 에서 해당 된다.
보충 지식:Object.observe()가 무엇 입 니까?
소개 하기 전에 이 방법 은 일부 브 라 우 저 에서 실 행 될 수 있 지만 사실은 이 방법 이 폐기 되 었 다 고 잔인하게 말 할 수 밖 에 없습니다!
개요:이 방법 은 대상 의 수정 을 비동기 적 으로 감시 하 는 데 사 용 됩 니 다.대상 의 속성 이 수정 되 었 을 때 방법의 리 셋 함 수 는 질서정연 한 수정 흐름 을 제공 합 니 다.그러나 이 인 터 페 이 스 는 각 브 라 우 저 에서 제거 되 었 습 니 다.일반적인proxy 개체을 사용 할 수 있 습 니 다.
방법:
Object.observe(obj, callback[, acceptList])
그 중에서 obj 는 감 시 된 대상 입 니 다.callback 은 리 셋 함수 입 니 다.그 중의 매개 변 수 는 changes 와 acceptList 를 포함 합 니 다.changes 하나의 배열 입 니 다.그 안에 포 함 된 모든 대상 은 수정 행 위 를 대표 합 니 다.모든 변경 행위 의 대상 은 다음 과 같 습 니 다:
var obj = {
foo: 0,
bar: 1
};
Object.observe(obj, function(changes) {
console.log(changes);
});
obj.baz = 2;
// [{name: 'baz', object: <obj>, type: 'add'}]
obj.foo = 'hello';
// [{name: 'foo', object: <obj>, type: 'update', oldValue: 0}]
delete obj.baz;
// [{name: 'baz', object: <obj>, type: 'delete', oldValue: 2}]
위 와 같이 chrome 도 지원 되 지 않 습 니 다.브 라 우 저의 호환성 은 다음 과 같 습 니 다.참고 문서:Object.ovserve()
추천 읽 기 글:Object.observe()데이터 귀속 혁명 폭발
해결 방법
Vue.set(object,key,value)방법 을 사용 하여 응답 속성 을 끼 워 넣 은 대상 에 추가 합 니 다.vm.$set 인 스 턴 스 방법 도 사용 할 수 있 습 니 다.전역 Vue.set 방법의 별명 이기 도 합 니 다.
예 3
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vue</title>
<script src="https://unpkg.com/[email protected]/dist/vue.js"></script>
<style>
li:hover {
cursor: pointer;
}
</style>
</head>
<body>
<div class="wrap">
<ul>
<li v-for="item,index in items" v-on:click="handle(index)">
<span>{{item.name}}</span>
<span>{{numbers[index]}}</span>
</li>
</ul>
</div>
<script>
var vm = new Vue({
el: ".wrap",
data: {
numbers: [],
items: [
{name: 'jjj'},
{name: 'kkk'},
{name: 'lll'},
]
},
methods: {
handle: function (index) {
// WHY: ,view , console
if (typeof(this.numbers[index]) === "undefined" ) {
this.$set(this.numbers, index, 1);
} else {
this.$set(this.numbers, index, ++this.numbers[index]);
}
}
}
});
</script>
</body>
</html>
이렇게 하면 우 리 는 최종 목적 을 실현 할 수 있다!제2 부분
위의 부분 은 data 아래 에 있 는 배열 을 말 합 니 다.store 에 있 는 배열 이 라면 보통 이렇게 할 수 있 습 니 다.
[ADD_ONE] (state, index) {
if ( typeof state.numbers[index] == "undefined") {
Vue.set(state.numbers, index, 1)
} else {
Vue.set(state.numbers, index, ++state.numbers[index])
}
}
Vue.set()방식 으로 바 꾸 고 늘 리 는 것 이다.메모:index 의 증가 와 감 소 를 확인 하기 위해 Vue.set()방식 을 사용 합 니 다.
줄 이 는 방식 은 다음 과 같다.
[REMOVE_ONE] (state, index) {
Vue.set(state.numbers, index, --state.numbers[index]);
}
제4 부분store 의 actions 에서 stroe 의 배열 을 채 워 야 한다 면 방법 은 다음 과 같 습 니 다.
state 내용:
kindnames: []
돌연변이 내용:
[ADD_KIND_NAME] (state, name) {
state.kindnames.push(name);
}
메모:여 기 는 push 방식 을 직접 사용 합 니 다.물론 push 를 제외 하고 우 리 는 shift 등 여러 가지 방식 도 할 수 있다.
actions 의 내용:
commit(ADD_KIND_NAME, state.items[index++].name);
여기,state.items[index++].name 에서 가 져 온 문자열 입 니 다.마지막 으로 데 이 터 를 보면 다음 과 같다.
주:마찬가지 로 문 서 를 참고 할 수 있 습 니 다---세부 사항 과 최선 의 실천
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Fastapi websocket 및 vue 3(Composition API)1부: FastAPI virtualenv 만들기(선택 사항) FastAPI 및 필요한 모든 것을 다음과 같이 설치하십시오. 생성main.py 파일 및 실행 - 브라우저에서 이 링크 열기http://127.0.0.1:...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.