目次
導入
Vue は、ユーザー インターフェイスを構築するための進歩的なフレームワークです。他の大きなフレームワークとは異なり、Vue は下から上にレイヤーごとに適用されるように設計されています。Vue のコア ライブラリはビュー レイヤーのみに焦点を当てており、開始が簡単であるだけでなく、サードパーティのライブラリや既存のプロジェクトとの統合も簡単です。一方、最新のツール チェーンやさまざまなサポート ライブラリと組み合わせると、Vue は複雑な単一ページ アプリケーション用のドライバーを提供することができます。単一ページ アプリケーション (index.html) を作成するために使用されます。ジャンプを実現するためのページ ジャンプに使用される vue プラグイン ルーティングです。
Vue の基本的なレンダリング補間とデータ モデル
//1-Vue基本渲染-插值
//代码
window.onload = function () {
// 创建vue实例,vue实例要与模板(DOM)绑定
let vm= new Vue({
el: "#app",
data: {// 数据模型
msg:'hello world'
},
// 函数
methods: {
changeData(){
if(this.msg==='hello world'){
// 更改数据模型中的数据
// 获取数据模型中的数据
// 在vue实例内访问vue实例身上的属性和方法
this.msg='你好我是修改后的值'
}else{
this.msg='hello world';
}
}
},
})
}
//html代码
<!-- 以前把msg作为元素文本的,获取dom节点,绑定事件,dom.innerText=msg-->
<div id="app">
<!-- 在模板内访问vue实例中数据模型中的数据 插值 -->
<!-- 基本渲染 插值 -->
{
{msg}}
<p>{
{msg}}</p>
<!-- 点击按钮 改变数据模型中的数据msg变量 -->
<button @click='changeData'>点我修改数据模型msg数据</button>
</div>
//数据模型更改,引发了vm驱动
MVVM
MVVM パターンは、名前が示すように、Model-View-ViewModel パターンです。
mvvm の概要: m はモデル サーバー上のビジネス ロジック操作を指し、v はビュー (ページ) を指し、vm は ViewModel モデルとビューの間のコア ハブ (vue.js など) を指します。
DOM Listeners
上図のとはData Bindings
、双方向バインドを実現するための鍵となる 2 つのツールであると考えることができます。ビュー側から見ると、ViewModel のツールは
DOM Listeners
ページ上の DOM 要素の変更を監視し、変更がある場合はモデル内のデータを変更するのに役立ちます。モデル側から見ると、モデル内のデータを更新するときに、
Data Bindings
このツールはページ内の DOM 要素の更新に役立ちます。
//2.数据模型
let vm=new Vue({
el:'#app',
data:{
msg:'高校优质男',
time:new Date()
},
methods:{
sayName(){
console.log(this.name)
},
}
})
// 每隔一秒重新查询一次时间
setInterval(()=>{
vm.time=new Date()
},1000)
// 查看vue实例对象
console.log(vm)
ライフサイクル
vue インスタンスの作成から仮想 dom の生成、データ バインディング、モニタリング、データのレンダリング、破棄までのプロセス全体
ライフサイクルの最初のステップは、vue インスタンスを作成して初期化することです。
vue インスタンスの初期化フェーズでは、
beforeCreate は
初期化中に beforeCreate を呼び出し、vue インスタンスのライフサイクル関連プロパティの初期化とイベントの初期化を完了します。現時点では、データ モデル内のデータとメソッドにはアクセスできません。
created
が初期化された後、Vue のデータ インジェクションとデータ モニタリングの操作が完了します。この構造の実行は、Vue インスタンスが作成され、データ データ モデルとメソッド メソッドにアクセスできることを意味します。vue インスタンスのマウント フェーズでは beforeMount、after created
,
Vue は
、インスタンスに el 属性が含まれているかどうかを判断します。vm.$mount(el) がない場合は、テンプレート属性が含まれているかどうかを判断します。含まれている場合は、レンダリング関数に解析されます。 el で指定された外部 HTML は解析されません。ここではテンプレートの解析のみが完了しますが、データはテンプレートにバインドされていません。
mount は
el を置き換えるために vm.$el を作成します。実際に完了するのはデータ バインディング操作であり、その間にレンダリング関数が実行され、テンプレートが解析され、データが動的にバインドされます。Update 前の vue インスタンス更新フェーズでは、仮想 dom が更新 さ
れ ますノードの 更新 が完了しました。ページの再レンダリングは、vue インスタンスの破棄フェーズ の前に呼び出され、 Destroyが破棄されます。この時点で、 破棄されたvue インスタンスにアクセスできます。
リスナー、サブコンポーネント、イベント リスナーなどの削除が完了し、Vue インスタンス オブジェクトが破棄されました。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/axios/1.3.6/axios.js"></script>
</head>
<body>
<!-- 模版 视图层 -->
<div id="app">
<!-- 采用ref代替id ref表示dom的引用 可以通过ref属性找到dom元素 -->
<div ref="box">{
{msg}}</div>
</div>
<script>
let vm = new Vue({
// 使用el属性和模版进行绑定
el: '#app',
// 数据模型 存放vue变量
data: {
msg: 'hello Vue2'
},
// vue实例中提供了template模板 就把template作为模板编译,使用render函数渲染
// template:`
// <h1>{
{msg}}</h1>
// `,
methods: {
// 异步请求 查询所有轮播图 axios
async findAll() {
let res = await axios.get('http://121.199.0.35:8888/index/carousel/findAll');
console.log(res);
}
},
/**
* 生命周期
* beforeCreate实例初始化之前 初始化默认事件和生命周期
* created 实例初始化完成 可以访问数据模型data和methods中的方法 是异步请求可以最早
*/
beforeCreate() {
console.log('实例初始化之前 初始化默认事件和生命周期', this.msg);
},
created() {
console.log('实例初始化完成 初始化完成响应式数据和methods方法', this.msg);
// this.findAll();
},
/**
* 实例挂载阶段 与模板绑定阶段
* beforeMount 实例挂载之前 查看有没有el选项,有的话查看有没有template选项
* 没有template选项,将el外部的html元素作为模板 此时访问不到dom元素
* mounted 实例挂载完成 vm创建$el代替el完成模板编译 此时可以访问dom元素 渲染图表 可以发送异步请求
*/
beforeMount() {
console.log('实例挂载之前 此时访问不到dom节点', this.$refs.box, '获取ref引用对应的dom元素')
},
// 也可以手动提供render函数编译模板
// render(createElement) {
// return createElement('h2', {}, this.msg1)
// },
mounted() {
console.log('实例挂载完成 此时可以访问dom节点', this.$refs['box'])
},
/**
* 实例更新阶段 只要响应式数据发生更改 生命周期就会被触发
* beforeUpdate 实例更新前 此时更改了数据,数据是最新,dom中数据还是原始数据,dom还未重新更新
* updated 实例更新后 此时dom中数据就是最新数据 dom重新被编译到模板中
*
* vue机制 nextTick 异步加载dom 更新dom 数据更改 dom用到该数据不会立马更新 dom更新存放在回调函数中
* 会在下一次回调函数中完成更新
*/
beforeUpdate() {
console.log('实例更新前', this.$refs.box.innerHTML, this.msg);
},
updated() {
console.log('实例更新完成', this.$refs.box.innerHTML, this.msg);
},
/**
* 实例销毁阶段生命周期
* beforeDestroy 实例销毁之前 依旧可以修改vue实例响应式数据
* destroyed 实例销毁完成 销毁了监听器 子组件 和事件监听 无法修改vue实例响应式数据 不会触发更新阶段生命周期
*/
beforeDestroy() {
console.log('实例销毁之前', this.msg);
},
destroyed() {
console.log('实例销毁完成', this.msg);
}
});
setTimeout(() => {
// 手动销毁实例
vm.$destroy()
}, 8000);
// 如果没有el属性 可以使用$mount和模板进行绑定
// vm.$mount('#app');
// setTimeout(()=>{
// vm.msg = 'hello world'
// },1000)
</script>
</body>
</html>
テンプレートの構文
導入:
Vue は HTML ベースのテンプレート構文を使用するため、開発者は DOM を基礎となる Vue インスタンスのデータに宣言的にバインドできます。すべての Vue テンプレートは正当な HTML であるため、仕様に準拠するブラウザおよび HTML パーサーで解析できます。Vue は内部的に、テンプレートを仮想 DOM レンダリング関数にコンパイルします。Vue を応答システムと組み合わせると、再レンダリングが必要なコンポーネントの最小数をインテリジェントに計算し、DOM 操作の数を最小限に抑えることができます。仮想 DOM に精通しており、JavaScript の生のパワーを好む場合は、オプションの JSX 構文 (React は jsx 構文を使用します) を使用して、レンダリング関数を作成し、テンプレートを使用せずに直接レンダリングすることもできます。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
</head>
<body>
<!-- 模版 -->
<div id="app">
<!-- 1.Mustache语法 双花括号 文本插值 -->
{
{msg}}
<!-- 2.使用v-once 进行一次性插值 后续该vue变量改变 执行一次性插值的dom元素不会改变 -->
<div v-once>{
{msg}}</div>
<!-- 3.使用v-html 识别代码片段 -->
<!-- {
{content}} 无法将字符串中标签解析 -->
<div v-html="content"></div>
<!-- 4.1给标签绑定变量 使用v-bind进行绑定 无法使用{
{}} -->
<!-- <div v-bind:title="title">我是一个块级元素</div> -->
<!-- 4.2绑定变量 简写为: -->
<div :title="title">我是一个块级元素</div>
<!-- 5.1给标签绑定事件 使用v-on:事件类型 -->
<!-- <button v-on:click="handler">点击我</button> -->
<!-- 5.2给标签绑定事件 简写为@ -->
<button @click="handler">点击我</button>
<!-- 6.{
{js表达式}} -->
{
{Boolean(str)}}
{
{str.split(",").reverse()}}
{
{str?'string':'null'}}
<!-- {
{if(str){console.log(str)}else{console.log('null')}}} -->
</div>
<script>
let vm = new Vue({
// el:'#app',
// 数据模型
data:{
msg:'hello vue2',
str:'hello',
content:'<p>文章标题</p><article>文章内容<a href="#">百度一下</a></article>',
title:'我div标签的提示说明'
},
methods:{
handler(){
console.log('我被点击了');
}
},
});
// vue实例与模版进行绑定
vm.$mount('#app');
setTimeout(()=>{
vm.msg = 'hello world'
},1000)
</script>
</body>
</html>
条件付きレンダリング
v-if
v-if (単独で使用可能)、式が true の場合、 v-if 属性を使用する要素がレンダリングされ、それ以外の場合は v-else を使用してレンダリングされます。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
</head>
<body>
<div id="app">
<!-- 条件渲染 v-if v-else-if v-else 或者使用v-show -->
<div v-if="type==='tel'">
<form>
<label for="tel">电话:</label>
<input type="text" id="tel" placeholder="请输入电话号码">
</form>
</div>
<div v-else-if="type==='email'">
<form>
<label for="email">邮箱:</label>
<input type="text" id="email" placeholder="请输入邮箱">
</form>
</div>
<div v-else>错误</div>
<button @click="toggle">切换</button>
<div v-show>显示内容</div>
</div>
<script>
new Vue({
el:'#app',
data:{
type:'tel',
isShow:false,
},
methods:{
toggle(){
if(this.type==='tel'){
this.type='email'
}else{
this.type='tel'
}
}
},
});
</script>
</body>
</html>
結果からわかるように、
v-if は条件付きブロック内のイベント リスナーとサブコンポーネントが確実に破棄され、切り替え中に適切に再作成されるため、「true」の条件付きレンダリングです。
v-if も遅延型です: 最初のレンダリングで条件が false の場合は何も行わず、条件が最初に true になるまで条件付きブロックはレンダリングを開始しません。
v-if はスイッチングのオーバーヘッドが高くなります。
v-if は要素/タグの追加または削除に対応します
条件を満たせば要素を追加 条件を満たさない場合は要素を削除
Vショー
v-show (CSSスタイルで表示属性を切り替える)、CSSスタイルを頻繁に切り替える、v-showを使用する
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
</head>
<body>
<div id="app">
<!-- 条件渲染 v-if v-else-if v-else 或者使用v-show -->
<div v-show="type==='tel'">
<form>
<label for="tel">电话:</label>
<input type="text" id="tel" placeholder="请输入电话号码">
</form>
</div>
<div v-show="type==='email'">
<form>
<label for="email">邮箱:</label>
<input type="text" id="email" placeholder="请输入邮箱">
</form>
</div>
<button @click="toggle">切换</button>
<div v-show>显示内容</div>
</div>
<script>
new Vue({
el:'#app',
data:{
type:'tel',
isShow:false,
},
methods:{
toggle(){
if(this.type==='tel'){
this.type='email'
}else{
this.type='tel'
}
}
},
});
</script>
</body>
</html>
結果からわかります。
v-show 要素は初期条件に関係なく常にレンダリングされ、CSS に基づいて単純に切り替えられます。
v-show では、初期レンダリングのオーバーヘッドが高くなります。
v-show は、要素の CSS スタイルの表示属性に対応します。
条件が満たされた場合、要素は表示されます。display:block。
条件が満たされない場合、要素は非表示になります。display:none。v-
show CSS スタイルを頻繁に切り替えるために使用されます。
リストのレンダリング
リストデータをレンダリングするために使用されます。v-for ディレクティブには、items 内のフォーム item の特別な構文が必要です。ここで、items はソース データ配列であり、item は反復される配列要素のエイリアスです。
鍵
Vue は要素を可能な限り効率的にレンダリングし、多くの場合、要素を最初からレンダリングするのではなく、既存の要素を再利用します。これを行うと、Vue が非常に高速になります。ただし、Vue に再利用させたくない場合もありますが、このとき、Vue は「これら 2 つの要素は完全に独立しているため、再利用しないでください。」を表現する方法を提供します。一意の値を持つキーを追加するだけです
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script> -->
<script src="../vue.js"></script>
</head>
<body>
<div id="app">
<ul>
<!-- <li v-for="(item,index) in animal">
{
{item}}---{
{message}}---{
{index}}
</li> -->
<!-- <li v-for="(item,index) of animal">
{
{item}}---{
{message}}---{
{index}}
</li> -->
<!-- <li v-for="(value,key,index) in obj">
{
{key}}---{
{value}}---{
{index}}
</li> -->
<li v-for="(value,key,index) of obj":key="index">
{
{key}}---{
{value}}---{
{index}}
</li>
</ul>
</div>
<script>
new Vue({
el:'#app',
data:{
message:'消息',
animal:['猴子','大象','老虎'],
obj:{
name:'terry',
age:18,
gender:'male'
}
},
methods:{},
})
</script>
</body>
</html>
スタイルバインディング
要素のクラス リストとインライン スタイルの操作は、データ バインディングの一般的なニーズです。これらは属性であるため、v-bind を使用してそれらを処理できます。式を通じて文字列の結果を計算するだけです。ただし、文字列の連結は面倒でエラーが発生しやすくなります。したがって、Vue では、クラスとスタイルに v-bind を使用する場合に特別な機能強化が行われました。文字列に加えて、式の結果の型はオブジェクトまたは配列にすることもできます。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<style>
</style>
</head>
<body>
<div id="app">
<!-- style绑定 动态绑定 -->
<div :style="{color:current}">{
{msg}}</div>
<div :style="styleObj1">{
{msg}}</div>
<div :style="[styleObj1,styleObj2]">{
{msg}}</div>
</div>
<script>
new Vue({
el:'#app',
data:{
msg:"hello Vue2",
current:'red',
styleObj1:{
fontSize:'24px',
backgroundColor:"pink",
},
styleObj2:{
width:'100px',
height:'100px',
}
},
methods:{},
})
</script>
</body>
</html>
クラスバインディング
要素のクラス リストとインライン スタイルの操作は、データ バインディングの一般的なニーズです。これらは属性であるため、v-bind を使用してそれらを処理できます。式を通じて文字列の結果を計算するだけです。ただし、文字列の連結は面倒でエラーが発生しやすくなります。したがって、Vue では、クラスとスタイルに v-bind を使用する場合に特別な機能強化が行われました。文字列に加えて、式の結果の型はオブジェクトまたは配列にすることもできます。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<style>
.four{
border: 1px solid cyan;
}
.active{
color: red;
font-size: 24px;
}
.error{
background: blue;
}
</style>
</head>
<body>
<div id="app">
<!-- 动态绑定类名 -->
<div class="four" :class="{active:isActive,error:hasError}">{
{msg}}</div>
<div class="four" :class="toggle">{
{msg}}</div>
<div class="four" :class="[isActive1,hasError1]">{
{msg}}</div>
</div>
<script>
new Vue({
el:'#app',
data:{
isActive:true,
hasError:false,
isActive1:'active',
hasError1:'error',
toggle:{
active:false,
error:true,
},
msg:"hello Vue2",
},
methods:{},
})
</script>
</body>
</html>
[インタビューの質問: 大規模プロジェクトではデータがオブジェクトではなく関数である理由]
コンポーネントは再利用可能なインスタンスです。コンポーネントを参照する場合、コンポーネント内のデータは通常のオブジェクトです。このコンポーネントを使用するすべてのユーザーが同じデータを参照するため、データ汚染が発生します。
return でラップされていないデータはプロジェクト内でグローバルに表示され、変数汚染の原因となります。return
でラップした後は、データ内の変数は現在のコンポーネントでのみ有効になり、他のコンポーネントには影響しません。
コンポーネントは複数のインスタンスの作成に使用される可能性があるため、コンポーネントを定義するときは、データを初期データ オブジェクトを返す関数として宣言する必要があります。データが純粋なオブジェクトのままであれば、すべてのインスタンスが同じデータ オブジェクトへの参照を共有することになります。データ関数を提供すると、新しいインスタンスが作成されるたびにデータ関数を呼び出すことができるため、元のデータ オブジェクトの完全に新しいコピーが返されます。