文章目录
介绍Vue
该部份将视角放在一个vue示例上,介绍vue是什么,并且给出vue应用和组件的实例代码。
vue是什么?
vue是一套用于构建用户界面的,自底向上的js框架
vue通过什么方式来构建应用?
通常一个应用会以一棵嵌套的组件树的形式来组织,Vue也是通过组件的方式来构建。组件可以是一个按钮,一个输入框,也可以是这些最小组件的嵌套,组件和组件之间通过vue之间实现的逻辑来传递数据。
Vue中的组件到底是什么?
开头说了,一个应用都可以通过一棵嵌套的组件树的形式来组织。而一般情况下,在一个应用中创建组件,有两种情况:全局组件和局部组件。
-
一种是按钮,输入框这种,统一了样式后,在全局都需要使用这一套样式的,称为全局组件;
-
而像一些固定的分组,如QQ中聊天窗的
聊天框
,只在聊天页面中需要用到,其他地方都不需要用到,因此没有必要让全局所有的其他组件都可以使用到聊天框
这个组件,这种组件就称为局部组件。
vue中的组件也是这样,以输入框,按钮这样的最小的界面为组件,同时支持嵌套来构成一个大组件。当然,vue也同时支持上面提到的这两种组件的注册方式
举一个例子,QQ中一个聊天页面就可以作为一个组件,这个组件同时嵌套了输入框,发送按钮,标题,聊天框等其他小组件,而其他的小组件又包含了更小的组件,直到达到了最底层。
vue如何创建一个新的应用?
最简单的方式,新建一个html文件:
<!DOCTYPE html>
<script> src="js/vue.js" </script>
<body>
<!--这是我们的View-->
<div id="app">
{{ message }}
</div>
</body>
<script>
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
}
})
</script>
</html>
其中,id="app"
的div
块即为vue应用渲染的部份,同时这个应用界面需要的信息不需要写在界面中,而是由vue实例来提供。
在后面会看到,不仅仅消息不需要提供,应用能够触发的所有事件,都是可以在vue实例中进行处理。
这种构建方法有什么好处?
当上面的应用被构建后,数据和 DOM 都已经被建立了关联,所有东西都是响应式的,即只要数据更新,界面就会产生我们设定好的更改。这样当我们声明好了逻辑后,我们就可以将注意力拿来更多的去关注数据层面的变动。这是非常友好的将数据与业务逻辑分离的方式。
Vue中的组件和Vue的应用有什么不同?
根据官方教程文档:每个 Vue 应用都是通过用 Vue 函数创建一个新的 Vue 实例开始的。
而同时,组件也是可复用的 Vue 实例,如下图,也即:vue应用就是一个包含了多个组件的大组件。
当然,应用实例和组件实例还是有一些不同,比如构造方法,比如构造数量等,具体可以看相关的分析文档,需要在具体实践的时候区分。
vue中的组件如何声明?
在说明vue中的组件包含哪些内容之前,需要想明白组件是用来做什么事的:
- 对于一些标签,文本区域,需要显示信息,同时这些信息一般不能硬编码在组件中,需要从数据区域中获取。
- 对于一些选择框,按钮,输入框,需要接收信息,同时接收后一般需要做一些相应的处理,传递给后台或经过某些处理后让其他的组件做出一部分反应。
上述的两种行为基本描述了组件的作用,再概括一点,也就是:显示信息,接受交互并触发信息传递事件,处理信息,向其他组件传递信息
排除上述几个最硬核的业务需求,还需要照顾到用户需求,因此还需要让组件足够美观
现在回过头来看vue中的组件,分为三个区域,分别对应了html、js、css,其中css起到的是额外的装饰作用,html用来显示信息的同时接受交互并触发信息传递事件,js部份用来处理信息并 向其他组件传递信息。
下面的例子展示了一个局部组件是如何定义的,注意其中各部分的作用已经详细进行了注释:
Temp.vue
<template>
<div class="temp">
<div>
<!--显示来自自己组件的信息-->
{{msg}}
</div>
<div>
<!--显示来自其他组件的信息-->
{{fromothers}}
</div>
<!--触发事件调用自己组件的方法'clickipt()'-->
<button v-on:click="clickipt"></button>
</div>
</template>
<script>
export default {
name: "temp",// 该组件的名字
props: ["fromothers"], // 来自其他组件的信息
data() {
return {
msg: "hello world!" // 自己组件提供给自己组件的信息
}
},
methods: {
clickipt() {
alert("click button");
this.$emit("trans-func", "to other component"); // 传递给其他组件的信息/数据
}
}
}
</script>
<style scoped>
</style>
注意到组件的声明中,data属性是通过方法的形式来声明,这对于组件来说是必需的,而对于应用实例来说,则不是必需的。
最后,组件应该还能够重复使用,即组件应该对应于一个"类",组件在具体的应用中可以被重复使用,相应的,叫做组件实例
那么全局组件如何声明?
<script>
Vue.component('button-counter', {
data: function () {
return {
count: 0
}
},
template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>'
})
</script>
可以看到,全局组件全部声明在<script>
块中,其中第一个参数对应了局部组件中的name
,第二个参数对应了局部组件中export default
中的其他内容。
数据与事件传输
本篇将视角扩大,放到vue的组件与组件之间,介绍vue组件如何获取数据和如何在组件之间传递数据。
组件的DOM如何获取数据?
vue组件获取数据的来源有两个:
- 从自己的组件实例中直接标明数据属性
data
,如上面例子中的data
中的属性。(另外还存在计算变量(通过执行方法来返回数据),暂且不提) - 从其他的组件实例中获取
组件DOM如何从自身获取数据?
vue应用示例可以直接通过定义data
属性,在data
属性中包括的所有的属性都可以直接通过在html中使用Mustache语法(双大括号)获取到并显示出来。
<div id="app">
{{ message }}
</div>
<script>
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
}
})
</script>
使用Mustache语法只能显示纯文本,如果要显示渲染html后的语言,则应该使用v-html
关键字,具体可以参考:原始HTML
<span v-html="rawHtml"></span>
同时,像输入框,选择框等,这些DOM组件本身也是一个数据来源,因此vue通过v-model
关键字提供了从DOM中绑定数据来源的方法(vue中称之为双向数据绑定),具体可以参考表单输入绑定
<input v-model="message" placeholder="edit me">
<p>Message is: {{ message }}</p>
获取的数据只能用来显示吗?
实际上获取到的数据,不仅仅可以用来显示数据,还可以用来当做标签的属性名,或者属性值,但和上面的 双大括号的语法(Mustache语法) 不同,vue提供了v-bind
关键字来完成这件事,具体可以参考下面的文档:
第二个链接是因为Class和Style由于其常用性,vue单独做了语法糖
组件如何处理组件自身触发的事件?
像按钮,输入框等,显示在界面上,接收了用户的交互,都会触发一些事件,根据需求其中一些需要在后端做相应的一些处理。
这些事件都可以通过vue来进行处理,使用v-on
关键字,具体参考文档:事件处理
组件如何从其他组件获取数据(通信)?
按照这个逻辑,一般组件之间消息传递,分为几种:
父组件向子组件传递
通过在子组件定义props属性,在父组件中的子组件标签中声明属性名和属性值来传递数据。参考资料:通过 Prop 向子组件传递数据
子组件
<script>
Vue.component('blog-post', {
props: ['title'], // 声明了title属性
template: '<h3>{{ title }}</h3>'
})
<script>
父组件
<!--在父组件中定义了title属性并传入了相应的值-->
<blog-post title="My journey with Vue"></blog-post>
<blog-post title="Blogging with Vue"></blog-post>
<blog-post title="Why Vue is so fun"></blog-post>
注意这只是简单的传递数据的例子,实际过程中,属性值的绑定在前面介绍过了,也是可以通过vue来实现动态获取的(
v-bind
)
子组件向父组件传递
通过在父组件中注册事件,在子组件中调用该事件this.$emit(event,data)
来实现。参考资料:监听子组件事件
同级组件之间传递
这一般是通过构建一个中间vue实例来完成消息传递。参考资料:vue组件间通信、数据传递(父子组件,同级组件)
跨层级的组件之间传递
参考同级组件之间传递的方式,这种方式适用于任意组件之间(即包括父子组件之间)
当构建的vue应用复杂的时候,不推荐适用后面提到的这种通信方式,而是推荐使用Vuex
是否有更方便的数据获取与处理方式?
条件与列表渲染
想一下对于一个应用,需要依次迭代来处理数据并显示组件是很常见的(好友列表,文件列表,日历…);同时,组件本身是否显示某种属性的判断,也是需要有的,因此vue提供了两个标签属性来完成这件事情,即条件渲染和列表渲染。参考文档:条件渲染,列表渲染
在文档中提到了一个问题,即
<li>
标签的渲染问题,vue通过引入is
关键字来解决,其作用可以参考:vue中is的作用和用法
计算属性与侦听器
同时,有很多情况下要显示的两个数据之间,是有关联的,比如对一个数组,不仅要显示出来,还要显示出数组长度,对于这两个数据,如果在数据区域依次声明,然后每次变动的时候让方法同时更新这两个属性的做法并不是最好的方法,vue中提供了计算属性和侦听器。
其中计算属性是声明属性arrlen
是计算属性并写好方法,每次调用它的时候,会执行一个方法计算arr
的长度并返回。
var vm = new Vue({
el: '#demo',
data: {
arr:[1,2,3,4],
},
computed: {// 计算属性
arrLen: function () {
return this.arr.length;
}
}
})
插一个题外话,如果之前是Python使用者,其中有一个内置的装饰器
@property
,也是可以将方法封装为属性
而侦听器则是监控某个属性的变化,从而做出相应的更新。
var vm = new Vue({
el: '#demo',
data: {
arr:[1,2,3,4],
arrLen:4,
},
watch: {// 计算属性
arr: function () {
this.arrLen = this.arr.length;
}
}
})
插槽
之前提到过,父组件向子组件传递信息的方式是通过在子组件中声明prop
,然后在父组件添加该组件的时候绑定相应的prop属性来完成,如下:
子组件
<template>
<div>{{fromothers}}</div>
</template>
<script>
export default {
name: "child",// 该组件的名字
props: ["fromothers"], // 来自其他组件的信息
}
</script>
父组件
<template>
<div id="demo">
<child fromothers="someinfo"/>
<child fromothers="someotherinfo"></child>
</div>
</template>
那如果我想在子组件中添加的,不仅仅是数据,还包括一段html,还包括其他的内容呢?能否有更方便的方式?vue提供了名为插槽的语法,充分利用了标签的空间。
即,在子组件的起始标签和结束标签之间填充内容,并在子组件中添加<slot>
标签,就像这样:
子组件
<template>
<div>{{fromothers}}</div>
<slot></slot>
</template>
父组件
<template>
<div id="demo">
<child fromothers="someinfo"/>
<child fromothers="someotherinfo">Content from parent</child>
</div>
</template>
插槽(起始标签和结束标签之间)中可以填充任意内容,甚至可以是一个其他的组件,或模板。具体可以参考文档:插槽
要注意作用域。
总结一下呗?
vue的实例创建分三种,分别是应用实例,全局注册组件,局部注册组件,这三种代码实现上和api会有略微的不同,但均为vue实例。
vue以组件为单位,提供了一整套自底向上构建应用的方式。包括数据获取,事件传递。在数据获取上,vue提供了Mustache语法
,v-html
,v-bind
,v-model
分别实现了从vue实例中获取文本数据,html数据,属性值的获取和从DOM中获取,另外prop-attribute-bind
提供了从父组件获取数据的方法;在事件传递上,vue提供了v-on
,$emit(event,data)
,来传递事件。
此外,为了使vue的使用更加方便,vue还提供了侦听器,计算属性,条件渲染、列表渲染,插槽等语法,这些语法并不是必需的,但是让vue使用起来更简洁方便了。
其他还有什么内容?
首先,vue还有很多其他的可以称得上是高级特性的方法,这部分可以看官网的文档来进一步了解,包括动画,动态/异步组件,混入等。
同时,只通过vue进行完整的开发的不够的,vue还有其他众多的包,如之前提到的用来管理和共享全局数据的vuex
,用来实现路由的vue-route
,用来构建项目模板的vue-cli
等,都需要慢慢的学习。