哈喽.我是慕筱佳,通过前几篇文章的学习,我们学习了一些系统指令,事件还有生命周期,接下来笔者将会带领你们走进更深的vue世界.

1.MVVM设计模式

vue是一个渐进式框架,其遵循MVVM设计模式,提到MVVM或许很多人会很陌生,这也是目前前端三大主流框架比较流行的设计模式,接下来让我们看看这个设计模式到底是什么?MVVM其实就是Model-View-ViewModel的缩写,它本质上市MVC的改进版,将其中的View 的状态和行为抽象化,让我们将视图 UI 和业务逻辑分开。主要的目的就是分离视图和模型.

  1. <div id="app">
  2. <h1>{{msg}}</h1>
  3. </div>
  4. <script>
  5. new Vue({
  6. el:"#app",
  7. data:{
  8. msg:"慕筱佳"
  9. }
  10. })
  11. </script>

2.MVVM的优点

1.低耦合
视图(View)可以独立于Model变化和修改,一个ViewModel可以绑定到不同的”View”上,当View变化的时候Model可以不变,当Model变化的时候View也可以不变。
2.可重用性
你可以把一些视图逻辑放在一个ViewModel里面,让很多view重用这段视图逻辑。
3.独立开发
开发人员可以专注于业务逻辑和数据的开发(ViewModel),设计人员可以专注于页面设计,使用Expression Blend可以很容易设计界面并生成xaml代码。
4.可测试
界面素来是比较难于测试的,测试可以针对ViewModel来写。

3.watch侦听器

对于watch监听器而言,其实本质是一个特殊的函数,主要是用来监视data中的某个数据的变化,从而做除一些逻辑的处理.并且不需要手动调用,监听器分为普通监听和深度监听.
1.watch侦听器的函数名必须和被监视的数据名保持一致
2.不能滥用watch侦听器, 因为会有性能开销

普通监听器:

  1. new Vue({
  2. el: "#app",
  3. data: {
  4. msg: 'hello'
  5. },
  6. //监听器
  7. watch: {
  8. msg(newValue, oldValue) {
  9. console.log(newValue, oldValue);
  10. }
  11. }
  12. })

深度监听器:

  1. watch: {
  2. //比如要监听user数据
  3. user:{
  4. // oldVal:系统自动注入,更新之前的值
  5. // newVal: 系统自动注入, 更新之后的值
  6. handler(newVal,oldVal) {
  7. console.log(newVal,oldVal);
  8. },
  9. //watch监听对象的时候,需要加deep:true,只有这样才能深入底层去实时监听,
  10. //没有加的话,对象是监听不到变化的,添加immediate时会在侦听开始之后被立即调用
  11. deep:true,
  12. immediate: true
  13. }
  14. }

4.computed计算属性

在 computed 中,可以定义一些 属性,这些属性,叫做 【计算属性】, 计算属性的本质,就是 一个方法,只不过我们在使用 这些计算属性的时候,是把它们的名称直接当作属性来使用的;并不会把 计算属性当作方法去调用.
在一个计算属性里可以完成各种复杂的逻辑,包括运算、函数调用等,只要最终返回一个结果就可以。所以计算属性中的方法必须要有返回值.而且存在缓存.对于性能开销比较友好.

  1. <div id="app">
  2. <input type="text" v-model="firstname"><br />
  3. <input type="text" v-model="lastname">
  4. <h2>{{fullname}}</h2>
  5. </div>
  1. new Vue({
  2. el: "#app",
  3. data: {
  4. firstname: "",
  5. lastname: ''
  6. },
  7. //计算属性
  8. computed: {
  9. fullname() {
  10. //必须要有返回值
  11. return this.firstname + this.lastname;
  12. }
  13. }
  14. })

computed相比methods来说,最大的优点就是计算属性存在缓存机制
相比之下,每当触发重新渲染时,调用方法将总会再次执行函数。 所以出于对性能的考虑,计算属性是比较好的.
注意 : 1.计算属性调用的时候是当做数据调用 2. 计算属性方法名, 不能和data中的数据同名

5.过滤器filter

过滤器实际是一种特殊的方法,主要用来对将要输出的数据进行预处理,定义的过滤器必须要有返回值,并且过滤器的第一个形参永远是待处理的数据(由系统自动注入),
vue中的过滤器分为两种:全局过滤器和局部过滤器.
过滤器只能在插值表达式和v-bind指令中使用,调用的时候通过管道符 | 来调用.

全局过滤器
在任何地方都可以使用

  1. <body>
  2. <div id="app">
  3. <h1>{{msg}}</h1>
  4. 调用全局过滤器
  5. <h1>{{msg | change}}</h1>
  6. </div>
  7. <script>
  8. //定义全局过滤器
  9. Vue.filter("change", data => {
  10. //必须返回索要处理的数据
  11. return data.toUpperCase();
  12. })
  13. new Vue({
  14. el: "#app",
  15. data: {
  16. msg: "hello world"
  17. }
  18. })
  19. </script>
  20. </body>

局部过滤器
定义在vue实例中的过滤器为局部过滤器, 不能在vue实例对象的外面使用.

  1. <div id="app">
  2. <h1>{{time | dateFmt}}</h1>
  3. <h1>{{msg | reverse}}</h1>
  4. <h1>{{str | uppPer}}</h1>
  5. </div>
  1. new Vue({
  2. el: "#app",
  3. data: {
  4. },
  5. filters: {
  6. dateFmt(time, divider = "/") {
  7. const date = new Date(time);
  8. const y = date.getFullYear(); //年
  9. const m = date.getMonth() + 1; //月
  10. const d = date.getDate(); //日
  11. const h = date.getHours(); //时
  12. const mm = date.getMinutes(); //分
  13. const ss = date.getSeconds(); //秒
  14. return `${y}${divider}${m}${divider}${d} ${h}:${mm}:${ss}`;
  15. },
  16. //处理字符串反转的过滤器
  17. reverse(str) {
  18. return str.split("").reverse().join("");
  19. },
  20. //转换为大写
  21. uppPer(data) {
  22. return data.toUpperCase();
  23. }
  24. }

1、 当有局部和全局两个名称相同的过滤器时候,会以就近原则进行调用,即:局部过滤器优先于全局过滤器被调用!
2、 一个表达式可以使用多个过滤器。过滤器之间需要用管道符“|”隔开。其执行顺序从左往右

6.组件components

组件(Component)是Vue.js最强大的功能之一。组件可以扩展HTML元素,封装可重用的代码。根据项目需求,抽象出一些组件,每个组件里包含了展现、功能和样式。每个页面,根据自己所需,使用不同的组件来拼接页面。这种开发模式使前端页面易于扩展,且灵活性高,而且组件之间也实现了解耦。
在vue中,一个组件本质是一个拥有预定义选项的一个 Vue 实例

  1. <myheader></myheader>
  2. <navbar></navbar>

上面的自定义标签其实就是vue中的组件.组件以一个自定义标签的形式存在,起到占位符的功能。通过Vue.js的声明式渲染后,占位符将会被替换为实际的内容.
vue组件分为全局组件和局部组件

6-1.组件命名规范

  • 小驼峰=>使用-连接的方式
  • 驼峰=>使用-连接的方式
  • 全部小写=>原样调用

    6-2.组件使用

    Vue组件的使用有3个步骤,创建组件构造器,注册组件,调用组件

1.构建组件对象

  1. // 组件对象
  2. const myheader = {
  3. template: `
  4. <div>{{title}}</div>
  5. `,
  6. data() {
  7. //在组件内部的data必须是一个函数
  8. return {
  9. title: "头部"
  10. }
  11. }
  12. }

2.注册组件时,如果全局注册,则为全局组件,如果局部注册,则为局部组件

  1. //注册全局组件
  2. Vue.component("myheader", myheader);
  1. new Vue({
  2. el: "#app",
  3. //注册局部组件
  4. //局部组件只能在vue实例中使用
  5. components: {
  6. myheader
  7. }
  8. })

3.使用组件

  1. <div id="app">
  2. <myheader></myheader>
  3. </div>

6-3.组件嵌套

  1. <body>
  2. <div id="app">
  3. <button @click="get">按钮</button>
  4. <navbar></navbar>
  5. </div>
  6. <script>
  7. new Vue({
  8. el: "#app",
  9. data: {
  10. title: "我是头部"
  11. },
  12. components: {
  13. "navbar": {
  14. template: `<div>
  15. <h1>{{navTitle}}</h1>
  16. <child-bar></child-bar>
  17. </div>`,
  18. data() {
  19. return {
  20. navTitle: "我是导航"
  21. }
  22. },
  23. components: {
  24. "childBar": {
  25. template: `
  26. <div>
  27. <ul>
  28. <li v-for="item in list">{{item}}</li>
  29. </ul>
  30. </div>
  31. `,
  32. data() {
  33. return {
  34. list: ["首页", "音乐", "影视"]
  35. }
  36. },
  37. methods: {
  38. //这里是组件childBar的方法
  39. }
  40. }
  41. }
  42. },
  43. },
  44. methods: {
  45. get() {
  46. console.log("get...");
  47. }
  48. }
  49. })
  50. </script>
  51. </body>

在组件嵌套中,要特别注意几点:

  • 组件中的data必须为一个函数
  • 组件中的私有数据必须要经过通信才能使用,不然通过this是无法拿到私有组件中的数据的.

    6-4.论data必须为函数【面试题】

    组件是可复用的vue实例,一个组件被创建好之后,就可能被用在各个地方,而组件不管被复用了多少次,组件中的data数据都应该是相互隔离,互不影响的,基于这一理念,组件每复用一次,data数据就应该被复制一次,之后,当某一处复用的地方组件内data数据被改变时,其他复用地方组件的data数据不受影响.

    6-5.动态组件

    vue提供内置的组件对象,为了更好的动态展示组件.
    is: 指定需要展示的组件名称, 一般需要使用v-bind动态绑定
    1. <component is="组件名称"></component>

    6-6.缓存组件keep-alive

    在vue2.0中提供了keep-alive组件,目的是为了对组件进行缓存,提高性能.只需要用keep-alive将目标组件包裹起来即可.
    1. <!-- 缓存组件 -->
    2. <keep-alive>
    3. <!-- 动态组件 -->
    4. <component :is="page"></component>
    5. </keep-alive>
    在keep-alive组件中,提供了特殊的生命周期钩子函数,只有在被缓存的组件中才存在.
    1. activated(){
    2. console.log('Home组件被激活');
    3. },
    4. deactivated(){
    5. console.log('Home组件被失活');
    6. }
    但是这种方法有bug,后续笔者会对以上bug做出解决方案.如果你的项目只有一种状态需要被缓存时,可以考虑使用这种方法.