加载中...

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中要进行绑定的变量的值为nullundefinedfalse,那么标签上进行动态绑定值的属性将不会渲染出来。

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-bindv-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

计算属性可以设置gettersetter

如下:

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 :>hello,world!</div>
<div :>字符串拼接</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 :>绑定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</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 :>绑定数组</div>
</div>
</template>
<script>
export default {
name: ''ClassAndStyle'',
data() {
return {
activeClass: ''active'',
errorClass: ''text-danger'',
};
},
};
</script>
<style lang="scss" scoped></style>

最终渲染的结果为:

在数组中也可以通过三元表达式动态切换类名。

<div v-bind:></div>

如果三元表达式无法满足需求,也可以在数组中以对象的形式来设置类名。

<template>
<div>
<div
:hljs-ln-line hljs-ln-numbers" data-line-number="5">
{ 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绑定到组件上的时候,class将被添加到组件的根元素上。

如果组件的身上本来就有类名,并不会在渲染的时候覆盖,而是都会存在。

绑定内联样式

对象语法

在给style 属性通过v-bind 进行样式绑定的时候,可以直接以对象的形式进行绑定。

<template>
<div>
<div :>动态绑定样式</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绑定了一个样式对象,其中包括widthheightbackground-colorfont-size 等内容。

需要注意的是,虽然样式对象看上去很像css。但是并不完全一样,例如cssbackground-color在样式对象中的写法是backgroundColor,采用的是小驼峰的写法,而这也是在绑定样式对象的时候设置由多个单词构成的样式属性时的写法。

和绑定HTML Class一样,也可以使用计算属性来绑定样式。

数组语法

如果想要将多个表示style样式的对象共同使用,可以绑定一个数组。

<template>
<div >
<div :>利用数组进行样式对象绑定</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 :>
给属性设置多种可能性的值
</div>

条件渲染

vue中支持根据条件的结果来进行渲染。可以通过v-ifv-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-ifv-show的div会显示出来,当值为false时,元素则会在渲染的时候消失。

虽然v-ifv-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-modelinputtextareaselect元素上创建双向数据绑定。

本质就是语法糖。

v-model会忽略所有表单元素的valuecheckedselected attribute的初始值而总是将vue实例的数据作为数据来来源。

v-model 在内部为不同的输入元素使用不同的 property 并抛出不同的事件:

  • text 和 textarea 元素使用 value property 和 input 事件;
  • checkbox 和 radio 使用 checked property 和 change 事件;
  • select 字段将 value 作为 prop 并将 change 作为事件。

在绑定过程中,需要注意:

  • 如果和textarea进行绑定,那么应该使用v-modelattribute的形式进行绑定,而不是在textarea标签内部通过{{}}的形式进行绑定。
  • 如果是多选,则需要在data中设置一个array
  • 单选和多选的绑定,要保证name值相同,如果不同的话会被理解为不是一组选项。
  • select 下拉框在进行绑定的时候,应该添加一项处于禁用状态的option,该选项作用是起到一个提示作用,这项处理可以避免在ios端第一项无法选择的问题。
  • select下拉框如果处于多项选择状态,v-model绑定的值同样需要设置为一个数组。
  • 在进行多选框绑定的时候,还可以通过设置true-valuefalse-value两个属性值。意思是选中时的值和未选中时的值。
  • 下拉框的optionvalue值也可以使用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 :>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事件。

根据这个原理,只要在组件内部实现了valueinput事件的处理,那么在父组件中就可以使用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">