Maison >interface Web >Voir.js >Explication détaillée de l'initialisation des données (initState) dans vue

Explication détaillée de l'initialisation des données (initState) dans vue

青灯夜游
青灯夜游avant
2020-10-30 17:57:064609parcourir

La colonne Tutoriel Vue.js suivante vous guidera à travers l'initialisation des données (initState) dans vue. Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer. J'espère qu'il sera utile à tout le monde.

Explication détaillée de l'initialisation des données (initState) dans vue

Initialisation des données

L'instance Vue exécutera une série d'opérations d'initialisation lors de sa création, et Parmi ces opérations d'initialisation, celle la plus étroitement associée à la liaison de données est initState.

Tout d'abord, jetons un coup d'œil à son code :

function initState(vm) {
    vm._watchers = [];
    var opts = vm.$options;
    if(opts.props) {
        initProps(vm, opts.props); //初始化props
    }
    if(opts.methods) {
        initMethods(vm, opts.methods); //初始化methods
    }
    if(opts.data) {
        initData(vm); //初始化data
    } else {
        observe(vm._data = {}, true /* asRootData */ );
    }
    if(opts.computed) {
        initComputed(vm, opts.computed); //初始化computed
    }
    if(opts.watch && opts.watch !== nativeWatch) {
        initWatch(vm, opts.watch); //初始化watch
    }
}

Dans l'initialisation de tant de données, les accessoires, les méthodes et les données sont relativement simples (je ne les présenterai donc pas dans détail☺) , bien que calculé et surveillé soient relativement difficiles et aient une logique compliquée, je parlerai donc principalement de calculé et surveillé ci-dessous (la partie de code suivante est simplifiée).

InitState initialise principalement les accessoires, les méthodes, les données, les données calculées et de surveillance dans l'instance vue.

Lors de l'initialisation des accessoires (initProps), chaque attribut des accessoires sera parcouru, puis une vérification de type, une surveillance des données, etc. seront effectuées (une fonction de hook qui lancera un avertissement lors de l'attribution d'une valeur aux attributs des accessoires ) est fourni.

Lors de l'initialisation des méthodes (initMethods), il surveille principalement si les noms de méthodes dans les méthodes sont légaux.

Lors de l'initialisation des données (initData), la fonction d'observation sera exécutée pour parcourir en profondeur chaque attribut des données afin d'effectuer un détournement de données.

Lors de l'initialisation de calculated (initComputed), il surveillera si les données existent déjà dans data ou props. Si elles existent, un avertissement sera émis. Sinon, la fonction DefinComputed sera appelée, surveillera les données et. liez les getters et les propriétés aux propriétés du composant. Si la valeur d'un attribut calculé est une fonction, la valeur par défaut est la fonction getter de l'attribut. De plus, la valeur de l'attribut peut également être un objet. Il n'a que trois champs valides : set, get et cache, qui indiquent respectivement le setter, le getter de l'attribut et si l'activation de la mise en cache est requise et la valeur par défaut du cache est true.

function initComputed(vm, computed) {
    var watchers = vm._computedWatchers = Object.create(null);

    for(var key in computed) {
        var userDef = computed[key];
        var getter = typeof userDef === 'function' ? userDef : userDef.get;

        //创建一个计算属性 watcher
        watchers[key] = new Watcher(
            vm,
            getter || noop,
            noop,
            computedWatcherOptions
        );

        if(!(key in vm)) {
            //如果定义的计算属性不在组件实例上,对属性进行数据劫持
            //defineComputed 很重要,下面我们再说
            defineComputed(vm, key, userDef);
        } else {
            //如果定义的计算属性在data和props有,抛出警告
        }
    }
}

Lors de l'initialisation de la montre (initWatch), la fonction vm.$watch sera appelée pour lier les rappels du setter aux propriétés de la montre (s'il n'y a pas de telle propriété dans le composant, elle ne peut pas être surveillée avec succès. La propriété doit exister dans les accessoires, les données ou calculé). Si la valeur de l'attribut dans la montre est une fonction, la valeur par défaut est la fonction de rappel setter de l'attribut. Si la valeur de l'attribut est un tableau, le contenu du tableau est parcouru et les rappels sont respectivement liés aux attributs. De plus, la valeur de l'attribut peut également être un objet , à ce stade, le champ du gestionnaire dans l'objet représente la fonction de rappel du setter, immédiat représente s'il faut exécuter immédiatement la méthode du gestionnaire à l'intérieur et deep représente s'il faut surveiller en profondeur.

La fonction vm.$watch utilisera directement Watcher pour construire l'objet observateur. La valeur de l'attribut dans watch existe sous le nom watcher.cb et est exécutée dans la fonction watcher.run lors de la mise à jour de l'observateur. Si vous souhaitez comprendre ce processus, vous pouvez lire mon introduction à Watcher dans la vue responsive system-observe, watcher et dep dans mon article précédent.

function initWatch(vm, watch) {
    //遍历watch,为每一个属性创建侦听器
    for(var key in watch) {
        var handler = watch[key];
        //如果属性值是一个数组,则遍历数组,为属性创建多个侦听器
        //createWatcher函数中封装了vm.$watch,会在vm.$watch中创建侦听器
        if(Array.isArray(handler)) {
            for(var i = 0; i < handler.length; i++) {
                createWatcher(vm, key, handler[i]);
            }
        } else {
            //为属性创建侦听器
            createWatcher(vm, key, handler);
        }
    }
}

function createWatcher(vm, expOrFn, handler, options) {
    //如果属性值是一个对象,则取对象的handler属性作为回调
    if(isPlainObject(handler)) {
        options = handler;
        handler = handler.handler;
    }
    //如果属性值是一个字符串,则从组件实例上寻找
    if(typeof handler === &#39;string&#39;) {
        handler = vm[handler];
    }
    //为属性创建侦听器
    return vm.$watch(expOrFn, handler, options)
}

calculé

calculé est essentiellement un observateur évalué paresseusement avec possibilité de cache Uniquement lorsque les dépendances changent, la première fois Uniquement en accédant au calculé. attribut la nouvelle valeur sera-t-elle calculée

Ce qui suit sera expliqué autour de cette phrase.

Comme mentionné dans le code ci-dessus, lorsque les données de l'attribut calculé existent dans data et props, vous serez averti, ce qui signifie que cette approche est erronée. Donc généralement, nous déclarerons les données directement dans les propriétés calculées. Dans le même extrait de code, si la propriété calculée définie ne se trouve pas sur l'instance du composant, la fonction définirComputed sera exécutée pour effectuer un détournement de données sur les données. Jetons un coup d'œil à ce qui est fait dans la fonction définirComputed.

function defineComputed(target, key, userDef) {
//是不是服务端渲染
var shouldCache = !isServerRendering();
//如果我们把计算属性的值写成一个函数,这时函数默认为计算属性的get
if(typeof userDef === &#39;function&#39;) {
sharedPropertyDefinition.get = shouldCache ?
//如果不是服务端渲染,则默认使用缓存,设置get为createComputedGetter创建的缓存函数
createComputedGetter(key) :
//否则不使用缓存,直接设置get为userDef这个我们定义的函数
userDef;
//设置set为空函数
sharedPropertyDefinition.set = noop;
} else {
//如果我们把计算属性的值写成一个对象,对象中可能包含set、get和cache三个字段
sharedPropertyDefinition.get = userDef.get ?
shouldCache && userDef.cache !== false ?
//如果我们传入了get字段,且不是服务端渲染,且cache不为false,
//设置get为createComputedGetter创建的缓存函数
createComputedGetter(key) : 
//如果我们传入了get字段,但是是服务端渲染或者cache设为了false,设置get为userDef这个我们定义的函数
userDef.get :
//如果没有传入get字段,设置get为空函数
noop;
//设置set为我们传入的传入set字段或空函数
sharedPropertyDefinition.set = userDef.set ?
userDef.set :
noop;
}
//虽然这里可以get、set都可以设置为空函数
//但是在项目中,get为空函数对数据取值会报错,set为空函数对数据赋值会报错
//而computed主要作用就是计算取值的,所以get字段是必须的

//数据劫持
Object.defineProperty(target, key, sharedPropertyDefinition);
}

Dans l'article précédent vue responsive system--observe, watcher, dep, j'ai mentionné dans l'introduction à propos de Watcher que lorsque l'observateur d'attribut calculé est instancié, il définira les options.lazy à true. C'est la clé d'une évaluation paresseuse des propriétés calculées et de la mise en cache. Bien sûr, le principe est que le cache n'est pas faux.

le cache n'est pas faux, la fonction createComputedGetter sera appelée pour créer la fonction getter ComputedGetter de l'attribut calculé

Regardons d'abord un morceau de code

function createComputedGetter(key) {
    return function computedGetter() {
        var watcher = this._computedWatchers && this._computedWatchers[key];
        if(watcher) {
            if(watcher.dirty) {
            //watcher.evaluate中更新watcher的值,并把watcher.dirty设置为false
            //这样等下次依赖更新的时候才会把watcher.dirty设置为true,
            //然后进行取值的时候才会再次运行这个函数
                watcher.evaluate();
            }
            //依赖追踪
            if(Dep.target) {
                watcher.depend();
            }
            //返回watcher的值
            return watcher.value
        }
    }
}

//对于计算属性,当取值计算属性时,发现计算属性的watcher的dirty是true
//说明数据不是最新的了,需要重新计算,这里就是重新计算计算属性的值。
Watcher.prototype.evaluate = function evaluate() {
    this.value = this.get();
    this.dirty = false;
};

//当一个依赖改变的时候,通知它update
Watcher.prototype.update = function update() {
    //三种watcher,只有计算属性 watcher的lazy设置了true,表示启用惰性求值
    if(this.lazy) {
        this.dirty = true;
    } else if(this.sync) {
        //标记为同步计算的直接运行run,三大类型暂无,所以基本会走下面的queueWatcher
        this.run();
    } else {
        //将watcher推入观察者队列中,下一个tick时调用。
        //也就是数据变化不是立即就去更新的,而是异步批量去更新的
        queueWatcher(this);
    }
};

Quand. options.lazy est défini sur true (seul le options.lazy de l'attribut calculé watcher est défini sur true). Chaque fois qu'une dépendance est mise à jour, la fonction d'exécution ne sera pas activement déclenchée, mais watcher.dirty sera défini sur true. De cette façon, lorsque la propriété calculée est évaluée, la fonction calculéeGetter sera exécutée. La fonction calculéeGetter a un jugement sur watcher.dirty. Lorsque watcher.dirty est vrai, watcher.evaluate sera exécuté pour mettre à jour la valeur et watcher dirty. est défini sur false, complétant ainsi le processus d'évaluation paresseux. Tant que la dépendance n'est pas mise à jour ultérieurement, la mise à jour ne sera pas exécutée, watcher.dirty ne sera pas défini sur true et watcher.evaluate ne sera pas exécuté pour mettre à jour la valeur lorsque la valeur est à nouveau obtenue, obtenant ainsi l'effet de cache. .

Pour résumer, nous comprenons que lorsque le cache n'est pas faux, les propriétés calculées sont paresseusement évaluées et mises en cache, et le cache par défaut est vrai, et nous utilisons principalement cette valeur par défaut, nous disons donc computed本质是一个惰性求值的观察者,具有缓存性,只有当依赖变化后,第一次访问 computed 属性,才会计算新的值.

Recommandations associées :

Résumé des questions d'entretien Front-end Vue 2020 (avec réponses)

tutoriel vue Recommandé : Les 5 dernières sélections de didacticiels vidéo vue.js en 2020

Pour plus de connaissances liées à la programmation, veuillez visiter : Enseignement de la programmation ! !

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer