シリーズ記事ディレクトリ
コンテンツ | 参考リンク |
---|---|
Vueの基本的な使い方 | Vue の基本的な使い方 (Vue の最も基本的な知識ポイントをマスターするための 1 つの記事) |
Vue通信と高度な機能 | Vue コンポーネントと高度な機能間の通信 (さまざまなコンポーネント、カスタム v-model、nextTick、スロット間の通信) |
Vue の高度な機能 | Vue の高度な機能 (動的コンポーネント、非同期ロード、キープアライブ、ミックスイン、Vuex、Vue-Router) |
ビューの原則 1 | Vue の原理 (MVVM モデルの理解、データ変更の詳細/監視、配列変更の監視、仮想 DOM の詳細な理解) |
ビューの原則 2 | Vue の原則 (diff アルゴリズム、テンプレートのコンパイル、コンポーネントのレンダリングと更新、JS 実装のルーティング) |
Vue インタビューの質問 | Web フロントエンド面接高頻度テストサイト - Vue 面接の質問 |
記事ディレクトリ
1. 仮想 DOM の概要 - diff アルゴリズム
- diff アルゴリズムは、vdom のコアであり、最も重要な部分です。
- diff アルゴリズムは、vue react (キーなど) の日常的な使用に反映できます。
差分アルゴリズムの概要:
- diff は対照であり、Linux の diff コマンド、git diff コマンドなどの広い概念です。
- 2 つの js オブジェクトでも diff を実行できます
- vdom diff のように、2 つのツリーが diff を実行します。
ソース: https://coding.imooc.com/lesson/419.html#mid=33875
ツリー差分の時間計算量は O(n^3) です
- まず、tree1 をトラバースします。
- 次に、tree2 をトラバースします。
- 第三に、並べ替え
- 100 ノード、100 万回計算するには、アルゴリズムは使用できません
時間の複雑さを O(n) に最適化する
- レベル間ではなく、同じレベルのみを比較する
- タグが同じでない場合は、直接削除して再構築し、詳細な比較を行わない
- タグとキーが同じ場合、それらは同じノードと見なされ、それ以上の比較は必要ありません。
ソース: https://coding.imooc.com/lesson/419.html#mid=33875
2. テンプレートのコンパイル
1. テンプレートのコンパイル - 構文付き
- テンプレートは、vue 開発の最も一般的に使用される部分、つまり、使用に関連する原則です。
- html ではなく、ディレクティブ、補間、JS 式が含まれています。
テンプレートのコンパイル:
- 前提条件: JS と構文
- vue テンプレート コンパイラは、テンプレートをレンダリング関数にコンパイルします
- render 関数を実行して vnode を生成する
構文:
- 検索する obj 属性として、{} の自由変数の検索ルールを変更します
- 一致する obj プロパティが見つからない場合、エラーが報告されます
- with は注意して使用する必要があります。スコープ規則に違反し、読みにくくなります。
例: with がないと、オブジェクトの undefined プロパティは undefined です
const obj = {
a: 100, b: 200}
console.log(obj.a) // 100
console.log(obj.b) // 200
console.log(obj.c) // undefined
with を使用すると、オブジェクトで定義されていないプロパティはエラーを報告します
const obj = {
a: 100, b: 200}
// 使用 with,能改变 {} 内自由变量的查找方式
// 将 {} 内自由变量,当作 obj 的属性来查找
with (obj) {
console.log(a) // 100
console.log(b) // 200
console.log(c) // Uncaught ReferenceError: c is not defined
}
2. コンパイルされた vue テンプレートは何ですか?
テンプレートのコンパイル:
- テンプレートは html ではなく、命令、補間、JS 表現があり、判定とループを実現できます。
- HTMLはタグ言語、判定とループを実現できるのはJSだけ
- したがって、テンプレートをある種の JS コードに変換する必要があります。つまり、テンプレートのコンパイルです。
例:
(1) インストールvue-テンプレート-コンパイラ
npm i vue-template-compiler --save
(2) index.js ファイルを作成する
const compiler = require('vue-template-compiler')
......
// 编译
const res = compiler.compile(template)
console.log(res.render)
(3) デモ (以下のデモは index.js ファイルにあります...)
補間:
- 印刷結果は次のとおりです。p タグを作成します。子要素は文字列である TextVNode です。
- _c: createElement、要素の作成
- _v: createTextVNode、テキストノードを作成
- _s: toString、文字列型に変換
- this: const vm = new Vue({…})、これは vm インスタンスです
// 插值
const template = `<p>{
{message}}</p>`
// with(this){return _c('p',['p',[_v(_s(message))]])}
// h -> vnode
// createElement -> vnode
表現:
- テンプレート内の式は JS コードとして実行されます
// 表达式
const template = `<p>{
{flag ? message : 'no message found'}}</p>`
//with(this){return _c('p',[_v(_s(flag ? message : 'no message found'))])}
プロパティと動的プロパティ:
- コンテナ、div1 は静的文字列であるため、コンパイル後に引用符で囲む必要があります
- imgUrl は動的な属性であり、変数であるため、コンパイル後に引用符で囲まれていません。
// 属性和动态属性
const template = `
<div id="div1" class="container">
<img :src="imgUrl"/>
</div>
`
// with(this){return _c('div',
// {staticClass:"container",attrs:{"id":"div1"}},
// [_c('img',{attrs:{"src":imgUrl}})]
// )}
調子:
- 三項式に変換する
// 条件
const template = `
<div>
<p v-if="flag === 'a'">A</p>
<p v-else>B</p>
</div>
`
// with(this){return _c('div',[(flag === 'a')?_c('p',[_v("A")]):_c('p',[_v("B")])])}
サイクル:
- _l: renderList、レンダー リスト
- 2 番目の戻り値。返される最初のパラメーターはタグ、2 番目のパラメーターは属性、3 番目のパラメーターは子要素です。
// 循环
const template = `
<ul>
<li v-for="item in list" :key="item.id">{
{item.title}}</li>
</ul>
`
// with(this){return _c('ul',_l((list),function(item){return _c('li',{key:item.id},[_v(_s(item.title))])}),0)}
イベント:
- on にイベントがあり、関数の名前は引用符なしの変数です。
// 事件
const template = `
<button @click="clickHandler">submit</button>
`
// with(this){return _c('button',{on:{"click":clickHandler}},[_v("submit")])}
v-モデル:
// v-model
const template = `<input type="text" v-model="name">`
// 主要看 input 事件
// with(this){return _c('input',{directives:[{name:"model",rawName:"v-model",value:(name),expression:"name"}],attrs:{"type":"text"},domProps:{"value":(name)},on:{"input":function($event){if($event.target.composing)return;name=$event.target.value}}})}
テンプレートをコンパイルします。
- テンプレートはレンダリング関数にコンパイルされ、レンダリング関数が実行されて vnode が返されます
- vnode に基づいて patch と diff を実行する
- webpack vue-loader を使用して、テンプレートは開発環境でコンパイルされます
3. vue コンポーネントでテンプレートの代わりに render を使用する
- いくつかの複雑なケースでは、テンプレートを使用できず、レンダリングを考慮することができます
- React は常に render を使用してきました (テンプレートなし)
Vue.component('heading', {
// template: `xxx`,
render: function (createElement) {
return createElement(
'h' + this.level,
[
createElement('a', {
attrs: {
name: 'headerId',
href: '#' + 'headerId'
}
}, 'this is a tag')
]
)
}
})
要約:
- 構文付き
- 関数をレンダリングするためのテンプレート、vnode へ、レンダリングおよび更新するためのテンプレート
- Vue コンポーネントはテンプレートの代わりに render を使用できます
4. コンポーネントのレンダリング/更新プロセスの要約
- コンポーネントがページにレンダリングされ、データを変更すると更新がトリガーされます (データ駆動型ビュー)
- その理由と、押さえておきたいポイントとは?
- プロセスの理解の包括性を調べる
3 つの知識ポイント:
- レスポンシブ: データ プロパティのゲッター セッターをリッスンします。
- テンプレートのコンパイル: テンプレートからレンダリング関数、次に vnode へ
- vdom:patch(elem,vnode) 和 patch(vnode, newVnode)
3 つのプロセス:
- 初期レンダリング プロセス
- 更新プロセス
- 非同期レンダリング
3. vue コンポーネントがどのようにレンダリングおよび更新されるか
1. 最初のレンダリング プロセス
- テンプレートをレンダリング関数に解析します (または開発環境で完成した vue-loader )。
- トリガー応答、データ プロパティ ゲッター セッターをリッスン
- render 関数を実行して vnode, patch(elem, vnode) を生成する
2. render 関数を実行すると、getter がトリガーされます
- テンプレートで使用されているものは get をトリガーします
- テンプレートで使用されていないものは、ビューとは関係がないため、get をトリガーしません。
<p>{
{
message}}</p>
export default {
data() {
return {
message: '杂货铺', // 会触发 get
city: '北京' // 不会触发 get,因为模板没用到,即和视图没关系
}
}
}
3. 更新プロセス
- データを変更してセッターをトリガーします(以前はゲッターで監視されていました)
- render 関数を再実行して newVnode を生成する
- patch(vnode, newVnode)
4. vue コンポーネントで非同期にレンダリングする方法
- $nextTick は非同期です
- データの変更を要約し、一度にビューを更新します
- DOM 操作の数を減らし、パフォーマンスを向上させる
4.JSでハッシュルーティングを実装する方法
- vue-router のルーティング モード: ハッシュ モード、H5 履歴
1. ウェブページの URL の構成要素
http://127.0.0.1:8881/01-hash.html?a=100&b=20#/aaa/bbb
location.protocol // 'http:' 【协议】
location.hostname // '127.0.0.1' 【IP地址/域名】
location.host // '127.0.0.1:8881' 【IP地址带端口】
location.port // '8881' 【端口】
location.pathname // '/01-hash.html' 【文件路径名】
location.search // '?a=100&b=20' 【参数】
location.hash // '#/aaa/bbb' 【#及后面的部分】
2. ハッシュの特徴
- ハッシュの変更により、Web ページのジャンプ、つまりブラウザの前後のジャンプがトリガーされます
- ハッシュの変更は、SPA の必要な機能であるページを更新しません。
- ハッシュがサーバー側に送信されることはありません (フロントエンドはそれ自体で対処します)
3. ハッシュ変更の例
- onhashchange: ハッシュ値の変更を監視するために使用されます
- href 属性は、現在表示されているドキュメントの完全な URL を設定または返す読み取りおよび書き込み可能な文字列です。
<p>hash test</p>
<button id="btn1">修改 hash</button>
// hash 变化,包括
// a. JS 修改 url
// b. 手动修改 url 的 hash
// c. 浏览器前进、后退
window.onhashchange = (event) => {
console.log('old url', event.oldURL)
console.log('new url', event.newURL)
console.log('hash', location.hash)
}
// 页面初次加载,获取 hash
document.addEventListener('DOMContentLoaded', () => {
console.log('hash:', location.hash)
})
// JS 修改 url
document.getElementById('btn1').addEventListener('click', () => {
location.href = '#/user'
})
5. JS で H5 履歴ルーティングを実装する方法
- URL指定でルーティングしますが、ジャンプ時にページを更新しません
- history.pushState
- window.onpopstate
1.例
- history.pushState(状態、タイトル、URL)
- state: 指定された URL に関連する状態オブジェクト popstate イベントがトリガーされると、オブジェクトはコールバック関数に渡されます。このオブジェクトが必要ない場合は、ここに null を入力できます
- title: 新しいページのタイトルですが、現在すべてのブラウザがこの値を無視するため、ここに null を入力できます
- url: 新しい URL。現在のページと同じドメインにある必要があります。ブラウザのアドレス バーにこの URL が表示されます
<p>history API test</p>
<button id="btn1">修改 url</button>
// 页面初次加载,获取 path
document.addEventListener('DOMContentLoaded', () => {
console.log('load', location.pathname)
})
// 打开一个新的路由
// 【注意】用 pushState 方式,浏览器不会刷新页面
document.getElementById('btn1').addEventListener('click', () => {
const state = {
name: 'page1'}
console.log('切换路由到', 'page1')
history.pushState(state, '', 'page1')
})
// 监听浏览器前进、后退‘
window.onpopstate = (event) => {
console.log('onpopstate', event.state, location.pathname)
}
2. 選び方
- B (企業または特定のユーザー グループ向け) システムでは、使いやすく、URL の仕様に左右されないハッシュを使用することをお勧めします。
- C (個人消費者向け) システムには、H5 履歴の選択を検討できますが、サーバー サポートが必要です。
- シンプルなものを選択できる、複雑なものを使用しない、コストとメリットを考慮できる
不积跬步无以至千里,不积小流无以成江海
クリックしてフォローし、迷子にならないように、更新を続けてください...