vue-router官网 || API-Vue.js || Vue官网 || axios中文网
基本用法:
绑定事件监听器。事件类型由参数指定。表达式可以是一个方法的名字或一个内联语句,如果没有修饰符也可以省略。用在普通元素上时,只能监听原生 DOM 事件。用在自定义元素组件上时,也可以监听子组件触发的自定义事件。在监听原生 DOM 事件时,方法以事件为唯一的参数。如果使用内联语句,语句可以访问一个 $event property:v-on:click=“handle(‘ok’, $event)”。从 2.4.0 开始,v-on 同样支持不带参数绑定一个事件/监听器键值对的对象。注意当使用对象语法时,是不支持任何修饰器的。监听事件:使用 v-on 指令来监听 DOM 事件,并在触发时运行一些 JavaScript 代码。例如操作data中的counter使其自增。
<div id="example-1"> <!--执行例子的代码,每点击一次按钮,使得counter值每次自增一 --> <button v-on:click="counter += 1">Add 1</button> <p>The button above has been clicked {{ counter }} times.</p> </div> var example1 = new Vue({ el: '#example-1', data: { counter: 0 //定义一个counter属性来存储点击的次数 } })监听自定义的事件处理方法,定义了一个greet方法: 点击按钮弹出两个消息,一个弹出 alert('Hello ’ + this.name + ‘!’) ,一个alert(event.target.tagName)触发事件的标签名
<div id="example-2"> <button v-on:click="greet">Greet</button> <!-- `greet` 是在下面定义的方法名 --> </div> var example2 = new Vue({ el: '#example-2', data: { name: 'Vue.js' }, methods: { // 在 `methods` 对象中定义方法 `greet` greet: function (event) { alert('Hello ' + this.name + '!') // `this` 在方法里指向当前 Vue 实例 exampole2 if (event) { // `event` 是原生 DOM 事件 alert(event.target.tagName) } } } }) // 也可以用 JavaScript 直接调用方法 example2.greet() // => 'Hello Vue.js!'内联处理器中的方法 所谓内联处理器就是带括号的()语句,为了访问原始DOM用特殊变量 $event把它传入方法.
<div id="example-3"> <!-- 点击两个按钮中的一个,提示出对应内容hi或者是what --> <button v-on:click="say('hi')">Say hi</button> <button v-on:click="say('hi',$event)">Say hi</button> <button v-on:click="say('what')">Say what</button> <button v-on:click="say('what',$event)">Say hi</button> </div> new Vue({ el: '#example-3', methods: { say: function (message) { alert(message); alert(event.target.tagName); } } })v-on的缩写形式@click=" "
<!-- 完整语法 --> <a v-on:click="doSomething">...</a> <!-- 缩写 --> <a @click="doSomething">...</a> <!-- 动态参数的缩写 (2.6.0+) --> <a @[event]="doSomething"> ... </a> <!-- 方法处理器 --> <button v-on:click="doThis"></button> <!-- 动态事件 (2.6.0+) --> <button v-on:[event]="doThis"></button> <!-- 内联语句 --> <button v-on:click="doThat('hello', $event)"></button> <!-- 缩写 --> <button @click="doThis"></button> <!-- 动态事件缩写 (2.6.0+) --> <button @[event]="doThis"></button> <!-- 停止冒泡 --> <button @click.stop="doThis"></button> <!-- 阻止默认行为 --> <button @click.prevent="doThis"></button> <!-- 阻止默认行为,没有表达式 --> <form @submit.prevent></form> <!-- 串联修饰符 --> <button @click.stop.prevent="doThis"></button> <!-- 键修饰符,键别名 --> <input @keyup.enter="onEnter"> <!-- 键修饰符,键代码 --> <input @keyup.13="onEnter"> <!-- 点击回调只会触发一次 --> <button v-on:click.once="doThis"></button> <!-- 对象语法 (2.4.0+) --> <button v-on="{ mousedown: doThis, mouseup: doThat }"></button>形如@click.once"xxx"
.stop - 调用 event.stopPropagation(),简单来说阻止冒泡。
.prevent - 调用 event.preventDefault(),简单来说阻止默认行为。
.capture - 添加事件侦听器时使用 capture 模式。
.self - 只当事件是从侦听器绑定的元素本身触发时才触发回调。简单来说仅仅绑定元素自身触发。
.once - 只触发一次回调。 简单来说绑定事件只会触发一次。
.passive - (2.3.0) 以 { passive: true } 模式添加侦听器,简单来说滚动事件的默认行为 (即滚动行为) 将会立即触发,不能和.prevent 一起使用
使用修饰符时,顺序很重要;相应的代码会以同样的顺序产生。
因此,用 v-on:click.prevent.self 会阻止所有的点击,而=v-on:click.self.prevent 只会阻止对元素自身的点击。
.{keyCode | keyAlias} - 只当事件是从特定键触发时才触发回调。
.native - 监听组件根元素的原生事件。
.left - (2.2.0) 只当点击鼠标左键时触发。
.right - (2.2.0) 只当点击鼠标右键时触发。
.middle - (2.2.0) 只当点击鼠标中键时触发。
.passive - (2.3.0) 以 { passive: true } 模式添加侦听器,简单来说滚动事件的默认行为 (即滚动行为) 将会立即触发,不能和.prevent 一起使用
在methods中定义方法主要有两种方式:
无括号的方法相当于自带$event,可以访问原始DOM,查看target等操作。例如, 上面例子中的greet方法。内联处理器中的方法相当于带括号的方法,如果不传参 $event则无法访问原始DOM,所以在传参时要写上 $event。可以用来显示原始 Mustache 标签。跳过大量没有指令的节点会加快编译,简单来说,忽略相应的指令。
<span v-pre>{{ this will not be compiled }}</span> 显示的是{{ this will not be compiled }} <span v-pre>{{msg}}</span> 即使data里面定义了msg这里仍然是显示的{{msg}}v-once: 场景:有些 template 中的静态 dom 没有改变,这时就只需要渲染一次,可以降低性能开销
<span v-once> 这时只需要加载一次的标签</span> v-once 和 v-pre 的区别: v-once只渲染一次;v-pre不编译,原样输出数据绑定最常见的形式就是使用“Mustache”语法 (双大括号) 的文本插值:,下面统一简称双括号。
<span>Message: {{ msg }}</span> 双括号会被替代为对应数据对象上msg的值。只要绑定的数据对象上msg的值发生了改变,双括号的内容都会更新,这就是双向绑定。通过使用 v-once 指令,执行一次性地插值,当数据改变时,插值处的内容不会更新 <span v-once>这个将不会改变: {{ msg }}</span> 双括号将数据解释为普通文本,非 HTML 代码。为了输出真正的 HTML,你需要使用 v-html指令。 <p>Using mustaches: {{ rawHtml }}</p> <p>Using v-html directive: <span v-html="rawHtml"></span></p>修饰符:
.prop - 作为一个 DOM property 绑定而不是作为 attribute 绑定。.camel - (2.1.0+) 将 kebab-case attribute 名转换为 camelCase。(从 2.1.0 开始支持).sync (2.3.0+) 语法糖,会扩展成一个更新父组件绑定值的 v-on 侦听器。用法:
动态地绑定一个或多个 attribute,或一个组件 prop 到表达式。在绑定 class 或 style attribute 时,支持其它类型的值,如数组或对象。在绑定 prop 时,prop 必须在子组件中声明。可以用修饰符指定不同的绑定类型。没有参数时,可以绑定到一个包含键值对的对象。注意此时 class 和 style 绑定不支持数组和对象。双括号语法不能作用在 HTML attribute 上(如绑定id、class、href等情况)这个时候应该使用 v-bind 指令 <div v-bind:id="dynamicId"></div>对于布尔 attribute (它们只要存在就意味着值为 true),v-bind 工作起来略有不同,在这个例子中:
<button v-bind:disabled="isButtonDisabled">Button</button>v-bind的缩写形式 :href=“url” ,:id="123"的形式。
<!-- 完整语法 --> <a v-bind:href="url">...</a> <!-- 缩写为:href="url" --> <a :href="url">...</a> <!-- 动态参数的缩写 (2.6.0+) --> <a :[key]="url"> ... </a> <!-- 绑定一个 attribute --> <img v-bind:src="imageSrc"> <!-- 动态 attribute 名 (2.6.0+) --> <button v-bind:[key]="value"></button> <!-- 缩写 --> <img :src="imageSrc"> <!-- 动态 attribute 名缩写 (2.6.0+) --> <button :[key]="value"></button> <!-- 内联字符串拼接 --> <img :src="'/path/to/images/' + fileName"> <!-- class 绑定 --> <div :class="{ red: isRed }"></div> <div :class="[classA, classB]"></div> <div :class="[classA, { classB: isB, classC: isC }]"> <!-- style 绑定 --> <div :style="{ fontSize: size + 'px' }"></div> <div :style="[styleObjectA, styleObjectB]"></div> <!--绑定一个全是 attribute 的对象 --> <div v-bind="{ id: someProp, 'other-attr': otherProp }"></div> <!-- 通过 prop 修饰符绑定 DOM attribute --> <div v-bind:text-content.prop="text"></div> <!-- prop 绑定。“prop”必须在 my-component 中声明。--> <my-component :prop="someThing"></my-component> <!-- 通过 $props 将父组件的 props 一起传给子组件 --> <child-component v-bind="$props"></child-component> <!-- XLink --> <svg><a :xlink:special="foo"></a></svg>v-model 会 忽略所有表单元素的 value、checked、selected, attribute 的初始值,而是 将Vue 实例的数据作为数据来源 。 你应该在组件的data 选项中声明初始值。
模板内的表达式非常便利,适合用于简单运算的。在模板中放入太多的逻辑会变得十分复杂。
<div id="example"> <!--将message 分割-> 翻转-> 拼接 --> {{ message.split('').reverse().join('') }} </div>本例,模板不再是简单的声明式逻辑。是显示变量 message 的翻转字符串。
对于任何复杂逻辑,应当使用计算属性。
<div id="example"> <p>Original msg: "{{ msg}}"</p> <p>Computed reversed msg: "{{ reversedMessage }}"</p> </div> var vm = new Vue({ el: '#example', data: { msg: 'Hello' }, computed: { // 计算属性的 getter reversedMessage: function () { // `this` 指向 vm 实例 return this.msg.split('').reverse().join('') } } }) 结果: Original msg: "Hello" Computed reversed msg: "olleH" 声明了一个计算属性 reversedMessage。 vm.reversedMessage 的 getter 函数: console.log(vm.reversedMessage) // => 'olleH' vm.message = 'Goodbye' console.log(vm.reversedMessage) // => 'eybdooG' f12打开控制台修改 vm,msg的值。计算属性vm.reversedMessage 的值始终取决 vm.msg的值。计算属性computed缓存 和函数function()的比较
在表达式中调用方法reveredMessage()来达到同样的效果: <p>Reversed message: "{{ reversedMessage() }}"</p> // 在组件中 methods: { //在methods中定义相关方法 reversedMessage: function () { return this.message.split('').reverse().join('') } } 同一函数定义为一个方法,两种方式的结果是相同的。不同的是计算属性是基于它们的响应式依赖进行缓存的。只在响应式依赖发生改变时才会重新求值。这就意味着只要 message 还没有发生改变,多次访问 reversedMessage 计算属性会立即返回之前的计算结果,而不必再次执行函数。每当触发重新渲染时,调用方法将总会再次执行函数。为什么需要缓存 ? 假设我们有一个性能开销比较大的计算属性 A,它需要遍历一个巨大的数组并做大量的计算。然后我们可能有其他的计算属性依赖于 A。如果没有缓存,我们将不可避免的多次执行 A 的 getter!
下面用一个实例进行展示效果。
Vue 提供了一种更通用的方式来观察和响应 Vue 实例上的数据变动:侦听属性。
适合场景:数据变化时执行异步或开销较大的操作。当你有一些数据需要随着其它数据变动而变动时。更好的做法是计算属性不是命令式的 watch 回调。
侦听器watch和计算属性computed的对比实例:
<div id="demo">{{ fullName }}</div> var vm = new Vue({ el: '#demo', data: { firstName: 'Foo', lastName: 'Bar', fullName: 'Foo Bar' }, watch: { firstName: function (val) { this.fullName = val + ' ' + this.lastName }, lastName: function (val) { this.fullName = this.firstName + ' ' + val } }, computed: { //计算属性时不需要提供fullname fullName: function () { return this.firstName + ' ' + this.lastName } } })计算属性默认形式为 getter,只能返回计算值,你也可以提供一个 setter。
运行 vm.fullName = ‘John Doe’ 时,setter 会被调用,vm.firstName 和 vm.lastName 会被更新。
computed: { fullName: { // getter get: function () { return this.firstName + ' ' + this.lastName }, // setter set: function (newValue) { var names = newValue.split(' ') this.firstName = names[0] this.lastName = names[names.length - 1] } } }实例:侦听器监听firstName和lastName 实例2:模拟异步任务,监听uname的变化,并调用checkName方法实现模拟验证。
用法:
观察 Vue 实例上的一个表达式或者一个函数计算结果的变化。回调函数得到的参数为新值和旧值。表达式只接受简单的键路径。对于更复杂的表达式,用一个函数取代。 // 键路径 vm.$watch('a.b.c', function (newVal, oldVal) { // 做点什么 }) // 函数 vm.$watch( function () { // 表达式 `this.a + this.b` 每次得出一个不同的结果时 // 处理函数都会被调用。 // 这就像监听一个未被定义的计算属性 return this.a + this.b }, function (newVal, oldVal) { // 做点什么 } )Vue.js 允许你自定义过滤器,用于一些常见的文本格式化。过滤器可以用在两个地方:双花括号插值和 v-bind 表达式 (后者从 2.1.0+ 开始支持)。过滤器应该被添加在 JavaScript 表达式的尾部,由“管道”符号指示:
<!-- 在双花括号中 --> {{ message | capitalize }} <!-- 在 `v-bind` 中 --> <div v-bind:id="rawId | formatId"></div>在一个组件的选项中定义本地的过滤器:
filters: { capitalize: function (value) { if (!value) return '' value = value.toString() return value.charAt(0).toUpperCase() + value.slice(1) } }全局定义过滤器:
Vue.filter('capitalize', function (value) { if (!value) return '' value = value.toString() return value.charAt(0).toUpperCase() + value.slice(1) })当全局过滤器和局部过滤器重名时,会采用局部过滤器。
过滤器函数总接收表达式的值 (之前的操作链的结果) 作为第一个参数。
在上述例子中,capitalize 过滤器函数将会收到 message 的值作为第一个参数。
过滤器的串联:
{{ message | filterA | filterB }}本例中,filterA 被定义为接收单个参数的过滤器函数,表达式 message 的值将作为参数传入到函数
中。继续调用同样被定义为接收单个参数的过滤器函数 filterB,将 filterA 的结果传递到 filterB 中。
过滤器是 JavaScript 函数,因此可以接收参数:
{{ message | filterA('arg1', arg2) }}filterA 被定义为接收三个参数的过滤器函数。其中 message 的值作为第一个参数,普通字符串 ‘arg1’
作为第二个参数,表达式 arg2 的值作为第三个参数。
实例:一个全局filter实例 upper和 lower来控制首字母大小写 ,和一个局部实例 upper
一般来说v-text指令等价于{{msg}},所以直接双大括号{{ }}取值即可。
<span v-text="msg"></span> <!-- 和下面的一样 --> <span>{{msg}}</span>css添加代码如下
[v-cloak] { display: none; }标签中代码如下
<div v-cloak> {{ message }} </div>**作用:**提供具名插槽或需要接收 prop 的插槽。 限制: 1. :template标签, 2. 组件中 (对于一个单独的带 prop 的默认插槽)
<!-- 具名插槽 --> <base-layout> <template v-slot:header> Header content </template> Default slot content <template v-slot:footer> Footer content </template> </base-layout> <!-- 接收 prop 的具名插槽 --> <infinite-scroll> <template v-slot:item="slotProps"> <div class="item"> {{ slotProps.item.text }} </div> </template> </infinite-scroll> <!-- 接收 prop 的默认插槽,使用了解构 --> <mouse-position v-slot="{ x, y }"> Mouse position: {{ x }}, {{ y }} </mouse-position>在实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用
在实例创建完成后被立即调用。挂载阶段还没开始,$el property 目前尚不可用。
在挂载开始之前被调用:相关的 render 函数首次被调用。
实例被挂载后调用,这时 el 被新创建的 vm.$el 替换了。
如果根实例挂载到了一个文档内的元素上,当 mounted 被调用时 vm.el 也在文档内。
注意 mounted 不会保证所有的子组件也都一起被挂载。如果你希望等到整个视图都渲染完毕,可以
在 mounted 内部使用 vm.$nextTick:
适用于更新之前访问现有的 DOM,比如手动移除已添加的事件监听器。
由于数据更改导致的虚拟 DOM 重新渲染和打补丁,之后会调用该钩子。 当这个钩子被调用时,组件 DOM 已经更新,你可以执行依赖于 DOM 的操作。然而在大多数情况下,你应该避免在此期间更改状态。如果要相应状态改变,通常最好使用计算属性或 watcher 取而代之。 注意 updated 不会保证所有的子组件也都一起被重绘。如果你希望等到整个视图都重绘完毕,可以在 updated 里使用 vm.$nextTick:
被 keep-alive 缓存的组件激活时调用。
被 keep-alive 缓存的组件停用时调用。
在这一步,实例仍然完全可用。
调用后,对应 Vue 实例的所有指令都被解绑、事件监听器被移除、子实例也都被销毁。
类型:string | Element 限制:只在用 new 创建实例时生效。 提供一个在页面上已存在的 DOM 元素作为 Vue 实例的挂载目标。可以是 CSS 选择器,也可以是一个 HTMLElement 实例。 在实例挂载之后,元素可以用 vm.$ el 访问。 如果在实例化时存在这个选项,实例将立即进入编译过程,否则,需要显式调用 vm.$mount() 手动开启编译。 提供的元素只能作为挂载点。不同于 Vue 1.x,所有的挂载元素会被 Vue 生成的 DOM 替换。因此不推荐挂载 root 实例到 或者 上。 如果 render 函数和 template property 都不存在,挂载 DOM 元素的 HTML 会被提取出来用作模板,此时,必须使用 Runtime + Compiler 构建的 Vue 库。
类型:Object | Function 限制:组件的定义只接受 function。 详细: Vue 实例的数据对象。Vue 将会递归将 data 的 property 转换为 getter/setter,从而让 data 的 property 能够响应数据变化。对象必须是纯粹的对象 (含有零个或多个的 key/value 对):浏览器 API 创建的原生对象,原型上的 property 会被忽略。大概来说,data 应该只能是数据 - 不推荐观察拥有状态行为的对象。 一旦观察过,你就无法在根数据对象上添加响应式 property。因此推荐在创建实例之前,就声明所有的根级响应式 property。 实例创建之后,可以通过 vm. d a t a 访 问 原 始 数 据 对 象 。 V u e 实 例 也 代 理 了 d a t a 对 象 上 所 有 的 p r o p e r t y , 因 此 访 问 v m . a 等 价 于 访 问 v m . data 访问原始数据对象。Vue 实例也代理了 data 对象上所有的 property,因此访问 vm.a 等价于访问 vm. data访问原始数据对象。Vue实例也代理了data对象上所有的property,因此访问vm.a等价于访问vm.data.a。 以 _ 或 $ 开头的 property 不会被 Vue 实例代理,因为它们可能和 Vue 内置的 property、API 方法冲突。你可以使用例如 vm. d a t a . p r o p e r t y 的 方 式 访 问 这 些 p r o p e r t y 。 当 一 个 组 件 被 定 义 , d a t a 必 须 声 明 为 返 回 一 个 初 始 数 据 对 象 的 函 数 , 因 为 组 件 可 能 被 用 来 创 建 多 个 实 例 。 如 果 d a t a 仍 然 是 一 个 纯 粹 的 对 象 , 则 所 有 的 实 例 将 共 享 引 用 同 一 个 数 据 对 象 ! 通 过 提 供 d a t a 函 数 , 每 次 创 建 一 个 新 实 例 后 , 我 们 能 够 调 用 d a t a 函 数 , 从 而 返 回 初 始 数 据 的 一 个 全 新 副 本 数 据 对 象 。 如 果 需 要 , 可 以 通 过 将 v m . data._property 的方式访问这些 property。 当一个组件被定义,data 必须声明为返回一个初始数据对象的函数,因为组件可能被用来创建多个实例。如果 data 仍然是一个纯粹的对象,则所有的实例将共享引用同一个数据对象!通过提供 data 函数,每次创建一个新实例后,我们能够调用 data 函数,从而返回初始数据的一个全新副本数据对象。 如果需要,可以通过将 vm. data.property的方式访问这些property。当一个组件被定义,data必须声明为返回一个初始数据对象的函数,因为组件可能被用来创建多个实例。如果data仍然是一个纯粹的对象,则所有的实例将共享引用同一个数据对象!通过提供data函数,每次创建一个新实例后,我们能够调用data函数,从而返回初始数据的一个全新副本数据对象。如果需要,可以通过将vm.data 传入 JSON.parse(JSON.stringify(…)) 得到深拷贝的原始数据对象。
类型:{ [key: string]: Function }
详细:
methods 将被混入到 Vue 实例中。可以直接通过 VM 实例访问这些方法,或者在指令表达式中使用。方法中的 this 自动绑定为 Vue 实例。
注意,不应该使用箭头函数来定义 method 函数 (例如 plus: () => this.a++)。理由是箭头函数绑定了父级作用域的上下文,所以 this 将不会按照期望指向 Vue 实例,this.a 将是 undefined。
类型:{ [key: string]: Function | { get: Function, set: Function } }
详细:
计算属性将被混入到 Vue 实例中。所有 getter 和 setter 的 this 上下文自动地绑定为 Vue 实例。
注意如果你为一个计算属性使用了箭头函数,则 this 不会指向这个组件的实例,不过你仍然可以将其实例作为函数的第一个参数来访问。
计算属性的结果会被缓存,除非依赖的响应式 property 变化才会重新计算。注意,如果某个依赖 (比如非响应式 property) 在该实例范畴之外,则计算属性是不会被更新的。
类型:{ [key: string]: string | Function | Object | Array }
详细:
一个对象,键是需要观察的表达式,值是对应回调函数。值也可以是方法名,或者包含选项的对象。Vue 实例将会在实例化时调用 $watch(),遍历 watch 对象的每一个 property。
注意,不应该使用箭头函数来定义 watcher 函数 (例如 searchQuery: newValue => this.updateAutocomplete(newValue))。理由是箭头函数绑定了父级作用域的上下文,所以 this 将不会按照期望指向 Vue 实例,this.updateAutocomplete 将是 undefined。
Vue 实例观察的数据对象。Vue 实例代理了对其 data 对象 property 的访问。
当前组件接收到的 props 对象。Vue 实例代理了对其 props 对象 property 的访问。
Vue 实例使用的根 DOM 元素。
用于当前 Vue 实例的初始化选项。需要在选项中包含自定义 property 时会有用处:
new Vue({ customOption: 'foo', created: function () { console.log(this.$options.customOption) // => 'foo' } })父实例,如果当前实例有的话。
当前组件树的根 Vue 实例。如果当前实例没有父实例,此实例将会是其自己。
当前实例的直接子组件。需要注意 $children 并不保证顺序,也不是响应式的。如果你使用 $children 来进行数据绑定,使用一个数组配合 v-for 来生成子组件,并且使用 Array 作为来源。
每个具名插槽有其相应的 property (例如:v-slot:foo 中的内容将会在 vm.$slots.foo 中被找到)。default property 包括了所有没有被包含在具名插槽中的节点,或 v-slot:default 的内容。
注意:v-slot:foo 在 2.6 以上的版本才支持。对于之前的版本,你可以使用废弃了的语法。
在使用渲染函数书写一个组件时,访问 vm.$slots 最有帮助。
示例:
<blog-post> <template v-slot:header> <h1>About Me</h1> </template> <p>Here's some page content, which will be included in vm.$slots.default, because it's not inside a named slot.</p> <template v-slot:footer> <p>Copyright 2016 Evan You</p> </template> <p>If I have some content down here, it will also be included in vm.$slots.default.</p>. </blog-post> Vue.component('blog-post', { render: function (createElement) { var header = this.$slots.header var body = this.$slots.default var footer = this.$slots.footer return createElement('div', [ createElement('header', header), createElement('main', body), createElement('footer', footer) ]) } })对于包括 默认 slot 在内的每一个插槽,该对象都包含一个返回相应 VNode 的函数。
vm.$scopedSlots 在使用渲染函数开发一个组件时特别有用。
注意:从 2.6.0 开始,这个 property 有两个变化:
作用域插槽函数现在保证返回一个 VNode 数组,除非在返回值无效的情况下返回 undefined。
所有的 $slots 现在都会作为函数暴露在 $scopedSlots 中。如果你在使用渲染函数,不论当前插槽是否带有作用域,我们都推荐始终通过 $scopedSlots 访问它们。这不仅仅使得在未来添加作用域变得简单,也可以让你最终轻松迁移到所有插槽都是函数的 Vue 3。
第一行在子组件中起别名aaa,父组件可以直接访问button-counter,第二行普通标签p,则就是p标签 打印所有存在ref别名的元素或者组件实例。
注意:
$refs 只会在组件渲染完成之后生效,并且它们不是响应式的。这仅作为一个用于直接操作子组件的“逃生舱”——你应该避免在模板或计算属性中访问 $refs。当前 Vue 实例是否运行于服务器。
效果图,第一个没有v-bind="$attrs",第二个绑定了。
包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。 通过 v-on="$listeners" 传入内部组件——在创建更高层次的组件时非常有用。
见上面指令篇的watch侦听属性。
基本用法:
Vue.delete(this.namelist,'name');//vue方法 Vue.delete(vm.namelist,'name');//vm实例的对象,并删除name Vue.delete(vm.msglist,2);//vm实例的数组,并删除第二个元素事件可以由 vm.$emit 触发。回调函数会接收所有传入事件触发函数的额外参数。
如本例,emit触发test事件传参hi, $on用msg接收参数hi并打印 vm.$on('test', function (msg) { console.log(msg) }) vm.$emit('test', 'hi') // => "hi"如果没有提供参数,则移除所有的事件监听器;
如果只提供了事件,则移除该事件所有的监听器;
如果同时提供了事件与回调,则只移除这个回调的监听器。
触发当前实例上的事件。附加参数都会传给监听器回调。
如果 Vue 实例在实例化时没有收到 el 选项,则它处于“未挂载”状态,没有关联的 DOM 元素。
使用 vm.$mount() 手动地挂载一个未挂载的实例。
迫使 Vue 实例重新渲染。注意它仅仅影响实例本身和插入插槽内容的子组件,而不是所有子组件。
函数作用:触发当前实例上的事件,附加参数都会传给监听器回调。 参数类型主要有六种类型,无参构造、有参构造两种、嵌套有无参构造下面给出示例。
步骤一:在模板定义相关点击事件函数,触发emit回调至父组件,可以简单传定值参数。 步骤二:在父组件监听事件并回调至methods执行相应方法,接收参数则需要$event。 步骤三:定义相关方法(函数)来进行相应的有无参数操作。总结:
在模板中传参只能写成固定值例如123或者’hello world之类的定值,不能直接访问组件中的data例如本例中的num,如果访问则结果变为undefined。如需调用还需使用内嵌形式,所谓内嵌就是在组件方法中调用emit。在组件的方法中调用emit并this.num的形式传参,在父组件中使用$event来接收参数,并在父组件的methods方法中使用。prop传数字、布尔、对象、数组的示例。
<blog-post v-bind:likes="42"></blog-post> <!-- 用一个变量进行动态赋值。--> <blog-post v-bind:likes="post.likes"></blog-post> <!-- 包含该 prop 没有值的情况在内,都意味着 `true`。--> <blog-post is-published></blog-post> <blog-post v-bind:is-published="false"></blog-post> <!-- 用一个变量进行动态赋值。--> <blog-post v-bind:is-published="post.isPublished"></blog-post> <blog-post v-bind:comment-ids="[234, 266, 273]"></blog-post> <!-- 用一个变量进行动态赋值。--> <blog-post v-bind:comment-ids="post.commentIds"></blog-post> <blog-post v-bind:author="{ name: 'Veronica', company: 'Veridian Dynamics' }" ></blog-post> <!-- 用一个变量进行动态赋值。--> <blog-post v-bind:author="post.author"></blog-post> 传入一个对象的所有 property: <blog-post v-bind="post"></blog-post> 等价于: <blog-post v-bind:id="post.id" v-bind:title="post.title" ></blog-post>单向数据流:简单来说:prop都是父组件对子组件的单向数据传输。
prop 都使其父子 prop 形成了单向下行绑定:父级 prop 的更新会向下流动到子组件中,防止从子组件意外变更父级组件的状态,从而导致你的应用的数据流向难以理解。当父级组件发生变更时,子组件中所有的 prop 都将刷新为最新的值。这代表你不应该在一个子组件内部改变 prop。如果你这样做了,Vue 会在浏览器的控制台中发出警告。为组件的 prop 指定验证要求,例如你知道的这些类型。如果有一个需求没有被满足,则 Vue 会在浏览器控制台中警告你。这在开发一个会被别人用到的组件时尤其有帮助。
为了定制 prop 的验证方式,你可以为 props 中的值提供一个带有验证需求的对象,而不是一个字符串数组。例如:
Vue.component('my-component', { props: { // 基础的类型检查 (`null` 和 `undefined` 会通过任何类型验证) 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 } } } })当 prop 验证失败的时候,(开发环境构建版本的) Vue 将会产生一个控制台的警告。
注意那些 prop 会在一个组件实例创建之前进行验证,所以实例的 property (如 data、computed 等) 在 default 或 validator 函数中是不可用的。
类型检查 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 创建的。
非 Prop 的 Attribute 一个非 prop 的 attribute 是指传向一个组件,但是该组件并没有相应 prop 定义的 attribute。
因为显式定义的 prop 适用于向一个子组件传入信息,然而组件库的作者并不总能预见组件会被用于怎样的场景。这也是为什么组件可以接受任意的 attribute,而这些 attribute 会被添加到这个组件的根元素上。
例如,想象一下你通过一个 Bootstrap 插件使用了一个第三方的 组件,这个插件需要在其 上用到一个 data-date-picker attribute。我们可以将这个 attribute 添加到你的组件实例上:
然后这个 data-date-picker=“activated” attribute 就会自动添加到 的根元素上。
替换/合并已有的 Attribute 想象一下 的模板是这样的:
为了给我们的日期选择器插件定制一个主题,我们可能需要像这样添加一个特别的类名:<bootstrap-date-input data-date-picker=“activated” class=“date-picker-theme-dark”
在这种情况下,我们定义了两个不同的 class 的值:
form-control,这是在组件的模板内设置好的 date-picker-theme-dark,这是从组件的父级传入的 对于绝大多数 attribute 来说,从外部提供给组件的值会替换掉组件内部设置好的值。所以如果传入 type=“text” 就会替换掉 type=“date” 并把它破坏!庆幸的是,class 和 style attribute 会稍微智能一些,即两边的值会被合并起来,从而得到最终的值:form-control date-picker-theme-dark。
禁用 Attribute 继承 如果你不希望组件的根元素继承 attribute,你可以在组件的选项中设置 inheritAttrs: false。例如:
Vue.component(‘my-component’, { inheritAttrs: false, // … }) 这尤其适合配合实例的 $attrs property 使用,该 property 包含了传递给一个组件的 attribute 名和 attribute 值,例如:
{ required: true, placeholder: ‘Enter your username’ } 有了 inheritAttrs: false 和 $attrs,你就可以手动决定这些 attribute 会被赋予哪个元素。在撰写基础组件的时候是常会用到的:
Vue.component(‘base-input’, { inheritAttrs: false, props: [‘label’, ‘value’], template: <label> {{ label }} <input v-bind="$attrs" v-bind:value="value" v-on:input="$emit('input', $event.target.value)" > </label> }) 注意 inheritAttrs: false 选项不会影响 style 和 class 的绑定。
这个模式允许你在使用基础组件的时候更像是使用原始的 HTML 元素,而不会担心哪个元素是真正的根元素:
<base-input v-model=“username” required placeholder=“Enter your username”
插槽内容: 1. 普通文本 2. 标签 3. 其他组件
编译作用域: 插槽跟模板的其它地方一样可以访问相同的实例 property (也就是相同的“作用域”) 规则:(简称父在父,子在子)
父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的。后备内容(或者叫默认内容) 标签中调用 输出结果: 具名插槽:(根据名字的标签分发内容) v-slot:header可以缩写#header的形式
主要有两种样式:
在template标签中使用v-slot:header起别名的形式,使用v-slot指令来取名,默认为default。使用标签header、main、footer和模板中的一致。模板中定义的内容: 作用域插槽:(使插槽内容能访问子组件中才有的数据) 插槽内容和插槽不一样要注意:
插槽内容实际上定义在父级作用域,相对于组件来说,无法直接访问子组件的相应数据。绑定在slot元素上的attribute被称为插槽 prop,用v-bind:user='user’来绑定。简写为:user=‘user’,为了将zujian3中的user传递给插槽,这样插槽内容通过插槽prop中就可以访问zujian3中的user数据。 在父级作用域中,使用带值的 v-slot 来定义插槽 prop的名字,v-slot:可以简写为#。 总结: 插槽是slot标签,而插槽内容是父级作用域中显示在插槽标签中的内容。 插槽内容的作用域是比模板高的,所以插槽标签在模板中可以直接访问组件中的data数据,而插槽内容不可以,所以通过作用域插槽来使得插槽内容访问组件中的数据。