vue.js 核心知识点三

2019-02-12  本文已影响8人  我跟你蒋

目录

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

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

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

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

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

- 3.6 vue生命周期


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

父组件

<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>

父组件

<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父组件调用子组件的方法

父组件:

<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

// 组件 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节点

单个组件的生命周期

父子组件的生命周期

兄弟组件的生命周期

宏mixin的生命周期

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

上一篇 下一篇

猜你喜欢

热点阅读