Vue2基础语法
Vue2入门基础语法
Vue实例
创建实例
通过实例化Vue构造函数创建一个Vue实例。
const vm = new Vue({});
数据
data
是Vue实例中的数据,在data中的数据都会被加入到响应式系统中。当数据发生改变之后,视图也会被更改。
data() { return { message: 'hello,world', }; },
在data中的数据可以直接在视图中使用。
<div> {{ message }} </div>
如果让data中的message发生改变,那么视图中的message展示的内容也会更新。
如果data中的数据使用了Object.freeze()方法,那么vue将无法再追踪数据的变化。
可以通过$data访问到data中的内容。
mounted() { console.log(this.$data); // {__ob__: Observer} console.log(this.$data.message); // hello,world },
在$data中可以访问所以的data中的数据。
方法
methods
对象里面存储的是方法。
methods: { sayHello() { console.log('hello,world!'); } },
创建的methods
对象里面的方法也可以在其他的位置访问。例如其他的方法当中。
sayGoodBye() { // 调用其他的方法 this.sayHello(); },
上面代码的是在sayGoodBye中调用sayHello()方法。
<template> <div> {{ fn1() }} </div> </template> <script> export default { name: 'DataAndMethods', data() { return { message: 'hello,world', }; }, methods: { fn1() { return '我是f1函数' } }, }; </script> <style lang="scss" scoped></style>
上面代码中,将函数fn1放在了视图中使用。
实例生命周期钩子
每一个vue实例,从诞生到销毁,都要经历一个完整的流程。而在不同的环节中,vue准备了不同的函数,只要到了指定的环节,对应的函数就会自动执行。这就是生命周期钩子。
Vue2中的生命周期钩子如下:
- beforeCreate -- 初始化之前
- created -- 实例初始化之后
- beoreMount -- 挂载成功之前
- mounted -- 挂载之后
- beforeUpdate -- 数据更新之前
- updated -- 数据更新之后
- beforeDestroy -- 组件销毁之前
- destroyed -- 组件销毁之后
模板语法
Vue中允许通过{{}}
的形式将数据渲染到模板中,也可以使用render()
函数来进行渲染。
文本
如果需要将文本渲染到页面上,可以直接将文本存储到data中,然后通过{{}}
的形式渲染到页面上。
data() { return { message: 'hello,world', }; }, // template <div>{{message}}</div>
原始html
如果要将html渲染到页面上,不能直接通过{{}}
的形式,这种形式无法解析html
标签,需要通过v-html
指令来实现html
的渲染绑定。
data() { return { htmlString: '<em>我是一段被html包裹的文本</em>' }; }, // 模板中 <div v-html="htmlString"></div>
滥用v-html容易导致xss攻击。
Attribute
{{}}
这种写法不能用在HTML 的Attribute
上,想要在标签的属性上进行值的动态绑定,应该使用v-bind
指令。
<template> <div> <div v-bind:title="title">Hello,World!</div> </div> </template> <script> export default { name: 'ModuleDemo', data() { return { title: 'hello,world' } }, } </script> <style lang="scss" scoped> </style>
上面代码中,将data中的title通过v-bind
指令绑定到了div标签的title
属性身上。当data中的title属性值发生改变之后,div的title值也会发生变化。
在vue中,v-bind
在进行绑定的时候,可以直接进行简写。
<div :title="title">Hello,World!</div>
如果data中要进行绑定的变量的值为
null
、undefined
或false
,那么标签上进行动态绑定值的属性将不会渲染出来。
JavaScript表达式
vue支持在{{}}
中进行表达式的解析。
{{1+2}} ==> 3
{{ number + 1 }} {{ ok ? 'YES' : 'NO' }} {{ message.split('').reverse().join('') }}
{{}}
中只能包含单个表达式。
指令
指令 (Directives) 是带有 v-
前缀的特殊 attribute。指令 attribute 的值预期是单个 JavaScript 表达式 (v-for
是例外情况)。指令的作用主要是监督值的变化,如果值发生变化,那么因为指令的存在就会发生连带反应,从而响应式的作用域DOM。
v-if指令
例如v-if
指令,该指令使用方式如下:
<template> <div> <div v-if="state">Hello,Vue2!</div> </div> </template> <script> export default { name: 'ModuleDemo', data() { return { state: true } }, } </script> <style lang="scss" scoped> </style>
上述代码中, v-if
在div的身上绑定的值是state
,此时state的值为true,那么被绑定v-if
指令的div就会显示在页面中。而如果将state
的值改为false,那么div
将在渲染的时候消失。
需要知道的是,v-if绑定的值为false时元素会消失,消失的方式是该节点直接被删除。
参数
vue中的有些指令是可以携带参数的,例如v-bind
指令,在v-bind
指令后面可以通过:
的形式来进行携带参数。
<div v-bind:title="content"></div>
上面代码中:
后面的title就是携带的参数。
动态参数
指令在携带参数的时候,携带的参数也可以是一个动态的值。通过[]
来进行设置。
<template> <div> <div v-bind:[bindattr]="message">hello,动态参数</div> </div> </template> <script> export default { name: 'ModuleDemo', data() { return { message: '动态参数绑定', bindattr: 'title' }; }, }; </script> <style lang="scss" scoped></style>
如果要移除动态参数的值,可以显示的给动态参数的值设置为null
。当动态参数值绑定出现异常的时候,也会被设置为null
。
在js的语法中,[]
里面的内容会被js理解为是js
的表达式。在vue里面,进行动态参数绑定的时候,并不建议在里面处理过于复杂的表达式,如果处理过程不可避免,建议使用计算属性。
在进行动态参数绑定的时候,
[]
里面的参数会全部转换为小写。
修饰符
vue中修饰符是以.
来进行设置。用于指出一个指令以特殊的方式进行绑定。例如,.stop
可以在v-on
指令绑定事件的时候,阻止冒泡。
<template> <div v-on:click="handleClick1"> <div v-on:click.stop="handleClick2">div2</div> </div> </template> <script> export default { name: 'ModuleDemo', methods: { handleClick1() { console.log('handleClick1') }, handleClick2() { console.log('handleClick2') } }, }; </script> <style lang="scss" scoped></style>
缩写
在vue
中,有些指令的使用频率非常高,每次都v-
开头,难免有一些繁琐。所以vue中对于v-bind
和v-on
指令提供了两个缩写。
例如:
<div :title="title"></div> <div @click="handleClick"></div>
计算属性
定义
在{{}}
中可以使用表达式实现某种目的,但是如果是过于复杂的表达式,并不建议在{{}}
中使用,可以通过计算属性
来实现。
例如:
<template> <div> {{ reverseString }} </div> </template> <script> export default { name: 'ComputedAndWatch', data() { return { message: 'hello,world!', }; }, computed: { reverseString() { return this.message.split('').reverse().join(''); }, }, }; </script> <style lang="scss" scoped></style>
上面代码中,data中存在一个message
数据,并且存在一个computed
对象,该对象就是计算属性,在其中定义一个reverseString
方法。该方法的主要作用就是将字符串进行反转。
在模板中的{{}}
内,直接使用在computed
中定义好的计算属性。
{{ reverseString }}
最终在页面中就会把计算属性方法的返回值渲染到页面中。
计算属性和方法的区别
计算属性和方法的区别体现在两个方面,一方面是使用方式和定义方式的不同。另外一方面是执行机制的不同。
定义方式和使用方式
在vue中,方法定义在methods
对象中,而计算属性定义在computed
中。在使用的过程中,方法的调用需要在名称的后面加上括号,而计算属性不需要。
下面的代码中将之前的反转字符串的例子在方法中和计算属性中分别实现一次,并且同时在{{}}
中调用。
<template> <div> {{ reverseString }} {{ reverseStringFn() }} </div> </template> <script> export default { name: 'ComputedAndWatch', data() { return { message: 'hello,world!', }; }, methods: { reverseStringFn() { return this.message.split('').reverse().join(''); }, }, computed: { reverseString() { return this.message.split('').reverse().join(''); }, }, }; </script> <style lang="scss" scoped></style>
执行机制
计算属性和方法的第二个区别,还体现在执行机制上的不同。如果重复的实现功能,无论是计算属性还是方法,都需要重复调用。但是,方法会随着每次重复调用,不断的重复执行内部的代码。而计算属性则存在缓存机制。
计算属性的缓存机制是基于它们的响应式依赖进行缓存的。也就是说,只有相关的响应式数据发生改变时,才会重新执行代码,否则就只会使用缓存中的值。
计算属性的getter和setter
计算属性可以设置getter
和setter
。
如下:
computed: { // reverseString() { // return this.message.split('').reverse().join(''); // }, reverseString: { get() { return this.message.split('').reverse().join(''); }, set(newValue) { this.message = newValue; }, }, },
侦听器
vue中还提供了另外一种更加直观的监听数据变化的方式:侦听器。通过侦听器可以随时监听数据的变化,从而做出应对措施。
比如:
<template> <div> </div> </template> <script> export default { name: 'ComputedAndWatch', data() { return { message: 'hello,world!', }; }, mounted() { setTimeout(() => { this.message = '哈哈哈'; }, 3000); }, watch: { message(newValue, oldValue) { console.log( `message的值发生了变化。之前的值是${oldValue}, 最新的值是${newValue}` ); }, }, }; </script> <style lang="scss" scoped></style>
在上面的代码中,在mounted
钩子函数中,设置了一个定时器,3s后将message的值改为一个新的值。而在代码中同时设置了message这条数据的侦听器。
侦听器内部的函数中会收到两个参数,分别是改变后的新值和改变前的旧值。当定时器触发,message的值发生改变之后,侦听器内部对应message的函数就会立刻执行。
在某些场景下,计算属性的效果往往比侦听器要更理想。
当需要在数据变化时执行异步或开销较大的操作时,侦听器的方式是比较有用的。
Class 与 Style 绑定
在通过vue开发项目的过程中,操作元素的class和style是非常常见的操作,同样也是数据绑定的常见需求。因为class和style属性都属于attribute
,所以可以通过v-bind
进行绑定。
字符串拼接
在进行class和style绑定的时候,可以通过字符串拼接的形式来构成表达式。
<template> <div> <div :class="str1 + str2">hello,world!</div> <div :style="str3 + str4">字符串拼接</div> </div> </template> <script> export default { name: 'ClassAndStyle', data() { return { str1: 'header', str2: 'Top', str3: 'color:', str4: 'red', }; }, }; </script> <style lang="scss" scoped></style>
上面代码在渲染后,div
生成的类名就为headerTop
,生成的style
为:color:red
。
绑定HTML Class
对象语法
可以给class
动态绑定一个对象,在对象中设置不同的类名。
<template> <div> <div :class="classObj">绑定HTML Class</div> </div> </template> <script> export default { name: 'ClassAndStyle', data() { return { classObj: { headerTop: true, container: false, }, }; }, }; </script> <style lang="scss" scoped></style>
上面的代码渲染完成后,div的class
类名为headerTop
。
当classObj
中的值发生变化后,页面视图中的类名也会自动发生变化。
如果在设置类名的时候,需要采用中横线的形式,例如
header-top
这种写法,那么就需要将对象的key设置为一个字符串:'header-top': false
。
在绑定class时,也可以采用计算属性的方式:
<template> <div> <div :class="bindClass">通过计算属性来绑定class</div> </div> </template> <script> export default { name: 'ClassAndStyle', computed: { bindClass() { return 'container'; }, }, }; </script> <style lang="scss" scoped></style>
上面代码中,将计算属性绑定在class的值上面。计算属性的返回值就会变成class的值。
数组语法
在对class
进行绑定的时候,也可以将class的值帮定为一个数组,例如:
<template> <div> <div :class="[activeClass, errorClass]">绑定数组</div> </div> </template> <script> export default { name: 'ClassAndStyle', data() { return { activeClass: 'active', errorClass: 'text-danger', }; }, }; </script> <style lang="scss" scoped></style>
最终渲染的结果为:class="active text-danger"
。
在数组中也可以通过三元表达式动态切换类名。
<div v-bind:class="[isActive ? activeClass : '', errorClass]"></div>
如果三元表达式无法满足需求,也可以在数组中以对象的形式来设置类名。
<template> <div> <div :class="[ { active: isActive, error: isError }, navClass, 'container', ]" ></div> </div> </template> <script> export default { name: 'ClassAndStyle', data() { return { navClass: 'nav', isActive: true, isError: false, }; }, }; </script> <style lang="scss" scoped></style>
上面代码经过处理,最终的类名为:class="active nav container"
。
绑定在组件上
当把class
绑定到组件上的时候,class
将被添加到组件的根元素上。
如果组件的身上本来就有类名,并不会在渲染的时候覆盖,而是都会存在。
绑定内联样式
对象语法
在给style
属性通过v-bind
进行样式绑定的时候,可以直接以对象的形式进行绑定。
<template> <div> <div :style="styleObj">动态绑定样式</div> </div> </template> <script> export default { name: 'ClassAndStyle', data() { return { styleObj: { width: '200px', height: '200px', backgroundColor: 'pink', fontSize: '16px', }, }; }, }; </script> <style> </style>
上面的代码中,给div通过v-bind
绑定了一个样式对象,其中包括width
、height
、background-color
和font-size
等内容。
需要注意的是,虽然样式对象看上去很像css
。但是并不完全一样,例如css
中background-color
在样式对象中的写法是backgroundColor
,采用的是小驼峰的写法,而这也是在绑定样式对象的时候设置由多个单词构成的样式属性时的写法。
和绑定HTML Class一样,也可以使用计算属性来绑定样式。
数组语法
如果想要将多个表示style样式的对象共同使用,可以绑定一个数组。
<template> <div class="header"> <div :style="[styleObj, baseStyle]">利用数组进行样式对象绑定</div> </div> </template> <script> export default { name: 'ClassAndStyle', data() { return { styleObj: { width: '200px', height: '200px', backgroundColor: 'pink', fontSize: '16px', }, baseStyle: { color: 'blue', }, }; }, }; </script>
如上的代码,div在渲染完成后,它的样式就包括styleObj
中的内容和baseStyle
中的内容。
自动添加前缀
vue会自动侦测绑定的属性,哪些需要使用浏览器前缀,并且主动帮属性加上前缀。
多重值
vue允许为一个属性设置多种可能性的值。
<div :style="{ display: ['-webkit-box', '-ms-flexbox', 'flex'] }"> 给属性设置多种可能性的值 </div>
条件渲染
vue中支持根据条件的结果来进行渲染。可以通过v-if
和v-show
来进行条件性的渲染。
<template> <div> <div v-if="loginStatus"> 已登录,欢迎<span v-show="loginStatus">{{ user }}</span> </div> <div v-else>尚未登录,请重新登录</div> </div> </template> <script> export default { name: 'ShowAndIf', data() { return { loginStatus: true, user: '张三', }; }, }; </script> <style lang="scss" scoped></style>
loginStatus
结果为true时,绑定了v-if
和v-show
的div会显示出来,当值为false
时,元素则会在渲染的时候消失。
虽然v-if
和v-show
都能够让元素显示和消失,但是二者是存在区别的。
v-if
的值为false时,元素是直接在网页中被删除,而v-show
的值为false时,元素虽然消失,但是在网页的源码中还是存在的,效果相当于设置了display:none
。
元素复用
Vue为了提高渲染元素速度,通常会复用已有元素。比如,
<template v-if="loginType === 'username'"> <label>Username</label> <input placeholder="Enter your username"> </template> <template v-else> <label>Email</label> <input placeholder="Enter your email address"> </template>
如果想要让input
不在复用,可以给元素加上一个key
。
<template v-if="loginType === 'username'"> <label>Username</label> <input placeholder="Enter your username" key="username-input"> </template> <template v-else> <label>Email</label> <input placeholder="Enter your email address" key="email-input"> </template>
这样通过key
告诉vue
,两个元素是完全独立的,并不需要进行复用。
v-if和v-show的区别:
v-if
是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。
v-if
也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。
相比之下,v-show
就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。
一般来说,v-if
有更高的切换开销,而 v-show
有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show
较好;如果在运行时条件很少改变,则使用 v-if
较好。
列表渲染
可以通过v-for
进行列表渲染。
<template> <div> <ul> <li v-for="item in list" :key="item.id">{{ item.title }}</li> </ul> </div> </template> <script> export default { name: 'ShowAndIf', data() { return { list: [ { id: '0190', title: 'html5' }, { id: '0210', title: 'css3' }, { id: '0870', title: 'javascript' }, { id: '0330', title: 'vue' }, ], }; }, }; </script> <style lang="scss" scoped></style>
在使用
v-for
进行循环渲染的时候,要设置key
保证渲染的高效性。
key
应该是独一无二。
事件处理
绑定事件
当需要把事件绑定到元素身上的时候,可以使用v-on
指令监听事件。
<div> <button v-on:事件="表达式或者函数调用"> 点击 </button> </div>
例如下面的代码,通过v-on
绑定事件,v-on
指令可以简写为@事件
。
<template> <div> <button v-on:click="count++">Clik1</button> <button v-on:click="sayHello">Click2</button> </div> </template> <script> export default { name: 'EventDemo', data() { return { count: 1, }; }, methods: { sayHello() { console.log(this.count); }, }, }; </script> <style lang="scss" scoped></style>
可以在绑定事件处理函数时传递参数:
<button v-on:click="sayHello('hello,vue')">Click2</button>
在事件处理函数中接收参数:
methods: { sayHello(string) { console.log(string) } }
如果想要传递event
对象,可以把$event
在调用函数的时候传递进去。
<button v-on:click="sayHello('hello,vue', $event)">Click2</button>
methods: { sayHello(string, event) { console.log(string); console.log(event); } }
事件修饰符
vue提供了一些事件修饰符,帮助解决一些在事件中经常出现的需求,例如事件冒泡、阻止默认行为等等。
常见的事件修饰符:
.stop
阻止冒泡.prevent
阻止默认行为.capture
事件捕获.self
当触发事件的元素是事件源时触发.once
只触发一次事件.passive
设置为true时,表示 listener 永远不会调用 preventDefault()。在移动端能提高性能。
按键修饰符
在监听键盘事件时,v-on
允许使用一些修饰符:
- .enter
.page-down
.delete
.tab
.esc
.space
.up
.down
.left
.right
.ctrl
表单输入绑定
基础
vue允许使用v-model
在input
、textarea
、select
元素上创建双向数据绑定。
本质就是语法糖。
v-model
会忽略所有表单元素的value
、checked
、selected
attribute的初始值而总是将vue实例的数据作为数据来来源。
v-model
在内部为不同的输入元素使用不同的 property 并抛出不同的事件:
- text 和 textarea 元素使用
value
property 和input
事件; - checkbox 和 radio 使用
checked
property 和change
事件; - select 字段将
value
作为 prop 并将change
作为事件。
在绑定过程中,需要注意:
- 如果和
textarea
进行绑定,那么应该使用v-model
以attribute
的形式进行绑定,而不是在textarea
标签内部通过{{}}
的形式进行绑定。 - 如果是多选,则需要在
data
中设置一个array
。 - 单选和多选的绑定,要保证
name
值相同,如果不同的话会被理解为不是一组选项。 select
下拉框在进行绑定的时候,应该添加一项处于禁用状态的option
,该选项作用是起到一个提示作用,这项处理可以避免在ios
端第一项无法选择的问题。select
下拉框如果处于多项选择状态,v-model
绑定的值同样需要设置为一个数组。- 在进行多选框绑定的时候,还可以通过设置
true-value
和false-value
两个属性值。意思是选中时的值和未选中时的值。 - 下拉框的
option
的value
值也可以使用v-bind
进行动态绑定。
修饰符
.lazy
在进行v-model
双向数据绑定的时候,默认情况下监听的是input
事件,可以通过加上.lazy
修饰符,将监听的事件改为change
事件。
<!-- 在“change”时而非“input”时更新 --> <input v-model.lazy="msg">
这样做的好处是能大大减少请求次数。
.number
.number
修饰符可以将输入框中的值通过parseFloat
进行转换,如果无法转换,则会返回原始值。
.trim
.trim
修饰符会自动过滤用户输入的首位空白字符。
组件基础
全局组件和局部组件的注册
可以通过Vue.component()
来定义全局组件。也可以以变量的形式定义局部组件。
// 定义一个名为 button-counter 的新组件 Vue.component('button-counter', { data: function () { return { count: 0 } }, template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>' })
定义的全局组件可以在vue
代码的任何位置进行使用。
const Counter = { template: `<div>我是Counter组件</div>` }
Counter
组件被定义成为一个局部组件,这个 局部组件想要使用,需要在父组件中进行注册。
{ ... components: { Counter } }
只有注册过的局部组件才能使用。
定义组价的目的,是为了复用。
因为组件是可复用的vue实例,所以在组件中可以接收与
new Vue
相同的选项。
data函数
为了保证数据的独立性,所以在定义组件的时候,组件的data
选项必须是一个函数。
{ data() { return {} } }
向子组件传值
在父组件中,可以通过prop
向子组件中传值。
例如:
父组件:
<template> <div> <TestDemo message="Hello,我是父传子传递的数据"></TestDemo> </div> </template> <script> import TestDemo from './TestDemo.vue'; export default { name: 'ComponentDemo', components: { TestDemo }, }; </script> <style lang="scss" scoped></style>
子组件:
<template> <div> <div>父组件向子组件中传递的数据: {{ message }}</div> </div> </template> <script> export default { name: 'TestDemo', props: ['message'], }; </script> <style lang="scss" scoped></style>
父组件中以attribute
的形式向子组件中传递了数据,而子组件中通过props
属性接收了传递过来的数据。
上面子组件中使用的props的值是一个数组,数组中的元素内容即为传递过来的值。
除了向子组件传递一个单独的值,也可以传递一组更为复杂的数据,并且通过v-for
的形式来循环渲染组件。
例如:
父组件
<template> <div> <ArticleItem v-for="item in articleList" :key="item.id" :title="item.title" :content="item.content"></ArticleItem> </div> </template> <script> import ArticleItem from './ArticleItem.vue' export default { name: 'ComponentDemo', components: { ArticleItem }, data() { return { articleList: [ {id: '0100', title: '测试文档1', content: '测试1测试1测试1测试1测试1测试1测试1测试1测试1测试1'}, {id: '0290', title: '测试文档2', content: '测试2测试1测试1测试1测试1测试1测试1测试1测试1测试1'}, {id: '012100', title: '测试文档3', content: '测试3测试1测试1测试1测试1测试1测试1测试1测试1测试1'}, {id: '0109900', title: '测试文档4', content: '测试4测试1测试1测试1测试1测试1测试1测试1测试1测试1'}, {id: '0109190', title: '测试文档5', content: '测试5测试1测试1测试1测试1测试1测试1测试1测试1测试1'}, ] } }, }; </script> <style lang="scss" scoped></style>
子组件:
<template> <div> <h3>{{ title }}</h3> <p>{{ content }}</p> </div> </template> <script> export default { name: 'ArticleItem', props: ['title', 'content'], }; </script> <style lang="scss" scoped></style>
上面的代码中,在父组件里面定义了一个数组,数组中包含了所需要的数据,然后通过v-for
的形式循环遍历子组件,并且将数组中的数据逐一的传递给子组件。
需要注意的是,在组件中,最上层的父元素一定要唯一。也就是说要保证单一父元素。
监听子组件事件
在vue的组件中,存在单向数据流这个概念。
什么意思呢?简单的说,就是父组件中传递给子组件中的数据,子组件是不能修改的。如果想要修改,必须要将这个需求提交给父组件,然后由父组件进行修改。
例如:
父组件:
<template> <div> <ClickUpdateFontSize :size="size" @add="handleClick"></ClickUpdateFontSize> </div> </template> <script> import ClickUpdateFontSize from './ClickUpdateFontSize.vue' export default { name: 'ComponentDemo', components: { ClickUpdateFontSize }, data() { return { size: 12 } }, methods: { handleClick() { this.size += 1 } }, }; </script> <style lang="scss" scoped></style>
子组件:
<template> <div> <div :style="{fontSize: size+ 'px'}">Hello,Components</div> {{size}} <button @click="addFs">点击增大1px字体</button> </div> </template> <script> export default { name: 'ClickUpdateFontSize', props: ['size'], methods: { addFs() { this.$emit('add') } }, } </script> <style lang="scss" scoped> </style>
在上面代码中,父组件向子组件传递了一个数值,该数值被子组件以props
接收,收到之后将这个值作为内容的字体大小的属性值。
当点击子组件中的按钮时,会向父组件通过$emit
触发一个自定义事件add
。而在父组件当中,在监听到子组件传递过来的自定义事件之后,直接将size
值进行递增修改。数据发生变化,自然子组件中的视图也就会发生改变。
使用事件抛出一个值
在子组件中触发一个自定义事件时,可以同时携带一个值。
methods: { addFs() { this.$emit('add', 2) } },
在子组件中触发事件的同时传递了一个值。
在父组件中接收一个值。
handleClick(num) { this.size += num }
如果在事件处理函数中想要使用
event
,可以直接打印。
在组件上使用v-model
上面说v-model
其实是语法糖,例如使用v-model
绑定一个input
,其实就相当于是动态绑定了value
和监听了input
事件。
根据这个原理,只要在组件内部实现了value
和input
事件的处理,那么在父组件中就可以使用v-model
对子组件进行动态绑定。
例如:
子组件当中:
<template> <div> <input type="text" v-bind:value="value" @input="$emit('input', $event.target.value)" /> </div> </template> <script> export default { name: 'VModelDemo', props: ['value'], }; </script> <style lang="scss" scoped></style>
父组件当中:
<template> <div> <VModelDemo v-model="message"></VModelDemo> {{message}} </div> </template> <script> import VModelDemo from './VModelDemo.vue'; export default { name: 'ComponentDemo', components: {VModelDemo }, data() { return { message: 'hello,world' } }, }; </script> <style lang="scss" scoped></style>
上面代码中,在子组件里面实现了value
的绑定和input
事件的监听,父组件也就自然而然的能够使用v-model
在子组件的身上进行值的动态绑定。
通过插槽分发内容
在使用子组件的时候,如果需要向子组件中传递内容,可以使用插槽。
<counter>我是传递的内容</counter>
而想要正确的显示传递的内容,就需要在子组件中使用插槽。
父组件:
<template> <div> <SlotComponents>哈哈哈哈</SlotComponents> </div> </template> <script> import SlotComponents from './SlotComponents.vue' export default { name: 'SlotDemo', components: {SlotComponents} } </script> <style lang="scss" scoped> </style>
子组件:
<template> <div> <div> 我是子组件: <slot></slot> </div> </div> </template> <script> export default { name: 'SlotComponents', }; </script> <style lang="scss" scoped></style>
动态组件
可以利用component
标签身上的is
属性来动态的切换组件。
父组件:
<template> <div> <button @click="componentsName = 'C1'">组件1</button> <button @click="componentsName = 'C2'">组件2</button> <button @click="componentsName = 'C3'">组件3</button> <component :is="componentsName"></component> </div> </template> <script> import C1 from './C1Component.vue'; import C2 from './C2Component.vue'; import C3 from './C3Component.vue'; export default { name: 'IsComponents', components: { C1, C2, C3 }, data() { return { componentsName: 'C1', }; }, }; </script> <style lang="scss" scoped></style>
子组件:
<template> <div> 组件1 </div> </template> <script> export default { name: 'C1Component' } </script> <style lang="scss" scoped> </style>
<template> <div> 组件2 </div> </template> <script> export default { name: 'C2Component' } </script> <style lang="scss" scoped> </style>
<template> <div> 组件3 </div> </template> <script> export default { name: 'C3Component' } </script> <style lang="scss" scoped> </style>
解析DOM模板时注意事项
有些 HTML 元素,诸如 <ul>
、<ol>
、<table>
和 <select>
,对于哪些元素可以出现在其内部是有严格限制的。而有些元素,诸如 <li>
、<tr>
和 <option>
,只能出现在其它某些特定的元素内部。
这会导致我们使用这些有约束条件的元素时遇到一些问题。例如:
<table> <blog-post-row></blog-post-row> </table>
这个自定义组件 <blog-post-row>
会被作为无效的内容提升到外部,并导致最终渲染结果出错。幸好这个特殊的 is
attribute 给了我们一个变通的办法:
<table> <tr is="blog-post-row"></tr> </table>
需要注意的是如果我们从以下来源使用模板的话,这条限制是*不存在*的:
- 字符串 (例如:
template: '...'
) 单文件组件(.vue)
<script type="text/x-template">
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战