介绍
现在,随着基于JavaScript的单页应用程序(SPA)和服务器端渲染(SSR)的兴起,可以用JavaScript编写整个前端应用程序,并整洁地管理和维护该应用程序的前端代码。诸如Angular,React和Vue之类的JavaScript框架允许开发人员使用JavaScript编写其整个前端应用程序,包括状态管理,页面路由支持和基于组件的体系结构等。如果像以前要编写40%以上的前端应用程序代码来获取数据和更新DOM,通常情况下,项目开发管理就变得很难控制了。
这些框架要求你在组件和数据驱动方法方面重新考虑你的应用程序,以创建交互式用户界面。因此,你不再需要手动查找Dom元素并用数据更新它,而是将数据放在应用程序的前面和中心,让这些框架处理一些普通的任务,例如使DOM元素与数据保持同步。
这些框架在开发时考虑了不同的理念,并且具有自己的学习曲线。例如,在这三者中,Angular的学习曲线最陡,而Vue则最容易学习和提高生产力。它们都使用基于组件的体系结构。这意味着,你可以在可管理的UI组件中分解整个前端应用程序,然后使用它们来构建应用程序。
总而言之,基于组件的体系结构提供了一种方法,使你的应用程序精简而又无需重复代码,甚至无需重复代码,这使得开发团队易于理解代码。
下面,我们将了解Vue的历史及其生态系统,包括Vue组件的解剖结构以及每个示例的概述。
Vue的历史
Vue由Evan You创建,当时他在google上使用AngularJS 1.0应用程序在Google工作。他创建Vue作为渐进式JavaScript框架和Angular的高性能替代品。
简而言之,术语“渐进式JavaScript框架”意味着你可以在现有Web应用程序中使用Vue,而不会遇到任何麻烦,并根据需要逐步使用框架功能。或者,你可以使用Vue和其他支持库构建整个前端。
Vue(发音/vjuː/
与View类似)是用于构建用户界面的渐进框架。它是从头开始设计的,可以逐步采用,并且可以根据不同的用例轻松地在库和框架之间扩展。它包含一个仅着眼于视图层的可访问的核心库,以及一个支持库的生态系统,可帮助你解决大型单页应用程序中的复杂性。—参考:链接
在成立之初,Vue充分利用了其他库的最佳功能,例如模板语法、双向数据绑定和Angular的指令,React的虚拟DOM实现,所有这些都消除了进行任何繁琐设置的麻烦学习曲线以提高工作效率并减少遇到的烦恼。
Vue的核心是使用响应式数据和更智能的依赖性跟踪来确定需要更新用户界面的哪一部分。通过使用虚拟DOM-Diff技术,Vue可以有效地创建要应用于DOM的最小数量的用户界面更改,然后甚至在眨眼之前就更新用户界面。
Vue生态系统
Vue从成为完整的框架开始已经走了很长一段路。
它具有丰富的官方核心库生态系统,强大的开发人员工具支持,大量的第三方插件,开发人员教程以及成熟的相关组件框架生态系统,例如Vuetify,BootstrapVue,Element,Quasar,NativeScript-Vue等等。你可能要根据应用程序的需求进行选择。
Vue团队维护的一些核心库及其定义如下。
- Vue路由器(https://router.vuejs.org/)Vue路由器是Vue.js的官方路由器。它与Vue.js核心深度集成,使使用Vue.js轻松构建单页应用程序变得轻而易举。
- Vuex(https://vuex.vuejs.org/)Vuex是Vue.js应用程序的状态管理模式+库。它充当应用程序中所有组件的集中存储,其规则确保状态只能以可预测的方式进行更改。
- Vue加载程序(https://vue-loader.vuejs.org)Vue加载程序是用于Webpack的加载程序,可让你以称为单文件组件(SFC)的格式创作Vue组件。webpack和vue-loader的结合为你提供了一个现代,灵活且功能强大的前端工作流,用于编写Vue.js应用程序。
- Vue服务器渲染器(https://ssr.vuejs.org/)Vue服务器渲染器有助于构建同构或通用JavaScript应用程序,该应用程序可在服务器端和客户端上运行,而大多数应用程序代码都是共享和重用的。
- Vue Test Utils(https://vue-test-utils.vuejs.org/)Vue Test Utils是Vue.js的官方单元测试实用程序库。
- Vue Dev开发工具(https://github.com/vuejs/vue-devtools)浏览器devtools扩展,用于调试Vue.js应用程序。
- Vue CLI(https://cli.vuejs.org/)Vue CLI是用于快速Vue.js开发的完整系统。它旨在成为Vue生态系统的标准工具基线。它可以确保各种构建工具与合理的默认设置一起顺利运行,因此你可以专注于编写应用程序,而不必花费大量时间进行配置工作。
Vue组件剖析
简要介绍典型的Vue单个文件组件(SFC)。准确来说,Vue单个文件组件包括三个部分:
- 模板 Template
- 脚本 Script
- 样式 Style
Vue单个文件组件是一个独立的用户界面,它具有自己的HTML标记,用于交互的脚本和用于表示的样式。
模板部分
在模板部分,你可以将HTML标记的代码以及在代码中的脚本部分中定义的任何数据变量或computed属性一起放置。
你应该注意这里的HTML标记是否太长,这通常表明你正在做太多东西,并且必须考虑为此过长内容额外创建子组件。
脚本部分
在脚本部分中,你可以根据需求定义任何本地数据,属性,计算属性,观察程序,方法,Vue生命周期钩子以及任何子组件的注册。
样式部分
最后,样式部分允许你定义组件样式,以使其可以使用普通CSS或使用Less,SCSS预处理器等来呈现。
Vue组件剖析
上面是Vue组件解剖的单页表示,这是骨架组件的要点。
1 <template> 2 <div> 3 <h1> {{ message }} </h1> 4 <div 5 </template> 6 <script> 7 export default { 8 /* Child component registration */ 9 components: {}, 10 11 /* Properties */ 12 props: [], 13 /* Component's local data */ 14 15 data() { 16 return { 17 message: 'Thinking in components' 18 } 19 }, 20 /* Watchers */ 21 watch: {}, 22 23 /* Computed properties */ 24 computed: {}, 25 26 /* Component methods */ 27 methods: { 28 }, 29 30 /* Vue lifecycle hooks: 31 Ref: https://vuejs.org/v2/guide/instance.html#Instance-Lifecycle-Hooks 32 */ 33 created() {}, 34 mounted() {}, 35 updated() {}, 36 destroyed() {} 37 .... 38 } 39 </script> 40 <style scoped> 41 42 </style>
Vue组件示例
Component 组件
本部分允许你注册在模板中使用的子组件。由于Vue允许逐步构建用户界面,因此你可以轻松地创建小的子组件,并使用它们来构建复合的用户界面。
以下是在Vue中定义和注册子组件的方法。
1. 如果要在没有任何构建系统的HTML文件中将带有脚本标记的Vue包含在内,或者正在使用诸如codepen.io,jsFiddle,jsbin等在线编辑器,则可以使用以下语法来定义和注册子组件。这将确保你的子组件已在Vue中全局注册,然后可以在HTML中的任何位置使用它。
/* In HTML file */ // Parent component <div id="app"> <!-- Child component coming right up --> <app-header></app-header> </div> // Child component template <script id="app-header-template" type="text/template"> <div> ... </div> </script> // In script file Vue.component('app-header', { template: '#app-header-template' }) // Parent component which will be mounted // on DOM element with id app new Vue({ /* The element to mount vue component */ el: "#app" })
2. 如果使用Vue CLI生成应用程序,则可以使用以下语法定义和注册子组件。以下语法将导入子组件并将其注册到父组件。
// Using single file component // ChildComponent.vue component file created in components folder <template> <div> ... </div> </template> <script> export default { ... } </script> // Inside Parent.vue <template> <div id="app"> <AppHeader></AppHeader> </div> </template> <script> import AppHeader from "@/components/AppHeader" export default { components: { AppHeader } } </script>
Props 向子组件传递变量
Prop 让你可以在组件上注册的一些自定义 attribute,允许你定义从父级传递到子级组件的变量。你可以定义数组或对象格式的属性。数组格式允许你快速定义Vue组件属性,另一方面,对象格式为你提供了更多选项来更详细地定义组件属性。
// usage // html <div id="app"> <!-- Child component coming right up --> <app-header :title="title" :subtitle="subtitle"> </app-header> </div> // Inside the component // Array format to define component properties Vue.component('app-header', { /* Component template */ template: '#app-header-template', props: ["title", "subtitle"] }) // Inside the component // Object format to define component properties new Vue({ /* The element to mount vue component */ el: "#app", data() { return { title: "Thinking in components", subtitle: "Learn component based design" } } })
通过 props 传递 title 和 subtitle 子组件,:title 和 :subtitle 作为自定义属性, : 表示数据绑定,这个 title 就是子组件 app-header 期望的 prop 变量。
data 数据
定义任何局部变量以向组件提供初始信息,这些信息充当组件的局部状态。
1 // Inside the component 2 // Use data variables to define 3 // initial state of the component 4 data() { 5 return { 6 firstName: 'John', 7 lastName: 'Doe' 8 email: 'john.doe@example.com' 9 } 10 }
Methods 方法
定义方法或事件处理函数。例如:为按钮设置click事件处理程序,并 handleClick 在“方法”部分中定义处理程序。当用户单击按钮时, handleClick 将调用我们的方法。
new Vue({ /* The element to mount vue component */ el: "#app", /* Local state data of the component */ data() { return { headingText: "Thinking in components", leadText: "Learning component based design" } }, /* Component methods */ methods: { handleClick() { window.alert('Do something awsome!') } } })
Computed 属性计算
定义称为计算属性的虚拟函数,您可以在方法或模板中使用它们。默认情况下,Vue会缓存计算属性的输出,因此对计算属性的任何调用都非常高效。
我们使用 betterHeading 计算属性,该属性以大写形式返回 title。
<div id="app"> <div class="jumbotron text-white text-center w-100"> <h1 class="display-4">{{ betterHeading }} </h1> <p class="lead"> {{ leadText }}</p> <p class="lead">Example : Vue component computed properties</p> </div> </div> new Vue({ /* The element to mount vue component */ el: "#app", /* Local state data of the component */ data() { return { headingText: "Thinking in components", leadText: "Learning component based design" } }, computed: { betterHeading: function() { return this.headingText.toUpperCase() } } })
我们也可以从方法中返回大写标题,那么为什么要使用计算属性?计算属性充分利用了Vue的反应性系统和依赖项跟踪,并且其输出被缓存,而方法的输出未被缓存。 betterTitle 计算属性的输出将由Vue缓存,除非更改 data 变量的 headingText 值,否则它将不会重新评估。
Vue生命周期钩子
它们是可用于每个Vue组件的特殊方法。他们让你了解到组件的生命周期事件,如 beforeCreated, created, beforeMounted, mounted, beforeUpdated, updated, beforeDestroyed, destroyed。
new Vue({ el: "#app", data() { return { headingText: '', leadText: '', } }, beforeCreate() { console.log("Before create hook: Component is not created and data variables are not available yet") }, created() { console.log("Created hook: Component is created and data variables are available") }, beforeMount() { console.log("Before mount hook: Component is not mounted on DOM yet") }, mounted() { console.log("Mounted hook: Component is mounted on DOM") this.headingText = "Thinking in components" this.leadText="Learning component based design" }, beforeUpdate() { console.log("Before update hook: Component is not updated yet") }, updated() { console.log("Updated hook: Component is updated") this.$destroy() }, beforeDestroy() { console.log("Before destroy hook: Component is about to be destroyed") }, destroyed() { console.log("Destroyed hook: Component is destroyed") } })
上面代码中使用了所有Vue组件生命周期钩子。由于它们是由Vue自动调用的,因此我们已将信息记录在console中。在此示例中要注意的几件事如下:
- 不能在 beforeCreate 钩子中访问数据变量。
- 如果组件没有模板或DOM元素,则将完全不调用 beforeMount (已安装), beforeUpdate (已更新)钩子。
- 我们正在更新 headingText 和 leadText 变量 mounted 的生命周期挂钩。这样一来,我们就可以触发 beforeUpdate 和 updated 生命周期挂钩,它们分别在Vue更新DOM和更新DOM之后被调用。
- 在更新的生命周期挂钩中,我们正在调用 this.$destroy() 一种特殊的方法来销毁组件。这将触发 beforeDestroy 和 destroyed 生命周期挂钩,分别在Vue销毁组件之前和销毁组件之后调用它们。
watch 属性监视
用于监视属性,变量或计算的属性,如果你需要在属性更改时执行一些其他操作,则可以使用观察者。在开发Vue应用程序的整个过程中,你将拥有大量的反应数据属性。你的应用程序将跟踪输入字段,数据计算和许多其他属性,并且值更新时可能需要执行操作。Vue观察者观察特定属性,并能够检测该属性何时更改。实际上,它充当特定数据属性的事件侦听器。使用方法如下:
export default { data () { return { message: '', speeed: '' } }, watch: { // your watchers will go in here! message: function(newMessage, oldMessage) { this.previewHint = "Waiting for you to stop typing.." this.showTypewriter = false this.debouncedTyper() }, speed: function(newSpeed, oldSpeed) { this.previewHint = "Waiting for you to stop tinkering with speed control.." this.showTypewriter = false this.debouncedTyper() } } }
message 和 speed 是 data 中定义的变量,当它们的值变动时就会触发这些函数。watcher是任何框架中响应式的基本原理之一。
参考:参考1