이 글에서는 vue2.x의 this 포인팅 문제에 대해 설명하고, 이것이 vue 인스턴스를 가리키는 이유를 소개합니다. 모두에게 도움이 되기를 바랍니다.
그룹 내의 코드 연습에서 이것이 왜 데이터, 메서드, props 및 계산의 값에 직접 호출될 수 있는지 언급했습니다. 그러자 모두가 추측을 했지만 명확한 대답은 없었습니다. 이 문제를 명확히 하려면 vue의 소스 코드를 이해한 후 이를 기록하는 기사를 작성하겠습니다.
질문하기
일반적으로 vue 코드를 개발하면 거의 항상 이렇게 작성합니다
export default { data() { return { name: '彭鱼宴' } }, methods: { greet() { console.log(`hello, 我是${this.name}`) } } }
여기서 this.name이 데이터에 정의된 이름에 직접 액세스할 수 있거나, this.someFn이 정의된 메서드에 직접 액세스할 수 있는 이유는 무엇입니까? 이 질문을 염두에 두고 vue2.x의 소스 코드를 살펴보기 시작했습니다.
소스코드 분석
vuevue 소스코드의 소스코드 주소입니다. 먼저 vue 인스턴스의 생성자를 살펴보겠습니다. 생성자는 소스 코드 디렉토리인 /vue/src/core/instance/index.js에 있습니다. 모두 게시하고 살펴보세요. 생성자는 매우 간단합니다. if (!(this 인스턴스of Vue)){}
new
키워드가 생성자를 호출하는 데 사용되는지 여부를 결정합니다. 그렇지 않으면 경고가 발생합니다. . 여기 이
가 있습니다. Vue의 인스턴스를 나타냅니다. new
키워드를 정상적으로 사용한다면 _init
함수를 사용하면 됩니다. 아주 간단하죠?
if (!(this instanceof Vue)){}
判断是不是用了 new
关键词调用构造函数,没有则抛出warning,这里的this
指的是Vue的一个实例。如果正常使用了new
关键词,就走_init
函数,是不是很简单。
_init函数分析
function Vue (options) { if (process.env.NODE_ENV !== 'production' && !(this instanceof Vue) ) { warn('Vue is a constructor and should be called with the `new` keyword') } this._init(options) } initMixin(Vue) stateMixin(Vue) eventsMixin(Vue) lifecycleMixin(Vue) renderMixin(Vue) export default Vue
_init函数有点长,做了很多事情,这里就不一一解读,和我们此次探索相关的内容应该在initState(vm)这个函数中,我们继续到initState这个函数里看看。
initState函数分析
let uid = 0 export function initMixin (Vue: Class<Component>) { Vue.prototype._init = function (options?: Object) { const vm: Component = this // a uid vm._uid = uid++ let startTag, endTag /* istanbul ignore if */ if (process.env.NODE_ENV !== 'production' && config.performance && mark) { startTag = `vue-perf-start:${vm._uid}` endTag = `vue-perf-end:${vm._uid}` mark(startTag) } // a flag to avoid this being observed vm._isVue = true // merge options if (options && options._isComponent) { // optimize internal component instantiation // since dynamic options merging is pretty slow, and none of the // internal component options needs special treatment. initInternalComponent(vm, options) } else { vm.$options = mergeOptions( resolveConstructorOptions(vm.constructor), options || {}, vm ) } /* istanbul ignore else */ if (process.env.NODE_ENV !== 'production') { initProxy(vm) } else { vm._renderProxy = vm } // expose real self vm._self = vm initLifecycle(vm) initEvents(vm) initRender(vm) callHook(vm, 'beforeCreate') initInjections(vm) // resolve injections before data/props initState(vm) initProvide(vm) // resolve provide after data/props callHook(vm, 'created') /* istanbul ignore if */ if (process.env.NODE_ENV !== 'production' && config.performance && mark) { vm._name = formatComponentName(vm, false) mark(endTag) measure(`vue ${vm._name} init`, startTag, endTag) } if (vm.$options.el) { vm.$mount(vm.$options.el) } } }
可以看出initState做了5件事情
- 初始化props
- 初始化methods
- 初始化data
- 初始化computed
- 初始化watch
我们先重点看看初始化methods做了什么
initMethods 初始化方法
export function initState (vm: Component) { vm._watchers = [] const opts = vm.$options if (opts.props) initProps(vm, opts.props) if (opts.methods) initMethods(vm, opts.methods) if (opts.data) { initData(vm) } else { observe(vm._data = {}, true /* asRootData */) } if (opts.computed) initComputed(vm, opts.computed) if (opts.watch && opts.watch !== nativeWatch) { initWatch(vm, opts.watch) } }
initMethods主要是一些判断:
function initMethods (vm, methods) { var props = vm.$options.props; for (var key in methods) { { if (typeof methods[key] !== 'function') { warn( "Method \"" + key + "\" has type \"" + (typeof methods[key]) + "\" in the component definition. " + "Did you reference the function correctly?", vm ); } if (props && hasOwn(props, key)) { warn( ("Method \"" + key + "\" has already been defined as a prop."), vm ); } if ((key in vm) && isReserved(key)) { warn( "Method \"" + key + "\" conflicts with an existing Vue instance method. " + "Avoid defining component methods that start with _ or $." ); } } vm[key] = typeof methods[key] !== 'function' ? noop : bind(methods[key], vm); } }
除去上述说的这些判断,最重要的就是在vue实例上定义了一遍methods里所有的方法,并且使用bind函数将函数的this指向Vue实例上,就是我们new Vue()的实例对象上。
这就解释了为啥this可以直接访问到methods里的方法。
initData 初始化数据
判断methods中定义的函数是不是函数,不是函数就抛warning; 判断methods中定义的函数名是否与props冲突,冲突抛warning; 判断methods中定义的函数名是否与已经定义在Vue实例上的函数相冲突,冲突的话就建议开发者用_或者$开头命名;
initdata做了哪些事情呢:
- 先在实例 _data 上赋值,getData函数处理 data 这个 function,返回的是一个对象
- 判断最终获取到的 data, 不是对象给出警告。
- 判断methods里的函数和data里的key是否有冲突
- 判断props和data里的key是否有冲突
- 判断是不是内部私有的保留属性,若不是就做一层代理,代理到 _data 上
- 最后监听data,使之成为响应式数据
再看下proxy函数做了什么:
function initData (vm) { var data = vm.$options.data; data = vm._data = typeof data === 'function' ? getData(data, vm) : data || {}; if (!isPlainObject(data)) { data = {}; warn( 'data functions should return an object:\n' + 'https://vuejs.org/v2/guide/components.html#data-Must-Be-a-Function', vm ); } // proxy data on instance var keys = Object.keys(data); var props = vm.$options.props; var methods = vm.$options.methods; var i = keys.length; while (i--) { var key = keys[i]; { if (methods && hasOwn(methods, key)) { warn( ("Method \"" + key + "\" has already been defined as a data property."), vm ); } } if (props && hasOwn(props, key)) { warn( "The data property \"" + key + "\" is already declared as a prop. " + "Use prop default value instead.", vm ); } else if (!isReserved(key)) { proxy(vm, "_data", key); } } // observe data observe(data, true /* asRootData */); }
其实这里的Object.defineProperty
就是用来定义对象的
proxy
的用处就是使this.name
指向this._data.name
剩下的observe函数不在此次探讨范围,感兴趣的朋友可以自己去看看源码。
总结
回到一开始抛出的问题做一个解答:
methods
里的方法通过bind
指定了this
为 new Vue的实例(vm
),methods里的函数也都定义在vm
上了,所以可以直接通过this
直接访问到methods
里面的函数。data
函数返回的数据对象也都存储在了new Vue的实例(vm
)上的_data
上了,访问this.name
时实际访问的是Object.defineProperty
代理后的this._data.name
_init 함수 분석
function noop (a, b, c) {} var sharedPropertyDefinition = { enumerable: true, configurable: true, get: noop, set: noop }; function proxy (target, sourceKey, key) { sharedPropertyDefinition.get = function proxyGetter () { return this[sourceKey][key] }; sharedPropertyDefinition.set = function proxySetter (val) { this[sourceKey][key] = val; }; Object.defineProperty(target, key, sharedPropertyDefinition); }_init 함수는 좀 길고 할 일이 많아서 하나씩 설명하지는 않겠습니다. 이번에는 내용이 initState(vm) 함수에 있어야 합니다. initState가 5가지 일을 하는 것을 볼 수 있습니다🎜
- props 초기화🎜
- 초기화 방법
- 데이터 초기화 데이터
- 컴퓨팅 초기화
- 초기화 초기화 방법이 초기화 초기화 방법에 대한 초기화 초기화 초기화 초기화 초기화 방법 🎜🎜rrreee🎜initmethods는 주로 판단입니다. 위의 판단에서 🎜가장 중요한 것은 vue 인스턴스의 메소드에 있는 모든 메소드를 정의하고 바인드 함수를 사용하여 함수의 this를 새로운 Vue의 인스턴스 객체인 Vue 인스턴스🎜로 지정하는 것입니다. () . 🎜🎜이것이 메소드의 메소드에 직접 액세스할 수 있는 이유를 설명합니다. 🎜🎜🎜initData는 데이터를 초기화합니다🎜🎜rrreee🎜initdata의 기능: 🎜
- 먼저 _data 인스턴스에 값을 할당하고, getData 함수는 데이터 함수를 처리하고 객체를 반환합니다.🎜
- 판단 최종 획득한 데이터는 객체가 아니며 경고가 발생합니다. 🎜
- 메서드의 함수와 데이터의 키 사이에 충돌이 있는지 확인🎜
- props와 데이터의 키 사이에 충돌이 있는지 확인🎜
- 내부 비공개 예약 속성인지 확인 , 그렇지 않은 경우 레이어 생성 프록시, _data에 대한 프록시🎜
- 마지막으로 데이터를 수신하여 반응형 데이터로 만듭니다🎜🎜🎜프록시 기능이 수행하는 작업을 살펴보겠습니다.🎜rrreee🎜실제로
Object.defineProperty
여기는
🎜🎜객체를 정의하는 데 사용되는프록시
의 목적은this.name
이this._data.name을 가리키도록 만드는 것입니다.
🎜🎜나머지 관찰 기능은 이 토론의 범위에 포함되지 않습니다. 관심 있는 친구는 소스 코드를 직접 확인해 볼 수 있습니다. 🎜🎜🎜요약🎜🎜🎜처음에 제기한 질문으로 돌아가서 답변해 주세요. 🎜- 🎜
메소드의 메소드 code> <code>bind
를 통해this
는 새로운 Vue(vm
)의 인스턴스로 지정되고 메소드의 함수도에 정의됩니다. >vm
이므로this
를 통해메서드
의 함수에 직접 액세스할 수 있습니다. 🎜🎜 - 🎜
data
함수에서 반환된 데이터 개체는 새 Vue 인스턴스(vm
)의_data
에도 저장됩니다.this.name
에 액세스하면 실제로 액세스되는 것은Object.defineProperty
프록시 다음의this._data.name
입니다. 🎜🎜🎜🎜 이 데이터 디자인 패턴의 장점과 단점에 대해서는 계속해서 살펴볼 수 있지만 결국 이는 이 토론의 일부가 아닙니다. 🎜🎜【관련 추천: 🎜vue.js 동영상 튜토리얼🎜】🎜
- 🎜
위 내용은 vue2.x에서 이것의 포인팅 문제에 대해 이야기해 봅시다. 왜 이것이 vue 인스턴스를 가리키나요?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

웹 개발에서 vue.js의 역할은 개발 프로세스를 단순화하고 효율성을 향상시키는 점진적인 JavaScript 프레임 워크 역할을하는 것입니다. 1) 개발자는 반응 형 데이터 바인딩 및 구성 요소 개발을 통해 비즈니스 로직에 집중할 수 있습니다. 2) vue.js의 작동 원리는 반응 형 시스템 및 가상 DOM에 의존하여 성능을 최적화합니다. 3) 실제 프로젝트에서는 Vuex를 사용하여 글로벌 상태를 관리하고 데이터 대응 성을 최적화하는 것이 일반적입니다.

vue.js는 2014 년 Yuxi가 출시하여 사용자 인터페이스를 구축하기 위해 진보적 인 JavaScript 프레임 워크입니다. 핵심 장점은 다음과 같습니다. 1. 응답 데이터 바인딩, 데이터 변경의 자동 업데이트보기; 2. 구성 요소 개발, UI는 독립적이고 재사용 가능한 구성 요소로 분할 될 수 있습니다.

Netflix는 React를 프론트 엔드 프레임 워크로 사용합니다. 1) React의 구성 요소화 된 개발 모델과 강력한 생태계가 Netflix가 선택한 주된 이유입니다. 2) 구성 요소화를 통해 Netflix는 복잡한 인터페이스를 비디오 플레이어, 권장 목록 및 사용자 댓글과 같은 관리 가능한 청크로 분할합니다. 3) React의 가상 DOM 및 구성 요소 수명주기는 렌더링 효율성 및 사용자 상호 작용 관리를 최적화합니다.

프론트 엔드 기술에서 Netflix의 선택은 주로 성능 최적화, 확장 성 및 사용자 경험의 세 가지 측면에 중점을 둡니다. 1. 성능 최적화 : Netflix는 React를 주요 프레임 워크로 선택하고 Speedcurve 및 Boomerang과 같은 도구를 개발하여 사용자 경험을 모니터링하고 최적화했습니다. 2. 확장 성 : 마이크로 프론트 엔드 아키텍처를 채택하여 응용 프로그램을 독립 모듈로 분할하여 개발 효율성 및 시스템 확장 성을 향상시킵니다. 3. 사용자 경험 : Netflix는 재료 -UI 구성 요소 라이브러리를 사용하여 A/B 테스트 및 사용자 피드백을 통해 인터페이스를 지속적으로 최적화하여 일관성과 미학을 보장합니다.

NetflixusesAcustomFrameworkCalled "Gibbon"BuiltonReact, NotreactorVuedirectly.1) TeamExperience : 2) ProjectComplexity : vueforsimplerProjects, 3) CustomizationNeeds : reactoffersmoreflex.4)

Netflix는 주로 프레임 워크 선택의 성능, 확장 성, 개발 효율성, 생태계, 기술 부채 및 유지 보수 비용을 고려합니다. 1. 성능 및 확장 성 : Java 및 SpringBoot는 대규모 데이터 및 높은 동시 요청을 효율적으로 처리하기 위해 선택됩니다. 2. 개발 효율성 및 생태계 : React를 사용하여 프론트 엔드 개발 효율성을 향상시키고 풍부한 생태계를 활용하십시오. 3. 기술 부채 및 유지 보수 비용 : Node.js를 선택하여 유지 보수 비용과 기술 부채를 줄이기 위해 마이크로 서비스를 구축하십시오.

Netflix는 주로 VUE가 특정 기능을 위해 보충하는 프론트 엔드 프레임 워크로 React를 사용합니다. 1) React의 구성 요소화 및 가상 DOM은 Netflix 애플리케이션의 성능 및 개발 효율을 향상시킵니다. 2) VUE는 Netflix의 내부 도구 및 소규모 프로젝트에 사용되며 유연성과 사용 편의성이 핵심입니다.

vue.js는 복잡한 사용자 인터페이스를 구축하는 데 적합한 점진적인 JavaScript 프레임 워크입니다. 1) 핵심 개념에는 반응 형 데이터, 구성 요소화 및 가상 DOM이 포함됩니다. 2) 실제 응용 분야에서는 TODO 응용 프로그램을 구축하고 Vuerouter를 통합하여 시연 할 수 있습니다. 3) 디버깅 할 때 VuedeVtools 및 Console.log를 사용하는 것이 좋습니다. 4) 성능 최적화는 V-IF/V- 쇼, 목록 렌더링 최적화, 구성 요소의 비동기로드 등을 통해 달성 할 수 있습니다.


핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

DVWA
DVWA(Damn Vulnerable Web App)는 매우 취약한 PHP/MySQL 웹 애플리케이션입니다. 주요 목표는 보안 전문가가 법적 환경에서 자신의 기술과 도구를 테스트하고, 웹 개발자가 웹 응용 프로그램 보안 프로세스를 더 잘 이해할 수 있도록 돕고, 교사/학생이 교실 환경 웹 응용 프로그램에서 가르치고 배울 수 있도록 돕는 것입니다. 보안. DVWA의 목표는 다양한 난이도의 간단하고 간단한 인터페이스를 통해 가장 일반적인 웹 취약점 중 일부를 연습하는 것입니다. 이 소프트웨어는

PhpStorm 맥 버전
최신(2018.2.1) 전문 PHP 통합 개발 도구

SublimeText3 영어 버전
권장 사항: Win 버전, 코드 프롬프트 지원!

SecList
SecLists는 최고의 보안 테스터의 동반자입니다. 보안 평가 시 자주 사용되는 다양한 유형의 목록을 한 곳에 모아 놓은 것입니다. SecLists는 보안 테스터에게 필요할 수 있는 모든 목록을 편리하게 제공하여 보안 테스트를 더욱 효율적이고 생산적으로 만드는 데 도움이 됩니다. 목록 유형에는 사용자 이름, 비밀번호, URL, 퍼징 페이로드, 민감한 데이터 패턴, 웹 셸 등이 포함됩니다. 테스터는 이 저장소를 새로운 테스트 시스템으로 간단히 가져올 수 있으며 필요한 모든 유형의 목록에 액세스할 수 있습니다.

ZendStudio 13.5.1 맥
강력한 PHP 통합 개발 환경
