vue组件化开发

1.组件化开发

1.1 组件化的基本使用

​ 简单的组件示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<div id="app">
<!-- 使用组件 -->
<my-cpn></my-cpn>
<my-cpn></my-cpn>
<my-cpn></my-cpn>
<cpnc></cpnc>
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<script>
// 1.创建组件构造器对象
const cpnc = Vue.extend({
template:`
<div>
<h2>标题</h2>
<p>内容1...<p>
<p>内容2...<p>
</div>`
})
// 2.全局注册组件,其他任何地方都可以使用
Vue.component('my-cpn', cpnc)
const app = new Vue({
el:"#app",
data:{
},
components:{//局部组件创建,只有本app组件可以使用
cpnc:cpnc
}
})
</script>

组件是可复用的 Vue 实例,且带有一个名字:在这个例子中是 my-cpn。我们可以在一个通过 new Vue 创建的 Vue 根实例中,把这个组件作为自定义元素来使用: <my-cpn></my-cpn>

1.1.1 创建组件构造器对象

template中是组件的DOM元素内容。

1.1.2 注册组件

  • 全局注册 Vue.component('给组件取得名字', 组件对象)

可以在多个vue实例中使用,类似于全局变量。

  • 局部注册 components:{'给组件取得名字', 组件对象}

只能在当前vue实例挂载的对象中使用,类似于局部变量,有块级作用域。

1.1.3 使用组件

<给组件起的那个名字></给组件起的那个名字>

补充:注册组件的语法糖

注册组件时候可以不实例化组件对象,直接在注册的时候实例化。{}就是一个组件对象,如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<div id="app">
<cpn1></cpn1>
<cpn2></cpn2>
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<script>
// 1.注册全局组件语法糖
Vue.component('cpn1', {
template:`
<div>
<h2>全局组件语法糖</h2>
<p>全局组件语法糖</p>
</div>`
})

const app = new Vue({
el:"#app",
components:{//局部组件创建
cpn2:{
template:`
<div>
<h2>局部组件语法糖</h2>
<p>局部组件语法糖</p>
</div>`
}
}
})
</script>

1.2 组件模板分离的写法

为了不在js代码中写很多html代码,将组件模板抽离出来

1.2.1 script标签

使用script标签定义组件的模板,script标签注意类型是text/x-template

1
2
3
4
5
6
7
<!-- 1.script标签注意类型是text/x-template -->
<script type="text/x-template" id="cpn1">
<div>
<h2>组件模板的分离写法</h2>
<p>script标签注意类型是text/x-template</p>
</div>
</script>

1.2.2 template标签(重要!)

​ 使用template标签,将内容写在标签内。

1
2
3
4
5
6
7
<!-- 2.template标签 -->
<template id="cpn2">
<div>
<h2>组件模板的分离写法</h2>
<p>template标签</p>
</div>
</template>

1.2.3 进一步分离

如上图所示,那么实际上可以把绿色部分的那部分代码保存到另外一个js文件中,然后在本文件中引入即可。

需要注意的是:直接用浏览器打开index.html看不到效果(会出现跨域问题),需要开启一个服务器

1
2
npm install http-server
http-server . -p 8080

还是不够好,在cpn.js中模板和js代码还是在一起,没有分离,那么终极大法来了,接着看。

1.2.4 终极大法(.vue文件来了)

1.3 为什么组件的data必须要是函数?

来,先看效果(需要http-server)

图中可以看到,不使用data的好像共用一个count属性,而使用函数的data的count是各自用各自的,像局部变量一样有块级作用域,这个块级就是vue组件的作用域。

我们在复用组件的时候肯定希望,各自组件用各自的变量,如果确实需要都用一样的,可以全局组件注册,也可以是用vuex来进行状态管理

1.4 父组件向子组件传值

  • 子组件中使用props属性

props属性使用

数组写法

1
props: ['cmovies', 'cmessage']

对象写法

1
2
3
4
5
6
7
props: { 
cmessage: {
type: String,
default: 'zzzzz',
required: true //在使用组件必传值
}
}

props属性的类型限制

1
2
3
4
//1.类型限制(多个类使用数组)
cmovies:Array,//限制为数组类型
cmessage:String,//限制为Strin类型
cmessage:['String','Number']//限制为String或Number类型

props属性的默认值

1
2
3
4
5
// 2.提供一些默认值,以及必传值
cmessage: {
type: String,
default: 'zzzzz',//默认值
}

props属性的必传值

1
2
3
4
5
cmessage: {
type: String,
default: 'zzzzz',
required: true //在使用组件必传值
}

类型是Object/Array,默认值必须是一个函数

1
2
3
4
5
6
7
//类型是Object/Array,默认值必须是一个函数
cmovies: {
type: Array,
default () {
return [1, 2, 3, 4]
}
},

自定义验证函数

1
2
3
4
vaildator: function (value) {
//这个传递的值必须匹配下列字符串中的一个
return ['zzzzz', 'ttttt', 'yyy'].indexOf(value) !== -1
}

自定义类型

1
2
3
4
5
   function Person(firstName,lastName) {
this.firstName = firstName
this.lastName = lastName
}
cmessage:Person//限定了cmessage必须是Person类型

1.5 子组件向父组件传值 (观察者模式的使用)

  • 子组件中使用this.$emit('方法名',要传递数据)

原理:父组件将方法的引用,传递到子组件内部,子组件在内部调用父组件传递过来的方法,同时把要发送给父组件的数据,在调用方法的时候当作参数传递进去。

1.6 使用ref获取DOM元素和组件引用

Vue属于MVVM框架,也就是数据驱动框架,所以通常是以数据驱动的形式去开发,它就是为了尽最大努力地避免DOM操作,解放程序员的双手。但是,有时候,我们不可避免地会进行DOM操作,那么Vue也提供了ref属性来直接获取DOM元素。

文章作者: 小王同学
文章链接: https://morvan.top/2021/12/07/vue组件化开发/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 小王同学的精神驿站