TypeScript 명시적 할당 단언으로 인해 Vue 속성이 응답하지 않음

이른바'현식부치단언'은 사실!: 연산자이다.TypeScript 2.7에서 도입한 특성으로 TypeScript 공식 문서를 참조할 수 있습니다.그래도 영어 문서를 좀 더 정확하게 보는 것을 권장합니다.나는 중국어 문서가 뜻밖에도 원문의 일부분을 삭제했다고 반드시 나무라야 한다.가장 심한 것은 중국어 문서는 심지어 정부에서 제시한 용법까지 삭제했다!무슨 속셈인지 모르겠다.
이번에 발생한 문제는 Vue의 계산 속성이 터치되지 않는다는 것이다.계산 속성이 터치되지 않는 이유는 모두가 잘 알고 있을 것이다. 속성이 업데이트되지 않았거나(성능 향상을 위해 중복 계산을 피함) 응답할 수 없는 속성에 의존했기 때문이다. 이런 공식 문서는 이미 명확하게 말했다.
계산 속성은 그들의 응답식 의존을 바탕으로 캐시를 하는 것이다.관련 응답식 의존이 바뀔 때만 값을 다시 구할 수 있습니다.
JavaScript로 작성한 경우 이러한 내용은 사실 모두 문제가 되지 않습니다.하지만 이번에 저는 프로젝트에 TypeScript를 도입했고 쓰기에 편하도록 vue-property-decoratorvuex-class도 도입했습니다.
문제는 이렇다. 흔히 볼 수 있는 업무 장면이기도 하다. 네비게이션 구성 요소인 NavBar는 vuex에서 Token을 읽고 계산 속성을 넣어 로그인 상태를 검사해야 한다.리셋 후 vuex 상태가 분실되는 문제를 피하기 위해 local Storage를 사용하여 Token을 더 저장합니다.그리고 로그아웃을 누르면 모든 토큰을 비웁니다.간략하게 쓰는 방법은 대략 다음과 같다.
@Component({})
export default class NavBar extends Vue {
    //   token
    @State('token') token!: string;
	//     
	get hasLogin() {
        return !!this.token || !!localStorage.getItem('token');
    }
	//   token
	@Action('updateToken') updateToken!: (payload: RootPayload) => void;
    //   
    logout() {
        this.updateToken({
            token: ''
        });
        localStorage.removeItem('token');
    }
}
나는 이곳을 본 사람들이 모두 대략vue-property-decoratorvuex-class의 용법을 보았고 주석(또는 장식기)도 사용한 적이 있다고 가정한다.왜 여기는 이른바 현식부치로 단언해야 합니까?vuex-class의 공식 문서 작성 방법은 다음과 같습니다.
@State('foo') stateFoo;
이렇게 하면 TypeScript 컴파일러의 null 검사로 인해 오류가 발생합니다.내가 보기에 인터넷에서 어떤 사람이 tsconfig에서 할 수 있다고 한다.json에 "strictNullChecks": falsenull 검사를 닫아서 컴파일을 통과했지만 조금의 편의를 위해 코드 검사를 닫는 것을 좋아하지 않아서 존재할 수 있는 질이 떨어질 수 있기 때문에 !:라는 문법을 사용해서 컴파일러에게 여기에 값이 있다는 것을 알려주었다.
그런데 문제가 생겼어요. 로고 함수를 터치한 후 로그인 상태는 변하지 않았어요.물러나지 않은 것이다.디버깅을 통해 나는 계산 속성이 터치되지 않은 것을 발견했다.local Storage는 분명히 응답할 수 없습니다. 그러면 검사해야 할 것은token입니다. 즉,token 값이 변하지 않았거나,token이 응답할 수 없다는 것입니다.이것은 매우 이상하다. 이론적으로 vuex의 변화는 Vue 실례에 비추고 여기서 얻은 Token도 데이터에 마운트되어야 한다. 왜냐하면 vue-class-component 문서에 따르면
Initial data can be declared as class properties.
@Component({...})
export default class App extends Vue {
  // initial data
  msg = 123
}
다시 디버깅을 하면 토큰의 값이 바뀔 수 있습니다.그렇다면 유일한 해석은 토큰이 응답할 수 없다는 것이다.그런데 왜 이러지?설마 이 창고가 틀렸단 말인가?그러나 나는 vue-class-component의 issue를 조사했지만 이 문제를 피드백하는 사람이 없다는 것을 발견하지 못했다.그럼 일단 창고가 문제가 아니라고 생각하세요.
사실 이전에 나는 비동기적인 문제로 인해 발생한 것이라고 의심한 적이 있다. 왜냐하면 Action은 프로미스를 되돌려줄 것이고, 나는 코드에서 현저하게 처리하지 않았기 때문이다.그래서 나는 동기화된 Mutation으로 바꿨지만 변화가 없었다.
응답할 수 없으니 응답할 수 있는 속성을 추가하세요.코드를 수정하려면 다음과 같이 하십시오.
@Component({})
export default class NavBar extends Vue {
    //   token
    // @State('token') token!: string;
	respondToken: string = ''; //     token
	//     
	get hasLogin() {
        return !!this.respondToken || !!localStorage.getItem('token');
    }
	mounted() {
        this.respondToken = localStorage.getItem('token') as string;
    }
	//   token
	@Action('updateToken') updateToken!: (payload: RootPayload) => void;
    //   
    logout() {
        this.updateToken({
            token: ''
        });
        localStorage.removeItem('token');
        this.respondToken = '';
    }
}
문제 해결.근데 왜죠?한참을 생각하다 보니 Vue의 생명주기가 생각났다.데이터의 응답 가능한 속성은create 기간에 마운트됩니다.이 토큰이create 기간에 마운트되지 않았다는 것을 의미합니다.나는 변경 전후의 코드를 tsc로 컴파일하여 실마리를 발견했다.
//    
var NavBar = /** @class */ (function (_super) {
    __extends(NavBar, _super);
    function NavBar() {
        var _this = _super !== null && _super.apply(this, arguments) || this;
        // props
        //   !
        return _this;
    }
    // ...
    __decorate([
        vuex_class_1.State("token")
    ], NavBar.prototype, "token");
    __decorate([
        vuex_class_1.Action('updateToken')
    ], NavBar.prototype, "updateToken");
    return NavBar;
}(vue_property_decorator_1.Vue));
//    
var NavBar = /** @class */ (function (_super) {
    __extends(NavBar, _super);
    function NavBar() {
        var _this = _super !== null && _super.apply(this, arguments) || this;
        // props
        _this.respondToken = ''; //     token,   !
        return _this;
    }
    // ...
    __decorate([
        vuex_class_1.State('token')
    ], NavBar.prototype, "token");
    __decorate([
        vuex_class_1.Action('updateToken')
    ], NavBar.prototype, "updateToken");
    return NavBar;
}(vue_property_decorator_1.Vue));
코드에서 볼 수 있듯이 데이터는 구조기에 놓여 초기화되었다.장식기, 즉 우리vuex-class는 전체 구성 요소를 초기화한 후에 마운트합니다.물론 그것을 탓할 수는 없다. TypeScript의 컴파일러도 뒤집어써야 한다. 왜냐하면 TypeScript의 컴파일러는 구성할 때 현식 값 단언의 변수를 무시하기 때문이다.우리는 아무 클래스나 컴파일하면 알 수 있다.
// ts
class Test {
	test!: string;
}
// js
var Test = /** @class */ (function () {
    function Test() {
    }
    return Test;
}());
봤지?이 물건은 정말 남에게 해를 끼친다.하지만 이것도 나로 하여금 Vue3에 대해 더욱 강한 흥미를 가지게 했다. TypeScript로 재구성한 Vue는 도대체 어떻게 변할 것인가?특히 대회에서 이 문제들을 어떻게 처리합니까?기대된다.

좋은 웹페이지 즐겨찾기