Vue.js学习笔记:组件以及配合keep-alive

一.组件?

1.组件 (Component) 是 Vue.js 最强大的功能之一

2.组件可以扩展 HTML 元素,封装可重用的代码

3.组件是自定义元素

二.使用组件

Vue组件的使用有2个步骤,注册组件,使用组件2个方面

1.注册

要注册一个全局组件,你可以使用 Vue.component(tagName, options)。例如:

 

Vue.component('my-component', {
  template: '<div>A custom component!</div>'
})

注意:

① Vue.component(tagName, options)//注册全局组件: (组件名称 组件构造器)  

组件构造器:

//创建一个组件构造器  
var myComponent = Vue.extend({  

   template:'<div>A custom component!</div>'  
})  

Vue.component('my-component',myComponent)

②对于自定义标签名,小写并且包含一个短杠,尽管遵循这个规则比较好。

 

2.实例化

 

new Vue({
  el: '#app'
})

 

三.动态组件,is,keep-alive,异步组件

1.动态组件


什么是动态组件:就是几个组件放在一个挂载点下,然后根据父组件的某个变量来决定显示哪个,或者都不显示。
动态切换:(:is后面的是对应的组件名,是变量,必须一致)
挂载点使用component标签,然后使用v-bind:is**=”组件名”**,会自动去找匹配的组件名,如果没有,则不显示;
改变挂载的组件,只需要修改is指令的值即可

<keep-alive>
   <component :is="componentID"></component>
</keep-alive>

2.keep-alive


a、包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们
b、它自身不会渲染一个 DOM 元素,也不会出现在父组件链中
c、当组件在 <keep-alive’> 内切换时,它的 activated 和 deactivated 两个生命周期钩子会对应执 

keep-alive:
使用 is 特性来切换不同的组件, 会导致重复渲染影响性能, <keep-alive’>能够使组件实例在创建时被缓存

/* 反复切换回影响性能 */
<component :is="currentTabComponent"></component>

/* 未被激活的组件将会被缓存 */
<keep-alive>
	<component :is="currentTabComponent"></component>
</keep-alive>

include 和 exclude 属性允许组件有条件地缓存

<!-- 逗号分隔字符串 -->
<keep-alive include="a,b">
	<component :is="view"></component>
</keep-alive>

<!-- 正则表达式 (使用 `v-bind`) -->
<keep-alive :include="/a|b/">
	<component :is="view"></component>
</keep-alive>

<!-- 数组 (使用 `v-bind`) -->
<keep-alive :include="['a', 'b']">
	<component :is="view"></component>
</keep-alive>

max:
最多缓存多少组件实例,一旦数字达到,新实例被创建之前,缓存组件中最久没有被访问实例会被销毁 

<keep-alive :max="10">   /* 必须 v-bind 绑定 这样才是 JS 表达式 */
	<component :is="view"></component>
</keep-alive>

3.异步组件

只在需要时才从服务器加载模块,且会把结果缓存供未来重新渲染
以工厂函数的方式定义组件,resolve()表示加载成功, reject()表示加载失败

简单的理解:用到的时候加载,不用的时候不加载

Vue.component('async-example', function (resolve, reject) {
  setTimeout(() => {
    return resolve({template: '<div>I am async!</div>'})
  }, 1000)
})


工厂函数也可以返回一个 Promise

Vue.component(
  'async-webpack-example',
  () => import('./my-async-component') /* import 函数返回一个 Promise 对象 */
)

使用局部注册的时候,可以直接返回 Promise 函数
new Vue({
  components: {
    'my-component': () => import('./my-async-component')
  }
})

路由的懒加载,就是加载异步组件

components: {
  Login: () => import('./components/Login'),
  Register: () => import('./components/Register')
}

 

四.functional 函数式组件

组件 没有管理任何状态 ,也 没有监听任何传递给它的状态 ,也 没有生命周期方法 时,可以将组件标记为
functional ,这意味它无状态 ( 没有 响应式数据 ) ,也没有实例 ( 没有 this 上下文 )
 
<heading :level="1" icon="HOMEMESSAGE">
    <a :title="title">{{title}}</a>
</heading>
Vue.component('heading', {
    functional: true, //标记函数式组件
    props: ['level', 'title', 'icon'],
    render(h, context) {
        // 函数式组件 没有this,只有上下文context
        //子组件节点
        let children = [];
        // 属性获取 
        const { icon, title, level } = context.props;

        // 添加图标功能 // <svg><use xlink:use="#icon-xxx"></use></svg> 
        if (icon) {
            children.push(h('svg', { class: 'icon' }, [h('use', { attrs: { 'xlink:href': '#icon-' + icon } })]))
        }
        let vnode = h(
            'h' + level,
            { attrs: { title } }, // 之前省略了title的处理
            children = children.concat(context.children)// 子组件节点
        )
        return vnode;
    }
})
 

五.总结Vue组件化的理解

1.vue 组件化理解


定义:组件是可复用的 Vue 实例,准确讲它们是VueComponent的实例,继承自Vue。
优点:从上面案例可以看出组件化可以增加代码的复用性、可维护性和可测试性。
使用场景:什么时候使用组件?以下分类可作为参考:
通用组件:实现最基本的功能,具有通用性、复用性,例如按钮组件、输入框组件、布局组件等。
业务组件:它们完成具体业务,具有一定的复用性,例如登录组件、轮播图组件。
页面组件:组织应用各部分独立内容,需要时在不同页面组件间切换,例如列表页、详情页组件

2.如何使用组件

    定义:Vue.component(),components选项,sfc
    分类:有状态组件,functional,abstract

        有状态组件是组件有data的定义,
        functional :可以理解是无状态组件,就没有定义data。是一个函数
        abstract:抽象式组件 (放抖动,节流的组件,没具体的视图)
        
    通信:props,$emit()/$on(),provide/inject,$children/$parent/$root/$attrs/$listeners
    内容分发:<slot>,<template>,v-slot
    使用及优化:is,keep-alive,异步组件

3.vue中的组件经历如下过程


    组件配置 => VueComponent实例 => render() => Virtual DOM=> DOM
    所以组件的本质是产生虚拟DOM

 

六.组件或元素引用

 
ref vm.$refs
ref 被用来给元素或子组件注册引用信息。引用信息将会注册在父组件的 $refs 对象上。如果 在普通
DOM 元素上使用,引用指向的就是 DOM 元素 ;如果 用在子组件上,引用就指向组件
 
1.设置输入框焦点
 
<input type="text" ... ref="inp"> 

mounted(){ 
    // mounted之后才能访问到inp
    this.$refs.inp.focus() 
}

2.改造message组件用打开、关闭方法控制显示

<!--自定义组件引用-->
 <message ref="msg">新增课程成功!</message> 
<script> 
	Vue.component('message', { 
	// 组件显示状态
	data() { 
		return {
			show: false 
		} 
	},
	template: ` <div class="message-box" v-if="show"> 
	<slot></slot> 
	<!--toggle内部修改显示状态--> 
	<span class="message-box-close" @click="toggle">X</span> 
	</div> `,
	// 增加toggle方法维护toggle状态 
	methods: { 
		toggle() { 
			this.show = !this.show; 
		} 
	},
	// 修改message-close回调为toggle 
	mounted () { 
		this.$bus.$on('message-close', this.toggle); 
		}, 
	})
	const app = new Vue({ 
		methods: { 
			addCourse() { 
				// 使用$refs.msg访问自定义组件 
				this.$refs.msg.toggle() 
			} 
		} 
	})
</script>
注意:
ref 是作为渲染结果被创建的,在初始渲染时不能访问它们
$refs 不是响应式的,不要试图用它在模板中做数据绑定
v-for 用于元素或组件时,引用信息将是包含 DOM 节点或组件实例的数组。
 

七.简单的例子

使用Vue,必须要引用它的js:import Vue from 'vue';

 

1.全局组件

<template>
  <div id="app">
      <h1>{{title}}</h1>
      <my-component></my-component>
  </div>
</template>
<script> 
import Vue from 'vue';

Vue.component('my-component', {
  template: '<div>A custom component!</div>'
})
export default {
  name: 'app',
  data: function () {
    return { 
      title: '全局组件的使用'
    } 
  }
}
</script>

 

2.局部组件

 

<template>
  <div id="app">
      <h1>{{title}}</h1>
      <my-component></my-component>
  </div>
</template>
<script> 
var Child = {
  template: '<div>A custom component!</div>'
}
export default {
  name: 'app',
  data: function () {
    return { 
      title: '局部组件的使用'
    } 
  },
  components: {'my-component': Child}
}
</script>

 

 

3.data传值(必须是函数

 

 

<template>
  <div id="app">
      <h1>{{title}}</h1>
      <my-component></my-component>
      <my-component></my-component>
      <my-component></my-component>
  </div>
</template>
<script> 
import Vue from 'vue';
var data = { counter: 0 }
Vue.component('my-component', {
  template: '<button v-on:click="counter += 1">{{ counter }}</button>',
  // 技术上 data 的确是一个函数了,因此 Vue 不会警告,
  // 但是我们返回给每个组件的实例的却引用了同一个data对象
  data: function () {
    return {
      counter: 0
    }
  }
})
export default {
  name: 'app',
  data: function () {
    return { 
      title: '组件共享了同一个 data,增加一个counter不会影响其他组件'
    } 
  }
}
</script>

 

 

四.定制组件的 v-model

一个组件的 v-model 会使用 value 属性和 input 事件,但是诸如单选框、复选框之类的输入类型可能把 value 属性用作了别的目的,model 选项可以回避这样的冲突:

 


Vue.component('my-checkbox', {
  model: {
    prop: 'checked',
    event: 'change'
  },
  props: {
    checked: Boolean,
    // this allows using the `value` prop for a different purpose
    value: String
  },
  // ...
})
<my-checkbox v-model="foo" value="some value"></my-checkbox>

上述代码等价于:
<my-checkbox
  :checked="foo"
  @change="val => { foo = val }"
  value="some value">
</my-checkbox>

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值