美文网首页
vue.js 核心知识点三

vue.js 核心知识点三

作者: 我跟你蒋 | 来源:发表于2019-02-12 17:29 被阅读8次

    目录

    - 3.1 vue中子组件调用父组件的方法

    - 3.2 Vue父组件调用子组件的方法

    - 3.3 涉及到组件之间的通信的问题

    - 3.4 vue中 keep-alive 组件的作用

    - 3.5 vue中编写可复用的组件

    - 3.6 vue生命周期


    - 3.1 vue中子组件调用父组件的方法

    • 第一种方法是 直接在子组件中通过this.$parent.event来调用父组件的方法

    父组件

    <template>
      <div>
        <child></child>
      </div>
    </template>
    <script>
      import child from '~/components/dam/child';
      export default {
        components: {
          child
        },
        methods: {
          fatherMethod() {
            console.log('测试');
          }
        }
      };
    </script>
    

    子组件

    <template>
      <div>
        <button @click="childMethod()">点击</button>
      </div>
    </template>
    <script>
      export default {
        methods: {
          childMethod() {
            this.$parent.fatherMethod();
          }
        }
      };
    </script>
    
    • 第二种方法是在子组件里用$emit向父组件触发一个事件,父组件监听这个事件就行了。

    父组件

    <template>
      <div>
        <child @fatherMethod="fatherMethod"></child>
      </div>
    </template>
    <script>
      import child from '~/components/dam/child';
      export default {
        components: {
          child
        },
        methods: {
          fatherMethod() {
            console.log('测试');
          }
        }
      };
    </script>
    

    子组件

    <template>
      <div>
        <button @click="childMethod()">点击</button>
      </div>
    </template>
    <script>
      export default {
        methods: {
          childMethod() {
            this.$emit('fatherMethod');
          }
        }
      };
    </script>
    
    • 第三种方法是父组件把方法传入子组件中,在子组件里直接调用这个方法

    父组件

    <template>
      <div>
        <child :fatherMethod="fatherMethod"></child>
      </div>
    </template>
    <script>
      import child from '~/components/dam/child';
      export default {
        components: {
          child
        },
        methods: {
          fatherMethod() {
            console.log('测试');
          }
        }
      };
    </script>
    

    子组件

    <template>
      <div>
        <button @click="childMethod()">点击</button>
      </div>
    </template>
    <script>
      export default {
        props: {
          fatherMethod: {
            type: Function,
            default: null
          }
        },
        methods: {
          childMethod() {
            if (this.fatherMethod) {
              this.fatherMethod();
            }
          }
        }
      };
    </script>
    

    - 3.2 Vue父组件调用子组件的方法

    • vue中如果父组件想调用子组件的方法,可以在子组件中加上ref,然后通过this.$refs.ref.method调用,例如:

    父组件:

    <template>
      <div @click="fatherMethod">
        <child ref="child"></child>
      </div>
    </template>
    <script>
      import child from '~/components/dam/child.vue';
      export default {
        components: {
          child
        },
        methods: {
          fatherMethod() {this.$refs.child.childMethods();
          }
        }
      };
    </script>
    

    子组件:

    <template>
      <div>{{name}}</div>
    </template>
    <script>
      export default {
        data() {
          return {
            name: '测试'
          };
        },
        methods: {
          childMethods() {
            console.log(this.name);
          }
        }
      };
    </script>
    

    在父组件中, this.$refs.child 返回的是一个vue实例,可以直接调用这个实例的方法

    - 3.3 涉及到组件之间的通信的问题。组件之间的通信可以分为以下几种:

    父子组件传递,父向子传递采用props,子向父采用事件emit
    非父子组件的传递,全局Event bus,new一个vue的实例,采用事件的方式通信,再者采用vuex全局状态管理

    - 3.4 vue中 keep-alive 组件的作用

    在vue项目中,难免会有列表页面或者搜索结果列表页面,点击某个结果之后,返回回来时,如果不对结果页面进行缓存,那么返回列表页面的时候会回到初始状态,但是我们想要的结果是返回时这个页面还是之前搜索的结果列表,这时候就需要用到vue的keep-alive技术了.
    keep-alive 是 Vue 内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染。

    <keep-alive>
    <component>
      <!-- 该组件将被缓存! -->
    </component>
    </keep-alive>
    

    props

    • include - 字符串或正则表达,只有匹配的组件会被缓存
    • exclude - 字符串或正则表达式,任何匹配的组件都不会被缓存
    // 组件 a
    export default {
      name: 'a',
      data () {
        return {}
      }
    }
    
    <keep-alive include="a">
      <component>
        <!-- name 为 a 的组件将被缓存! -->
      </component>
    </keep-alive>可以保留它的状态或避免重新渲染
    
    <keep-alive exclude="a">
      <component>
        <!-- 除了 name 为 a 的组件都将被缓存! -->
      </component>
    </keep-alive>可以保留它的状态或避免重新渲染
    
    
    
    <keep-alive include="a,b">
      <!-- 将缓存name为a或者b的组件,结合动态组件使用 -->
      <component :is="view"></component>
    </keep-alive>
    
    <!-- 使用正则表达式,需使用v-bind -->
    <keep-alive :include="/a|b/">
      <component :is="view"></component>
    </keep-alive>
    
    <!-- 动态判断 -->
    <keep-alive :include="includedComponents">
      <router-view></router-view>
    </keep-alive>
    
    

    但实际项目中,需要配合vue-router共同使用.
    router-view 也是一个组件,如果直接被包在 keep-alive 里面,所有路径匹配到的视图组件都会被缓存:

    <keep-alive>
        <router-view>
            <!-- 所有路径匹配到的视图组件都会被缓存! -->
        </router-view>
    </keep-alive>
    

    如果只想 router-view 里面某个组件被缓存,怎么办?
    增加 router.meta 属性

    // routes 配置
    export default [
      {
        path: '/',
        name: 'home',
        component: Home,
        meta: {
          keepAlive: true // 需要被缓存
        }
      }, {
        path: '/:id',
        name: 'edit',
        component: Edit,
        meta: {
          keepAlive: false // 不需要被缓存
        }
      }
    ]
    
    <keep-alive>
        <router-view v-if="$route.meta.keepAlive">
            <!-- 这里是会被缓存的视图组件,比如 Home! -->
        </router-view>
    </keep-alive>
    
    <router-view v-if="!$route.meta.keepAlive">
        <!-- 这里是不被缓存的视图组件,比如 Edit! -->
    </router-view>
    

    【加盐】使用 router.meta 拓展
    假设这里有 3 个路由: A、B、C。

    需求:

    首页是A页面
    B页面跳转到A,A页面需要缓存
    C页面跳转到A,A页面不需要被缓存

    实现方式
    思路是在每个路由的beforeRouteLeave(to, from, next)钩子中设置to.meta.keepAlive

    在 A 路由里面设置 meta 属性:

    {
            path: '/',
            name: 'A',
            component: A,
            meta: {
                keepAlive: true // 需要被缓存
            }
    }
    

    在 B 组件里面设置 beforeRouteLeave:

    export default {
            data() {
                return {};
            },
            methods: {},
            beforeRouteLeave(to, from, next) {
                 // 设置下一个路由的 meta
                to.meta.keepAlive = true;  // 让 A 缓存,即不刷新
                next();
            }
    };
    

    在 C 组件里面设置 beforeRouteLeave:

    export default {
            data() {
                return {};
            },
            methods: {},
            beforeRouteLeave(to, from, next) {
                // 设置下一个路由的 meta
                to.meta.keepAlive = false; // 让 A 不缓存,即刷新
                next();
            }
    };
    

    这样便能实现 B 回到 A,A 不刷新;而 C 回到 A 则刷新。

    keep-alive生命周期钩子函数:activated、deactivated
    使用<keep-alive>会将数据保留在内存中,如果要在每次进入页面的时候获取最新的数据,需要在activated阶段获取数据,承担原来created钩子中获取数据的任务。

    路由大法不错,不需要关心哪个页面跳转过来的,只要 router.go(-1) 就能回去,不需要额外参数。

    实现前进刷新,后退不刷新参考 https://github.com/iceuncle/vue-navigation

    - 3.5 vue中编写可复用的组件

    组件,是一个具有一定功能,且不同组件间功能相对独立的模块。高内聚、低耦合。

    开发可复用性的组件应遵循以下原则:

    1.规范化命名:组件的命名应该跟业务无关,而是依据组件的功能命名。
    2.数据扁平化:定义组件接口时,尽量不要将整个对象作为一个 prop 传进来。每个 prop 应该是一个简单类型的数据。这样做有下列几点好处:
    (1) 组件接口清晰。(2) props 校验方便。(3) 当服务端返回的对象中的 key 名称与组件接口不一样时,不需要重新构造一个对象。
    扁平化的 props 能让我们更直观地理解组件的接口。

    <!-- 反例 -->
    <card :item="{ title: item.name, description: item.desc, poster: item.img }></card>
    
    
    <card
      :title="item.name"
      :description="item.desc"
      :poster="item.img">
    </card>
    
    

    3.可复用组件只实现 UI 相关的功能,即展示、交互、动画,如何获取数据跟它无关,因此不要在组件内部去获取数据。
    4.可复用组件应尽量减少对外部条件的依赖,所有与 vuex 相关的操作都不应在可复用组件中出现。
    5.组件在功能独立的前提下应该尽量简单,越简单的组件可复用性越强。
    6.组件应具有一定的容错性。
    7.组件应当避免对其父组件的依赖,不要通过 this.parent 来操作父组件的示例。父组件也不要通过 this.children 来引用子组件的示例,而是通过子组件的接口与之交互。
    8.可复用组件除了定义一个清晰的公开接口外,还需要有命名空间。命名空间可以避免与浏览器保留标签和其他组件的冲突。特别是当项目引用外部 UI 组件或组件迁移到其他项目时,命名空间可以避免很多命名冲突的问题。

    - 3.6 vue生命周期

    1、什么是vue生命周期?
    答: Vue 实例从创建到销毁的过程,就是生命周期。也就是从开始创建、初始化数据、编译模板、挂载Dom→渲染、更新→渲染、卸载等一系列过程,我们称这是 Vue 的生命周期。

    2、vue生命周期的作用是什么?
    答:它的生命周期中有多个事件钩子,让我们在控制整个Vue实例的过程时更容易形成好的逻辑。

    3、vue生命周期总共有几个阶段?
    答:它可以总共分为8个阶段:创建前/后, 载入前/后,更新前/后,销毁前/销毁后

    • 创建前/后

    在beforeCreated阶段,vue实例的挂载元素el和数据对象data都为undefined,还未初始化。  在created阶段,vue实例的数据对象data有了,el还没有。

    • 载入前/后

    在beforeMount阶段,vue实例的$el和data都初始化了,但还是挂载之前为虚拟的dom节点,data.message还未替换。
      在mounted阶段,vue实例挂载完成,data.message成功渲染。

    • 更新前/后

    当data变化时,会触发beforeUpdate和updated方法。

    • 销毁前/后

    在执行destroy方法后,对data的改变不会再触发周期函数,说明此时vue实例已经解除了事件监听以及和dom的绑定,但是dom结构依然存在

    4、第一次页面加载会触发哪几个钩子?
    答:第一次页面加载时会触发 beforeCreate, created, beforeMount, mounted 这几个钩子

    5、DOM 渲染在 哪个周期中就已经完成?
    答:DOM 渲染在 mounted 中就已经完成了。

    6、简单描述每个周期具体适合哪些场景?
    答:生命周期钩子的一些使用方法:
    beforecreate : 可以在这加个loading事件,在加载实例时触发
    created : 初始化完成时的事件写在这里,如在这结束loading事件,异步请求也适宜在这里调用
    mounted : 挂载元素,获取到DOM节点
    updated : 如果对数据统一处理,在这里写上相应函数
    beforeDestroy : 可以做一个确认停止事件的确认框
    nextTick : 更新数据后立即操作dom


    vue组件生命周期
    生命周期推荐看http://web.jobbole.com/94470/
    1. created阶段的ajax请求与mounted请求的区别:前者页面视图未出现,如果请求信息过多,页面会长时间处于白屏状态

    2. mounted 不会承诺所有的子组件也都一起被挂载。如果你希望等到整个视图都渲染完毕,可以用 vm.$nextTick

    3. vue2.0之后主动调用$destroy()不会移除dom节点,作者不推荐直接destroy这种做法,如果实在需要这样用可以在这个生命周期钩子中手动移除dom节点

    单个组件的生命周期

    • 初始化组件时,仅执行了beforeCreate/Created/beforeMount/mounted四个钩子函数
    • 当改变data中定义的变量(响应式变量)时,会执行beforeUpdate/updated钩子函数
    • 当切换组件(当前组件未缓存)时,会执行beforeDestory/destroyed钩子函数
    • 初始化和销毁时的生命钩子函数均只会执行一次,beforeUpdate/updated可多次执行

    父子组件的生命周期

    • 仅当子组件完成挂载后,父组件才会挂载
    • 当子组件完成挂载后,父组件会主动执行一次beforeUpdate/updated钩子函数(仅首次)
    • 父子组件在data变化中是分别监控的,但是在更新props中的数据是关联的(可实践)
    • 销毁父组件时,先将子组件销毁后才会销毁父组件

    兄弟组件的生命周期

    • 组件的初始化(mounted之前)分开进行,挂载是从上到下依次进行
    • 当没有数据关联时,兄弟组件之间的更新和销毁是互不关联的

    宏mixin的生命周期

    -mixin中的生命周期与引入该组件的生命周期是仅仅关联的,且mixin的生命周期优先执行

    相关文章

      网友评论

          本文标题:vue.js 核心知识点三

          本文链接:https://www.haomeiwen.com/subject/lgmkeqtx.html