学习Vue,这一篇文章就够了(持续更新中)

  • A+
所属分类:Web前端
摘要

目录:点击文字跳转,点击背景或三角展开使用Vue的好处:文档传送门:Vue官网


Vue基础.js

目录:

Vue基础.js
语法:
指令
v-if :判断
v-for:循环
注意事项
1. 关于提高性能
v-on:事件绑定
修饰符
v-bind:动态绑定
2. 切换class属性
v-model:数据双向绑定
修饰符
过滤器
Vue的生命周期
Vue的Ajax异步请求:axios
Vue组件
入门案例
组件名
组件注册
组件通讯--父传子
Props
组件通讯--子传父
$emit
父子组件的双向数据绑定
插槽

点击文字跳转,点击背景或三角展开

使用Vue的好处:

  1. 解耦视图和数据
  2. 可复用的组件
  3. 前端路由技术
  4. 状态管理
  5. 虚拟Dom

文档传送门:Vue官网

语法:

el:挂载点

  1. el设置Vue实例的挂载的元素

  2. Vue会管理el选中的及其内部的后代元素(不用js或jq操作不了挂载点之外的)

  3. 可以使用选择器(dom也可以),但推荐使用id选择器

  4. 可以选择使用其他双标签,但不能是html和body(id或类选择器等则也可以选单标签)

注:在methods中,想用dom就可以this.$el(等价于document.getElementById("app"))

data:数据对象

  1. Vue中用到的数据都定义在data

  2. data中可以写复杂类型的数据

  3. 渲染复杂类型的数据时,遵守js的语法即可

computed:计算属性

  1. 用于预处理data中的属性
  2. 内容都是方法,相较于methods而言,其方法大多为名词
  3. 除非方法内的data值发生改变,会再次执行方法,否则方法只执行一次。执行后会将值进行缓存,下次调用直接从缓存中获取
  4. 例如用插值表达式使用时,是不需要在方法名后加()进行使用的

示例:

<div id="app">     {{fullName}} 他花了 {{totalMoney}} 巨资充实了自己 </div>	 <script>     var app = new Vue({         el: '#app',         data: {             finalName: "猫巷",             lastName: "Number One",             books: [{                 id: 1,                 name: "Thinking In Java",                 price: 40             },                     {                         id: 2,                         name: "On Java",                         price: 30                     },                     {                         id: 3,                         name: "深入理解计算机原理",                         price: 20                     },                     {                         id: 4,                         name: "现代操作系统",                         price: 10                     }                    ]         },         computed: {             fullName: function() {                 return this.finalName + " " + this.lastName             },             totalMoney: function() {                 let totalMoney = 0;                 for (let i = 0; i < this.books.length; i++) {                     totalMoney += this.books[i].price;                 }                 return totalMoney;             }         }     }); 

结果:学习Vue,这一篇文章就够了(持续更新中)

以上computed里的两个方法是简写,每个计算属性的方法都有一对getter和setter,取值时调用get(),赋值时调用set()。具体如下:

computed: {             fullName: { 				get: function(){ 					return this.finalName + " " + this.lastName 				}, 				set: function(newValue){ 					// newValue为此fullname的新赋的值 					// set方法通常都不写,因为computed为计算属性。因此通常也被称为只读属性 				}             },             fullName: { 				get: function(){ 					let totalMoney = 0;                 	for (let i = 0; i < this.books.length; i++) {                     	totalMoney += this.books[i].price;                 	}                 	return totalMoney; 				}, 				set: function(newValue){ 					// newValue为此fullname的新赋的值 					// set方法通常都不写,因为computed为计算属性。因此通常也被称为只读属性 				}             }         } 

methods:定义函数

  1. Vue中用到的方法都定义在methods中,且大多为动词形式
  2. 写法与普通方法无异,遵守js的语法即可
  3. 相较于computed,没有缓存,因此效率与computed相比较低

指令

插值表达式

挂载完对应元素后,可通过{{message}} 取出data中的message值

插值表达式之间支持简单Js,例如:

<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Vue 测试实例 - 菜鸟教程(runoob.com)</title> <script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script> </head> <body> <div id="app"> 	{{5+5}}<br> 	{{ ok ? 'YES' : 'NO' }}<br> 	{{ message.split('').reverse().join('') }} 	<div v-bind:id="'list-' + id">菜鸟教程</div> </div> 	 <script> new Vue({   el: '#app',   data: { 	ok: true,     message: 'RUNOOB', 	id : 1   } }) </script> </body> </html> 

效果如下:

10 YES BOONUR 菜鸟教程 (div的id为list-1) 

v-once:只展示初始值

使用v-once后,在渲染数据后,修改data的值,将不会再进行响应式更新。即只展示最初始的值

<div id="app">     <span v-once>{{message}}</span> </div> <script> 	new Vue({         el: "#app",         data:{             message: "hello vue"         }     }) </script> 

注意:v-once 后面不需要加 =""

v-pre:不解析语法

等价于<pre></pre>标签,例如:

<div id="app">     <span v-pre>{{message}}</span> </div> <script> 	new Vue({         el: "#app",         data:{             message: "hello vue"         }     }) </script> 

此时页面展示不是hello vue ,而是{{message}}

v-cloak:等待vue解析完数据后再显示页面

浏览器解析html文件是从上往下,有时候js代码卡住,用户就会先看见还未渲染的数据,如{{message}},而不是data中的hello vue,这体验是不好的。v-cloak原理是,加上v-cloak属性的元素,默认会看不见,等待vue渲染完毕后就会删除所有v-cloak属性,然后就自动展示出数据了。

v-text:设置文本值

  1. 设置双标签内的文本值
  2. 会覆盖原双标签里的文本值
  3. 内部可写表达式,也会识别为文本

v-html:设置innerHtml

  1. 设置双标签的innerHtml值
  2. 需要在内部写html语句采用v-html,只需要纯文本则用v-text。v-html写的会被解析为html语句

v-if :判断

根据 if 表达式后的值(true 或 false )来决定是否插入此元素

<div id="app">     <span v-if="flag">         <label>账号:</label>         <input type="text" id="account" placeholder="请输入账号">     </span>     <span v-else>         <label>邮箱:</label>         <input type="text" id="emails" placeholder="请输入邮箱">     </span>     <button type="button" @click="flag = !flag">切换登录</button> </div>  <script type="text/javascript">     new Vue({         el:"#app11",         data:{             flag : true         }     }) </script> 

点击按钮效果如图:学习Vue,这一篇文章就够了(持续更新中)学习Vue,这一篇文章就够了(持续更新中)

注意:表单里的值之所以没清空,是因为Vue底层采用的虚拟Dom元素Dom结构极为相似,且是对立情况出现的情况下,Vue底层会渲染同一个的虚拟Dom到页面上,再比较所渲染元素的具体区别(属性值等),进行页面的渲染。

虚拟Dom

浏览器解析Dom时,会将元素直接渲染到页面上。而Vue、React等底层采用了虚拟Dom,元素会先被Vue渲染到虚拟Dom中,在渲染到页面的同时会比较是否有可重复利用的元素,如果有 则渲染时直接复制原虚拟Dom的元素,再根据具体区别(属性值等)进行修改。这么做大大提升了页面渲染的效率。

总结:

  • 获取监听变化后生成的虚拟节点树
  • 与上一次虚拟DOM节点树进行比较
  • 找到差异的部分,渲染到真实的DOM节点上面
  • 更新视图

特殊情况需要解决虚拟Dom的复用时

上述例子,切换表单明显需要清空表单内的值,此时虚拟Dom带来了反面效果,可通过添加key属性来解决。

  • key值相同,代表可以复用
  • key值不同,代表不能被复用

示例:

	<div id="app11"> 		<span v-if="flag"> 			<label>账号:</label> 			<input type="text" id="account" placeholder="请输入账号" key="username"> 		</span> 		<span v-else> 			<label>邮箱:</label> 			<input type="text" id="emails" placeholder="请输入邮箱" key="email"> 		</span> 		<button type="button" @click="flag = !flag">切换登录</button> 	</div> 

上述例子label没写key,所以可被复用,input二者的key不同,即不可复用。在点击按钮时,input内的值自然就被清空了

v-show:是否展示此元素

  1. 当显示条件为true时:

    v-ifv-show效果相同

  2. 当显示条件为false时:

    v-if不渲染dom元素,而v-show仍然渲染;渲染时会加上行内样式:style = "display: none"

当数据要在显示隐藏间频繁切换时,使用v-show

当数据只有一次切换根据条件及进行渲染时使用v-if

v-for:循环

常用场景:

  1. 数组集合循环

    <div id="app10">     <ul>      	<!--  			1.item为值,index为索引 			2.就写一个默认就为item,即是值 			3.括号可省略但不建议 		-->            <li v-for="(item,index) in arr">{{item}}==={{index}}</li>     </ul> </div>  <script type="text/javascript">     new Vue({         el: "#app10",         data: {             arr: [1,2,3,4,5]         },     }) </script> 

    结果:学习Vue,这一篇文章就够了(持续更新中)

  2. 遍历Json形式的数据(超好用)

    <div id="app10">     <ul>         <!--  			1.注意value和key的顺序是反的,先写的始终是值value,后写的是索引index或键key 			2.其他点同上 		-->            <li v-for="(value,key) in person">{{key}}==={{value}}</li>     </ul> </div>  <script type="text/javascript">     new Vue({         el: "#app10",         data: {             person: {                 id:1001,                 username:"admin",                 password:"123"             }         },     }) </script>   

    结果:学习Vue,这一篇文章就够了(持续更新中)

  3. json集合(两者结合)

    <div id="app10">     <table cellspacing="1" border="1">         <tr>             <th>编号</th>             <th>id</th>             <th>产品名称</th>             <th>产品价格</th>         </tr>         <tr v-for="(product,index) in persons"> 			<td>{{ index + 1 }}</td>             <td v-for="value in product">{{ value }}</td>                      </tr>     </table> </div>  <script type="text/javascript">     new Vue({         el: "#app10",         data: {             persons: [                 {id: 1001, proName: "手机", proMoney: "123"},                 {id: 1002, proName: "平板", proMoney: "1090"},                 {id: 1003, proName: "电脑", proMoney: "2222"},                 {id: 1004, proName: "摄像机", proMoney: "3041"},             ]         },     }) </script>   

    结果:学习Vue,这一篇文章就够了(持续更新中)

注:获取对象索引还可以:v-for="(value, key, index) in Person"

注意事项

1. 关于提高性能

官方推荐我们在使用v-for时,给对应的元素或组件加上:key,即绑定key属性。且绑定的属性值为当前元素(item)

原因:这么做其实与其虚拟Dom的Diff算法有关

Diff算法:Diff算法的作用是用来计算出 Virtual DOM (即虚拟Dom) 中被改变的部分,然后针对该部分进行原生DOM操作,而不用重新渲染整个页面

案例:

页面使用ul-li标签展示数组arr=[A,B,C,D,E],此时往第三个位置插入个F元素(即创建新元素)。

此时高效率做法应是直接往第三个位置插入F元素①,而虚拟Dom采用的是极低效率的“将C变成F,D变成C,E变成D,创建新li标签且值为E“。数据更新后,采用Diff算法渲染时会”判断不同的数量,再一个一个更替不同的地方“②。此做法会提升消耗,降低效率

此时,若在遍历时加入key属性,且与单个遍历对象item一一绑定,遍历时虚拟Dom会优先将keyitem对应的值进行绑定渲染,再将新创建的(无对应key值)元素进行插入,即可达到①的效果

用代码总结就是:<ul><li v-for="item in arr" :key="item"> </li></ul>

注意:

  1. 绑定index是没用的,因为新增或删除元素时,index会发生变化,此时固定的item对应的index就会发生改变。
  2. 绑定item的前提是保证arr数组中的元素是唯一(不重复的)
2. 关于响应布局实时渲染

对于数组,调用push、pop、shift、unshift、splice、sort、reverse等方法,都可以达到响应式布局。

但是arr[2] = "aaa"这种直接通过索引下标修改元素的,Vue是没有监听的,因此不会实时渲染到页面上。

通常解决方式有两种:

  1. arr.splice(2, 1, "aaa");
  2. Vue.set(arr, 2, "aaa"), 即Vue(要修改的对象,要修改的索引值,修改后的值)

v-on:事件绑定

  1. 指令作用为:为元素绑定事件
  2. 事件名不需要写on (v-on:click)
  3. 指令可简写成@(@click)
  4. 绑定的方法定义在methods中
  5. 方法内部可通过this访问定义在data中的属性
  1. 当绑定的方法没有参数时,括号可加可不加。

  2. this中有很多$开头的属性。如$event表示原生dom的事件。this.$el = document.getElementById("app")

  3. 使用@click后想要获取点击本事件本体,有两种方式:

    ​ a. this.$refs.ref可获得el绑定的所有带有ref属性的标签,再通过下标即可获取对应元素。

    ​ b. 通过event.currentTarget获取本身标签元素this

事例:绑定methods中的方法名

<div id="example-2">   <!-- `greet` 是在下面定义的方法名,不写括号时,默认方法的`第一个参数`可接收原生event事件-->   <button v-on:click="greet">Greet</button> </div> <script>     var example2 = new Vue({       el: '#example-2',       data: {         name: 'Vue.js'       },       // 在 `methods` 对象中定义方法       methods: {         greet: function (event) {           // `this` 在方法里指向当前 Vue 实例           alert('Hello ' + this.name + '!')           // `event` 是原生 DOM 事件           if (event) {             alert(event.target.tagName)           }         }       }     }) </script> 

事件数量:

Dom有的事件Vue基本都有,总的事件如图:

学习Vue,这一篇文章就够了(持续更新中)

修饰符

修饰符是以半角句号 . 指明的特殊后缀,用于指出一个指令应该以特殊方式绑定。例如.prevent 修饰符告诉 v-on 指令对于触发的事件调用 event.preventDefault(),即阻止元素的默认行为。event.stopPropagation()阻止事件冒泡等。常用的修饰符有以下几种:

  • .stop - 阻止冒泡
  • .prevent - 阻止默认事件
  • .capture - 阻止捕获
  • .self - 只监听触发该元素的事件
  • .once - 只触发一次
  • .left - 左键事件
  • .right - 右键事件
  • .middle - 中间滚轮事件
事例
<!-- 阻止单击事件继续传播 --> <a v-on:click.stop="doThis"></a>  <!-- 提交事件不再重载页面 --> <form v-on:submit.prevent="onSubmit"></form>  <!-- 修饰符可以串联 --> <a v-on:click.stop.prevent="doThat"></a>  <!-- 只有修饰符 --> <form v-on:submit.prevent></form>  <!-- 添加事件监听器时使用事件捕获模式 --> <!-- 即内部元素触发的事件先在此处理,然后才交由内部元素进行处理 --> <div v-on:click.capture="doThis">...</div>  <!-- 只当在 event.target 是当前元素自身时触发处理函数 --> <!-- 即事件不是从内部元素触发的 --> <div v-on:click.self="doThat">...</div>  <!-- 点击事件将只会触发一次 --> <a v-on:click.once="doThis"></a>  <!-- 滚动事件的默认行为 (即滚动行为) 将会立即触发 --> <!-- 而不会等待 `onScroll` 完成  --> <!-- 这其中包含 `event.preventDefault()` 的情况 --> <!-- 这个 .passive 修饰符尤其能够提升移动端的性能 --> <div v-on:scroll.passive="onScroll">...</div> 

注:

  1. 使用修饰符时,顺序很重要;相应的代码会以同样的顺序产生。因此,用 v-on:click.prevent.self 会阻止所有的点击,而 v-on:click.self.prevent 只会阻止对元素自身的点击。
  2. 不要把 .passive.prevent 一起使用,因为 .prevent 将会被忽略,同时浏览器可能会向你展示一个警告。请记住,.passive 会告诉浏览器你不想阻止事件的默认行为。

v-bind:动态绑定

v-bind 被用来响应地更新 HTML 属性,可简写为一个冒号:

例子:

1. 用以挂载data中的数据

<div id="app">     <pre>     	<a v-bind:href="url">菜鸟教程</a>     </pre> </div>      <script> new Vue({   el: '#app',   data: {     url: 'http://www.runoob.com'   } }) </script> 

注意:插值表达式无法直接赋值标签的属性值。

2. 切换class属性

可根据布尔值来确定是否拼接class属性

固定的class可直接在前面定义,即 class="class1",因为:class是拼接上去的,不会覆盖原来

a. 传入数组,根据布尔值进行是否拼接class属性
<html> 	<head> 		<meta charset="utf-8"> 		<title>v-bind</title> 	</head> 	<body> 		<script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script>  		<div id="app"> 			<div v-bind:class="{'active': isActive,'line':isLine}"> 				v-bind:class 指令 			</div> 		</div>  		<script> 			new Vue({ 				el: '#app', 				data: { 					isActive: true, 					isLine:false 				} 			}); 		</script> 	</body> </html> 

效果如图:学习Vue,这一篇文章就够了(持续更新中)

上述例子等价于:

<html> 	<head> 		<meta charset="utf-8"> 		<title>v-bind</title> 	</head> 	<body> 		<script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script>  		<div id="app">             <!-- 也可以指向method或computed --> 			<div v-bind:class="getClasses()"> 				v-bind:class 指令 			</div> 		</div>  		<script> 			new Vue({ 				el: '#app', 				data: { 					isActive: true, 					isLine: false 				}, 				methods: { 					getClasses: function() { 						return { 							'active': this.isActive, 							'line': this.isLine 						}; 					} 				} 			}); 		</script> 	</body> </html> 
b. 与v-model结合使用,达到切换class效果
<html> <head> <meta charset="utf-8"> <title>Vue 测试实例 - 菜鸟教程(runoob.com)</title> </head> <style>     .class1{       background: #444;       color: #eee;     } </style> <body> <script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script>  <div id="app">   <label for="r1">修改颜色</label><input type="checkbox" v-model="use" id="r1">   <br><br>   <div v-bind:class="{'class1': use}">     v-bind:class 指令   </div> </div>      <script> new Vue({     el: '#app',   data:{       use: false   } }); </script> </body> </html> 

效果: 学习Vue,这一篇文章就够了(持续更新中),点击选择框,下方div背景会跟随选择框的状态改变

c. 传入数组,批量绑定属性
<div id="app">     <div class="test1" v-bind:class="[test2, test3]">         v-bind:class 指令     </div> </div>  <script>     new Vue({         el: '#app',         data: {             test2: "class2",             test3: "class3"         }     }); </script> 

结果:学习Vue,这一篇文章就够了(持续更新中)

3. 动态绑定style

实例:

<div id="app">     <!-- 格式: :style="key(属性名): value(属性值)" -->     <h2 :style="{fontSize: '5px'}">动态绑定style</h2>     <h2 :style="{fontSize: finalSize+'px'}">动态绑定style</h2> </div>  <script>     var app = new Vue({         el: '#app',         data: {             finalSize: 5         }     }); </script> 

结果:学习Vue,这一篇文章就够了(持续更新中)

同上,也可以传入数组,进行批量设值

v-model:数据双向绑定

用来在 inputselecttextareacheckboxradio等表单控件元素上创建双向数据绑定,根据表单上的值,自动更新绑定的元素的值

input示例

<div id="app">     <p>{{ message }}</p>     <input v-model="message"> </div>      <script> new Vue({   el: '#app',   data: {     message: 'Runoob!'   } }) </script> 

radio示例

<div id="app">     <label>         <input type="radio" value="男" v-model="sex" />男     </label>     <label>         <input type="radio" value="女" v-model="sex" />女     </label><br>     性别是: {{ sex }} </div> <script>     new Vue({         el: "#app",         data: {             sex: "女"         }     }) </script> 

结果:学习Vue,这一篇文章就够了(持续更新中)

checked示例

<div id="app">     <input type="checkbox" value="篮球" v-model="hobbies">篮球     <input type="checkbox" value="足球" v-model="hobbies">足球     <input type="checkbox" value="羽毛球" v-model="hobbies">羽毛球     <input type="checkbox" value="乒乓球" v-model="hobbies">乒乓球     <p>你的爱好有:{{ hobbies}}</p> </div> <script>     new Vue({         el: "#app",         data: {             hobbies:['篮球', '足球']         }     }) </script> 

结果:学习Vue,这一篇文章就够了(持续更新中)

值绑定

示例:

<div id="app">     <label v-for="item in hobbies" :for="item">         <input type="checkbox" :id="item" :value="item" v-model="myHobbies" />     </label>     <p>你的爱好有:{{ myHobbies}}</p> </div> <script>     new Vue({         el: "#app",         data: {             hobbies: ['篮球', '足球', '乒乓球', '羽毛球', '保龄球', '高尔夫球'],             myHobbies:[]         }     }) </script> 

结果:学习Vue,这一篇文章就够了(持续更新中)

修饰符

.lazy

在默认情况下,v-model 在每次 input 事件触发后将输入框的值与数据进行同步。你可以添加 lazy 修饰符,从而转为在 change 事件_之后_进行同步:

<!--  	在“change”时而非“input”时更新  	即敲下回车或表单失焦后触发,而不是敲一下触发一次事件,降低事件使用频率 --> <input v-model.lazy="msg"> 
.number

如果想自动将用户的输入值转为数值类型,可以给 v-model 添加 number 修饰符(用户只能输入数字类型):

<input v-model.number="age" type="number"> 

这通常很有用,因为即使在 type="number" 时,HTML 输入元素的值也总会返回字符串。如果这个值无法被 parseFloat() 解析,则会返回原始的值。

.trim

如果要自动过滤用户输入的首尾空白字符,可以给 v-model 添加 trim 修饰符:

<input v-model.trim="msg"> 

过滤器

用作一些常见的文本的格式化,并且多个过滤器可串联{{ message | filterA | filterB }}

格式:

<!-- 在两个大括号中 --> {{ message | capitalize }}  <!-- 在 v-bind 指令中 --> <div v-bind:id="rawId | formatId"></div> 

示例

插值表达式以及class属性的过滤(首个字母大写):

<!-- 过滤器 --> <div id="app9"> 	<div v-bind:class="clsTest|clsTest"> 		{{message | toLowerCase}} 	</div> </div>  <script type="text/javascript"> 			new Vue({ 				el:"#app9", 				data:{ 					message:"runoob!", 					clsTest:"class" 				}, 				filters:{ 					toLowerCase:function(value){ 						return value.charAt(0).toUpperCase() + value.substr(1) 					}, 					clsTest:function(cls){ 						return cls+"1"; 					} 				} 			}) </script> 

结果为:

<div class="class1">Runoob</div> 

过滤器是 JavaScript 函数,因此可以接受参数:

{{ message | filterA('arg1', arg2) }} 

Vue的生命周期

整体流程图:

学习Vue,这一篇文章就够了(持续更新中)

文字解析

Vue 实例从创建到销毁的过程,就是生命周期。从开始创建、初始化数据、编译模板、挂载Dom→渲染、更新→渲染、销毁等一系列过程,称之为 Vue 的生命周期。

Vue一共有8中生命周期(4种状态的前后):分别为:

  • 创建Vue实例前 ---beforeCreate
  • 创建Vue实例后 ---created
  • 挂载前 ---beforeMount
  • 挂载后 ---mounted
  • 数据更新前 ---beforeUpdate
  • 数据更新后 ---update
  • 实例销毁前 ---beforeDestroy
  • 实例销毁后 ---destroyed

其中,数据的渲染在mounted阶段渲染完毕。

每个过程对应一个事件钩子(callHook()),对应一个函数的执行,如 挂载前会执行beforeMount()方法

实例解析

<div id="app11">     {{ message }} </div>  <script type="text/javascript">     var app = new Vue({         el: "#app11",         data: {             message: "Hello Vue.js!"         },         beforeCreate: function () {             showDate("vue实例创建前",this);         },         created: function () {             showDate("vue实例创建后",this);         },         beforeMount: function () {             showDate("挂载前",this);         },         mounted: function () {             showDate("挂载后",this);         },         beforeUpdate: function () {             showDate("数据更新前",this);         },         updated: function () {             showDate("数据更新后",this);         },         beforeDestroy: function () {             showDate("vue实例销毁前",this);         },         destroyed: function () {             showDate("vue实例销毁后",this);         }     });      /** 展示真实dom结构 **/     function realDom() {         console.log("真实dom结构:"+document.getElementById("app11").innerHTML)     }      /** 展示data的数据以及将要挂载的对象 **/     function showDate(process,obj) {         console.log(process);         console.log("data数据:"+obj.message);         console.log("挂载的对象:");         console.log(obj.$el);         realDom();         console.log('-------------------')         console.log('-------------------')     }     app.message="good"     app.$destroy(); </script> 

结果:

  1. 当app.message="good"作用,app.$destroy()注释时:
vue实例创建前 data数据:undefined 挂载的对象: 	undefined 真实dom结构:     {{ message }} ------------------- ------------------- vue实例创建后 data数据:Hello Vue.js! 挂载的对象: 	undefined 真实dom结构:     {{ message }} ------------------- ------------------- 挂载前 data数据:Hello Vue.js! 挂载的对象: 	<div id="app11"> {{ message }} </div> 真实dom结构:     {{ message }} ------------------- ------------------- 挂载后 data数据:Hello Vue.js! 挂载的对象: 	<div id="app11"> good </div> 真实dom结构:     Hello Vue.js! <!-- 注:此时这里挂载对象为“good”是因为message已经被赋值,但挂载上去的仍是“Hello Vue.js!”,原因是因为赋值一定会有一个值的变化的过程,而这个过程在Vue中发生在Mounted阶段,即挂载后 --> ------------------- ------------------- 数据更新前 data数据:good 挂载的对象: 	<div id="app11"> good </div> 真实dom结构:     Hello Vue.js! ------------------- ------------------- 数据更新后 data数据:good 挂载的对象: 	<div id="app11"> good </div> 真实dom结构:     good ------------------- ------------------- 
  1. 当app.$destroy()作用,app.message="good"注释时:
vue实例创建前 data数据:undefined 挂载的对象: 	undefined 真实dom结构:     {{ message }} ------------------- ------------------- vue实例创建后 data数据:Hello Vue.js! 挂载的对象: 	undefined 真实dom结构:     {{ message }} ------------------- ------------------- 挂载前 data数据:Hello Vue.js! 挂载的对象: 	<div id="app11"> {{ message }} </div> 真实dom结构:     {{ message }} ------------------- ------------------- 挂载后 data数据:Hello Vue.js! 挂载的对象: 	<div id="app11"> Hello Vue.js! </div> 真实dom结构:     Hello Vue.js! ------------------- ------------------- vue实例销毁前 data数据:Hello Vue.js! 挂载的对象: 	<div id="app11"> Hello Vue.js! </div> 真实dom结构:     Hello Vue.js! ------------------- ------------------- vue实例销毁后 data数据:Hello Vue.js! 挂载的对象: 	<div id="app11"> Hello Vue.js! </div> 真实dom结构:     Hello Vue.js! <!-- 之所以销毁前后与之前没变化,是因为destroy只是销毁了vue对象,然而vue已渲染、产生的效果是不会消失的。   --> ------------------- ------------------- 

Vue的Ajax异步请求:axios

通用写法格式:

// 发送 POST 请求 axios({   method: 'post',   url: '/user/12345',   data: {     firstName: 'Fred',     lastName: 'Flintstone'   }.then(function(){...}).catch(function(){...}) }); 

在axios中的this无法指代vue实例,拿取不到vue中data的数据。因此可在axios定义上方定义类似:

var _this = this; 来获取vue实例对象。然后获得user对象可通过_this.user获取

GET 请求

axios.get('/user?ID=12345') .then(function (response) { // then方法等价于success方法,Ajax正确执行后的回调函数     console.log(response); }) .catch(function (error) { // catch方法等价于error方法,Ajax执行出现异常后的回调函数     console.log(error); });  // 上面的请求也可以这样做(get的参数必须加params) axios.get('/user', {     params: {         ID: 12345     } }) .then(function (response) {     console.log(response); }) .catch(function (error) {     console.log(error); }); 

POST 请求

// post请求不需要加params,直接花括号里加Json数据 axios.post(‘/user’, { firstName: ‘Fred’, lastName: ‘Flintstone’ }) .then(function (response) { console.log(response); }) .catch(function (error) { console.log(error); });  <!-- =========== 另一种例子 ============== -->  var app = new Vue({         el: "#app1",         data: {             user: {                 username: "",                 password: ""             }         },         methods: {             reg: function () {                 var _this = this;                 axios.post('/sshTest/user/save',_this.user).then(function (response) {                     console.log(response);                 }).catch(function (message) {                     console.log(message);                 })             }         }     }) 

多个并发请求

function getUserAccount() { 	return axios.get(‘/user/12345’); } function getUserPermissions() { 	return axios.get(‘/user/12345/permissions’); } // axios.all()方法里传入Ajax方法的数组 axios.all([getUserAccount(), getUserPermissions()]) .then(axios.spread(function (acct, perms) { // 两个请求现在都执行完成 })); 

axios(config) 写法

// 发送 POST 请求 axios({   method: 'post',   url: '/user/12345',   data: {     firstName: 'Fred',     lastName: 'Flintstone'   } }); 

使用 application/x-www-form-urlencoded 请求头

import qs from 'qs'; const data = { 'bar': 123 }; const options = {   method: 'POST',   headers: { 'content-type': 'application/x-www-form-urlencoded' },   data: qs.stringify(data),   url, }; axios(options); 

Vue组件

入门案例

<div id="app">         <button-counter></button-counter> </div>  <script>     // 定义一个名为 button-counter 的新组件     Vue.component('button-counter', {         data() {             return {                 count: 0             }         },         template: '<button @click="count++">我点击了 {{ count }} 次</button>'     }) 	/* 以上也可以等价于以下 	// 创建组件构造器对象     const cpn = Vue.extend({         data() {             return {                 count: 0             }         },         template: '<button @click="count++">我点击了 {{ count }} 次</button>'     });     // 组件注册     Vue.component('button-counter',cpn) 	*/          new Vue({ el: '#app' }) </script> 

效果如图:学习Vue,这一篇文章就够了(持续更新中) ,点击按钮则count+1. 且在页面上是看不到button绑定的事件的。

注意:

  1. 例中的 ”button-counter" 即为组件名,自定义组件名遵循规则 (字母全小写且必须包含一个连字符)。这会避免和当前以及未来的 HTML 元素相冲突。
  2. 组件是可以重复使用的,组件内的data相互独立互不影响
  3. data必须是个函数,而不能是对象(Vue的规定,以此来保证每个组件的data独立)
  4. data函数的返回是个对象(即要{}包裹)

组件名

定义组件名的方式有两种:

使用 kebab-case(推荐)
Vue.component('my-component-name', { /* ... */ }) 

当使用 kebab-case (短横线分隔命名) 定义一个组件时,你也必须在引用这个自定义元素时使用 kebab-case,例如 <my-component-name>

使用 PascalCase
Vue.component('MyComponentName', { /* ... */ }) 

当使用 PascalCase (首字母大写命名) 定义一个组件时,在JS中引用两种命名法都可以使用。但是,HTML不区分大小写,因此只能使用 kebab-case

模板分离

在实际开发中,直接写template='<div>...</div>'一个是可读性不好,一个是没有复用性,还有就是在写字符串时许多开发工具并不会语法提示。因此就有了模板分离:将HTML字符串用特殊标签包住后,直接写在其内部,引用其id给template即可直接使用

<div id="app">     <my-button></my-button> </div>   <template id="test"> 	<div>         <input type='text'>         <input type='button' value="模板">         <input type='checkbox' checked="checked">模板显示     </div> </template>  <script>     Vue.component('MyButton', {         // 引用其模板的id         template: test     })      new Vue({el: '#app'}) </script> 

效果:学习Vue,这一篇文章就够了(持续更新中)

  1. 可用<template></template>与<script type="text/x-template" id="test"></script>进行包裹,效果一样,更推荐前者
  2. 模板不用写在Vue实例所挂载的内部

组件注册

全局注册

Vue.component('my-component-name', {   // ... 选项 ... }) 

这些组件是全局注册的。它们在注册之后可以用在任何新创建的 Vue 实例 (new Vue) 的模板中。比如:

Vue.component('component-a', { /* ... */ }) Vue.component('component-b', { /* ... */ }) Vue.component('component-c', { /* ... */ })  new Vue({ el: '#app' }) <div id="app">   <component-a></component-a>   <component-b></component-b>   <component-c></component-c> </div> 

在所有子组件中也是如此,也就是说这三个组件在各自内部也都可以相互使用。

局部注册

全局注册往往是不够理想的。比如,如果你使用一个像 webpack 这样的构建系统,全局注册所有的组件意味着即便你已经不再使用一个组件了,它仍然会被包含在你最终的构建结果中。这造成了用户下载的 JavaScript 的无谓的增加。

在这些情况下,可以通过一个普通的 JavaScript 对象来定义组件。然后在 Vue实例内用components 选项中定义你想要使用的组件:

 <div id="app">     <!-- 标签名不区分大小写,因此必须采用kebab-case风格 -->     <component-a></component-a> </div>  <script>     // JS定义对象     var ComponentA = {         data() {             return {                 count: 0             }         },         template: '<button @click="count++">我点击了 {{ count }} 次</button>'     }      new Vue({         el: '#app',         components: {             // 等价于 "CompunentA" : ComponentA             // 注意,全局注册的组件不能写在这,会报ComponentA is not define             ComponentA         }     }) </script> 

​ 对于 components 对象中的每个 property 来说,其 property 名就是自定义元素的名字,其 property 值就是这个组件的选项对象。

注意局部注册的组件在其子组件中不可用。例如,如果希望 ComponentAComponentB 中可用,则需要这样写:

var ComponentA = { /* ... */ }  var ComponentB = {   components: {     'component-a': ComponentA   },   // ... } 

或者如果你通过 Babel 和 webpack 使用 ES6 模块,那么代码看起来更像:

import ComponentA from './ComponentA.vue'  export default {   components: {     ComponentA   },   // ... } 

在 ES6 中,在对象中放一个类似 ComponentA 的变量名其实是 ComponentA: ComponentA 的缩写,即这个变量名同时是:

  • 用在模板中的自定义元素的名称
  • 包含了这个组件选项的变量名

组件通讯--父传子

Props

写在props中的值,接收数据通过组件上的同名属性接收,使用方式与在data中无异(因此可使用v-bind进行数据绑定)。

示例:

<div id="app">     <!--          posts为Vue实例中data的数据         v-bind:post,:arr绑定post,arr属性值,通过props传入。使用时与从data中取值无异         在组件上使用vue实例的方法要加.native,声明是本页面的方法,否则只能调用Vue中的方法 	-->     <component-a v-for="post in posts" @click.native="vueFun(post.id)" :post="post" :arr="[1,2,3,4,5]"></component-a> </div>   <script>     var ComponentA = {         data() {             return {                 count: 0             }         },         props: ["post","arr"],         template:         '<ul><li @click.stop="componentFun(post.title)" v-for="(item, index) in arr">{{item}} {{post.title}} {{index + count}}</li></ul>',         methods: {             componentFun(obj) {                 console.log(obj)             }         }     }      new Vue({ 			el: '#app', 			components: { 				ComponentA 			}, 			data: { 				posts: [ 						{ id: 1, title: 'My journey with Vue' }, 						{ id: 2, title: 'Blogging with Vue' }, 						{ id: 3, title: 'Why Vue is so fun' } 					] 			}, 			methods: { 				vueFun(obj) { 					showData(obj) 				} 			} 		})      		function showData(obj) { 			console.log(obj) 		} </script> 

结果:学习Vue,这一篇文章就够了(持续更新中),点击后

data与props用法相似,组件私有的数据、可读可写的写在data中。只读不可写的写在props中

Props的命名
  1. 由于HTML是大小写不敏感的,使用标签的属性统一采用小写。
  2. 对于Props中驼峰命名的数据,需要使用其等价的 kebab-case (短横线分隔命名)

建议:在JS中采用驼峰命名,属性使用kebab-case(短横线分隔命名)

Props的类型限定

简略写法(数组):

props: ['title', 'likes', 'isPublished', 'commentIds', 'author'] 

限定类型写法(对象):

props: {     title: String,     likes: Number,     isPublished: Boolean,     commentIds: Array,     author: Object,     callback: Function,     contactsPromise: Promise // or any other constructor } 

使用错误类型时页面不会报错,但控制台会报错。

注意[]{}。简略写法必须加引号'',限定类型写法可省略。

Props语法
Vue.component('my-component', {   props: {     // 基础的类型检查     propA: Number,     // 多个可能的类型     propB: [String, Number],     // 必填的字符串     propC: {       type: String,       required: true     },     // 带有默认值的数字     propD: {       type: Number,       default: 100     },     // 带有默认值的对象     propE: {       type: Object,       // 对象或数组默认值必须从一个工厂函数获取       default: function () {         return { message: 'hello' }       }     },     // 自定义验证函数     propF: {       validator: function (value) {         // 这个值必须匹配下列字符串中的一个         return ['success', 'warning', 'danger'].indexOf(value) !== -1       }     }   } }) 

nullundefined 会通过任何类型验证

Props类型检查的种类

type 可以是下列原生构造函数中的一个:

  • String
  • Number
  • Boolean
  • Array
  • Object
  • Date
  • Function
  • Symbol

额外的,type 还可以是一个自定义的构造函数,并且通过 instanceof 来进行检查确认。例如,给定下列现成的构造函数:

function Person (firstName, lastName) {   this.firstName = firstName   this.lastName = lastName } 

你可以使用:

Vue.component('blog-post', {   props: {     author: Person   } }) 

来验证 author prop 的值是否是通过 new Person 创建。

Props的单向数据流

所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外变更父级组件的状态,从而导致你的应用的数据流向难以理解。

每次父级组件发生变更时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你应该在一个子组件内部改变 prop。如果你这样做了,Vue 会在浏览器的控制台中发出警告(Avoid mutating a prop directly since the value will be overwritten whenever the parent component)。

在两种情况下,我们很容易忍不住想要去修改prop中数据:

  1. Prop作为初始值传入后,子组件想把它当作局部数据来用;
  2. Prop作为原始数据传入,由子组件处理成其它数据输出。

对这两种情况,正确的应对方式是:

  1. 在子组件中定义一个局部变量,并用prop的值初始化它:
props: ['initialCounter'], data: function () {   // this可调用props中的属性值   return { counter: this.initialCounter } } 
  1. 定义一个计算属性,处理prop的值并返回:
props: ['size'], computed: {   normalizedSize: function () {     return this.size.trim().toLowerCase()   } } 

在JavaScript中对象和数组是引用类型,指向同一个内存空间,如果prop是一个对象或数组,在子组件内部改变它会影响父组件的状态

非Props的Attribute属性

当在组件上写有Attribute属性,却在props中没有进行定义(接收数据),即为非Props的Attribute属性

因为显式定义的 prop 适用于向一个子组件传入信息,然而组件库的作者并不总能预见组件会被用于怎样的场景。这也是为什么组件可以接受任意的 attribute,而这些 attribute 会被添加到这个组件的根元素上。

实例:

<div id="app">     <component-b test type="text" class="componentClass" style="margin-left: 50px;">		</component-b> </div>  <script>     var ComponentB = {         template:'<input type="date" class="myClass" style="width : 500px">'     } </script> 

结果:学习Vue,这一篇文章就够了(持续更新中)

  1. test可以是任意属性,可以是hiden、disabled等具有实际意义属性,或是test这种自定义属性。
  2. 当组件与模板根元素有相同属性type时,组件的属性值会覆盖模板根元素的属性值。
  3. classstyle比较特殊,不会覆盖原来的属性值,而是拼接上去。
  4. 如果不想让组件上的属性影响到模板根元素,可设置禁用Attribute继承

禁用Attribute继承

不希望组件的根元素继承 attribute,你可以在组件的选项中设置 inheritAttrs: false

<div id="app">     <component-a type='text' ></component-a> </div>  <script> 	var ComponentA = {         template:'<input class="myClass" type="date" style="width : 500px">',         // 不继承任何组件上传来的属性         inheritAttrs: false     } </script> 

结果:学习Vue,这一篇文章就够了(持续更新中)

  1. type=date不会被type=text覆盖
  2. inheritAttrs对class与style无效,仍然会继续拼接

$attrs

作用:在指定元素位置传递attribute属性。

使用v-bind='$attrs'非Props的Attribute属性绑定到指定的元素上,而不是只能绑定在根元素上

父组件想传值给曾子组件时,如果使用inheritAttrs,子组件会有很多无关的属性在组件上。此时禁用子组件的Attribute继承后,使用$attrs子组件上使用即可达到传值效果。

inheritAttrs是会覆盖相同的属性值的,但$attrs是不会覆盖的(value会覆盖?) -lyx todo

<body>     <div id="app">         <component-a type='submit' width="20px"></component-a>     </div>      <script>         var ComponentB = {             template: ` 			<div> <!-- 在此位置使用type='submit',width因为已经有了,$attrs无法覆盖原属性值,因此width仍然是30 --> 				<input width="30px" v-bind="$attrs" value="测试">      	   </div> 			`,             inheritAttrs: false         }          var ComponentA = {             components:{                 ComponentB             },             template: ` 				<div> 					<input class="myClass" type="date" style="width : 500px"> 					<!-- 在组件上使用v-bind='$attrs' --> 					<component-b v-bind="$attrs"></component-b>  		       </div>`,             // 不继承任何组件上传来的属性             inheritAttrs: false         }          new Vue({el:"#app",components:{ComponentA}})     </script> 

结果:学习Vue,这一篇文章就够了(持续更新中)

$listener:事件监听器

<div id="app">     A{{msg}}     <my-button :msg="msg" @todo="handleClick"></my-button> </div>  <script>     let vm = new Vue({         el: '#app',         data: {             msg: '100'         },         methods: {             handleClick() {                 console.log('点击事件')             }         },         components: {             'MyButton': {                 // 这里的v-on='$listeners' 与 v-bind='$attrs'异曲同工                 template: `<div>B<my-radio v-on="$listeners"></my-radio></div>`,                 components: {                     'MyRadio': {                         template: `<div @click="$listeners.todo">C</div>`,                     }                 },                 created() {                     console.log(this.$listeners)                 }             },         }     }) </script> 

注:

  1. 爷孙组件传递规则,同$attrs传递规则一样,逐级传递

  2. v-bind='$attrs'一样,直接使用v-on='$listeners'也可以把所有原生事件附加在指定氧元素上。自定义事件由于不知道处罚方式(event = click or blur 等),所以无法触发。

  3. 触发指定指定的事件有两种情况:

    <my-button @todo="handleClick" @click='clickFun'></my-button> 
    1. 触发原生事件:此时要在附加的元素上添加@click="$listeners.click"即可添加事件

      注意:click为触发的事件event

    2. 触发自定义事件:@click="$listeners.todo",@event='$listeners.点击事件名'

组件通讯--子传父

$emit

格式:$emit.("父组件方法名", 传给父组件的值)

作用:可触发指定父组件的方法,父组件会监听子组件,而触发条件就是$emit

我们开发一个子组件,有时他需要与父级组件沟通,如:通知父组件数据变化、根据子组件给父组件赋值等。

示例:

<div id="app">     <div :style="{ fontSize: finalSize + 'em' }">         <!-- 自定义事件 -->         <component-a @sendvalue='getChildValue' @big='finalSize += 0.5' :key="post.id" :post="post" :finalSize="finalSize"></component-a>         <div>             {{childValue}}         </div>     </div> </div>  <script>     var ComponentB = {         data() {             return {                 son: -1             }         },         template: `             <div>                 <button @click='sendToChild(1)'>点击传值1</button>             </div> 			`,         methods: {             sendToChild(value) {                 this.$emit('sendParent', value)             }         }     }      var ComponentA = {         props: ['post'],         components: {             ComponentB         },         template: `             <div class="blog-post">            		<button @click="$emit('big')">            			{{post.name1}}                 </button>                 <component-b @sendParent='sendPatent'></component-b>                 <div v-html="post.content"></div>              </div>             `,         methods: {             sendPatent(value) {                 this.$emit('sendvalue', value)             }         }     }      new Vue({         el: "#app",         components: {             ComponentA         },         data: {             post: {                 id: 1,                 name1: "文本变大",                 name2: "子组件传递值给父组件",                 age: 13,                 content: "测试文本"             },             obj: "test",             finalSize: 1,             childValue: 0         },         methods: {             getChildValue(value) {                 this.childValue = value;             }         }     }) </script> 

点击之前: 学习Vue,这一篇文章就够了(持续更新中) 点击之后:学习Vue,这一篇文章就够了(持续更新中)

自定义事件名

不同于组件和 prop,事件名不存在任何自动化的大小写转换。而是触发的事件名需要完全匹配监听这个事件所用的名称。例如:我们监听这个事件

this.$emit('myEvent') 

则监听这个名字的 kebab-case 版本是不会有任何效果的:

<!-- 没有效果 --> <my-component v-on:my-event="doSomething"></my-component> 

并且 v-on 事件监听器在 DOM 模板中会被自动转换为全小写 (因为 HTML 是大小写不敏感的),所以 v-on:myEvent 将会变成 v-on:myevent——导致 myEvent 不可能被监听到。

因此,推荐始终使用 kebab-case 的事件名

父子组件的双向数据绑定

表单

有时候需要在组件上使用v-model,输入修改子组件的表单input的同时修改父组件的data值。

示例:

<div id="app">     <my-input v-model="message"></my-input>{{message}} </div>  <script>     var MyInput = {         props:["value"],         template:` 	<div> 		<input :value="value" @input="$emit('input',$event.target.value)">     </div> 	`,         inheritAttrs:false     }     new Vue({         el:"#app",         components:{             MyInput         },         data:{             message: "测试文本"         }     }) 

原理:

v-model本质上可分解为v-bind:value以及@input事件,在组件上使用v-model没有什么差别,差别在于:使用子组件时,@input事件不再是默认的改变自己this.value = $event.target.value,而是修改调用父类的input方法,并将$event.target.value赋值给message

自定义组件的v-model -lyx? todo

一个组件上的 v-model 默认会利用名为 value 的 prop 和名为 input 的事件,但是像单选框、复选框等类型的输入控件可能会将 value attribute 用于不同的目的。model 选项可以用来避免这样的冲突:

不写:checked='select' 没有初始化,且子组件的checked值始终为false,即使复选框被选中也为false

<div id="app2">     {{select}}     <my-checkbox v-model='select' :checked='select'></my-checkbox>     <input type="checkbox" v-model="select" /> </div> <script> var MyCheckbox = {     model: {         props: "checked",         event: "change"     },     props: {         checked: Boolean     },     template: ` <div><input type='checkbox' :checked='checked' @change='$emit("change",$event.target.checked)'>111</div> `,     inheritAttrs: false }  new Vue({     el: "#app2",     data: {         select: true     },     components: {         MyCheckbox     },     inheritAttrs: true }) </script> 
.sync修饰符

在有些情况下,我们可能需要对一个 prop 进行“双向绑定”。但是,子组件不能直接修改父组件的值,通过子父组件的数据双向绑定也可以达到效果,但是十分繁琐,在Vue中提供了.sync的语法糖 -lyx todo

<div id="app">     <div style="width: 309px;height: 200px;border: 1px solid black;">         <my-button :child-show.sync="show" v-show="show"></my-button>     </div> </div>  <script>     let vm = new Vue({             el: '#app',             data: {                 show: true             }             components: {                 'MyButton': {                 props: ["child-show"],                 template:                  `<div> 					<button @click.stop='$emit("update:childshow",false)'>                         test                     </button>     			</div>`                 }             }         }) </script> 

当我们用一个对象同时设置多个prop双向绑定的时候,也可以将这个 .sync 修饰符和 v-bind 配合使用:

<my-button v-bind.sync="doc"></my-button> 

插槽

插槽,也就是slot,是组件的一块HTML模板。这块模板显示不显示、以及怎样显示由父组件来决定;但是插槽显示的位置却由子组件自身决定

实际上,插槽最核心的两个问题在这里就点出来了,是显示不显示怎样显示

具名插槽:带名字的插槽

实例:

<div id="app">     <my-button>         <!-- 等价于<template #parents> -->         <template v-slot:parents> 			<div>     			<input value='我是父类的插槽内容'>             </div>         </template>     </my-button> </div>  <template id="temp1"> 	<div>         <div class="child">             我是子类的插槽内容         </div>         <slot name='parents'></slot>     </div> </template>  <script>     Vue.component('MyButton', {         template: temp1     })      new Vue({el: '#app'}) </script> 

效果:学习Vue,这一篇文章就够了(持续更新中)

  1. 当组件渲染的时候,<slot></slot> 将会直接被替换为组件双标签内的内容。插槽内可以包含任何模板代码,包括 HTML,甚至可以是其他的组件。

  2. <slot></slot>标签无name属性时,默认name='default',会渲染出组件起始标签内的所有未设置v-sloat的节点以及v-sloat:default的节点。这类插槽也称作:默认插槽/匿名插槽/单个插槽

  3. v-onv-bind 一样,v-slot 也有缩写,即把参数之前的所有内容 (v-slot:) 替换为字符 #

    例如 v-slot:header 可以被重写为 #header

    注:采用#缩写时,default不可省略

  4. 除了v-slot:header#header外,还有slot='header'也是一样的,但是已被废弃,了解即可

作用域插槽:带数据的插槽

作用域插槽,与前一种插槽相比,区别就是携带数据

<!-- 匿名插槽 --> <slot></slot> <!-- 具名插槽 --> <slot name="up"></slot> <!-- 作用域插槽 --> <slot name="up" :data="data"></slot> 

实例:

...待更新中

后备内容

有时为一个插槽设置具体的后备 (也就是默认的) 内容是很有用的,它只会在没有提供内容的时候被渲染。

<div id="app">     <my-button>         <template #slot1>             <div>                 <input class='parent' value='我是父类的插槽内容1'>             </div> 		</template>         <template>             <div>                 <input class='parent' value='我是父类的插槽内容2'>             </div> 		</template>     </my-button> </div>  <template id="temp1"> 	<div>         <slot name='slot1'>一个slot='sloat1'的插槽都没有</slot>     	<slot name='slot2'>一个slot='sloat2'的插槽都没有</slot>     </div> </template>  <script>     Vue.component('MyButton', {         template: temp1     })      new Vue({el: '#app'}) </script> 

结果:学习Vue,这一篇文章就够了(持续更新中)

注:后备内容也同样支持HTML语法

后续内容待更新。。。