【vue】组件使用总结

组件基础

Vue 组件的示例:

// 定义一个名为 button-counter 的新组件
Vue.component('button-counter', {
  data: function () {
    return {
      count: 0
    }
  },
  template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>'
})

组件的复用
你可以将组件进行任意次数的复用:

<div id="components-demo">
  <button-counter></button-counter>
  <button-counter></button-counter>
  <button-counter></button-counter>
</div>

互不影响

组件注册

全局注册

Vue.component('my-component-name', {
  // ... 选项 ...
})

注册之后可以用在任何新创建的 Vue 根实例 (new Vue) 的模板中。

局部注册
使用components可以局部注册组件,注册后的组件只有在该实例作用域下有效

在这些情况下,你可以通过一个普通的 JavaScript 对象来定义组件:

var ComponentA = { /* ... */ }
var ComponentB = { /* ... */ }
var ComponentC = { /* ... */ }

然后在 components 选项中定义你想要使用的组件:

new Vue({
  el: '#app',
  components: {
    'component-a': ComponentA,
    'component-b': ComponentB
  }
})

注意局部注册的组件在其子组件中不可用

Vue组件的模板在某些情况下会受到HTML的影响,例如<table>内只允许<tr>,<td>等,可以使用is属性来挂载组件

<div id="app">
	<table>
		<tbody is="my-component"><.tbody>
	</table>
</div>
<script>
	Vue.component('my-component', {
		template: '<div>这里是组件的内容</div>'
	});
	var app = new Vue({
		el: '#app'
	})
</script>

组件和实例的区别在data必须是函数,将数据return出来

Prop

示例:

<div id="app">
	<div>
	  <input v-model="parentMsg">
	  <br>
	  <child v-bind:message="parentMsg"></child>
	</div>
</div>

<script>
// 注册
Vue.component('child', {
  // 声明 props
  props: ['message'],
  // 同样也可以在 vm 实例中像 “this.message” 这样使用
  template: '<span>{{ message }}</span>'
})
// 创建根实例
new Vue({
  el: '#app',
  data: {
	parentMsg: '父组件内容'
  }
})
</script>

注意props后的变量格式:['message']

camelCase (驼峰命名法) 的 prop 名需要使用其等价的 kebab-case (短横线分隔命名) 命名

Vue.component('blog-post', {
  // 在 JavaScript 中是 camelCase 的
  props: ['postTitle'],
  template: '<h3>{{ postTitle }}</h3>'
})
<!-- 在 HTML 中是 kebab-case 的 -->
<blog-post post-title="hello!"></blog-post>

prop 可以通过 v-bind 动态赋值

<!-- 动态赋予一个变量的值 -->
<blog-post v-bind:title="post.title"></blog-post>

<!-- 动态赋予一个复杂表达式的值 -->
<blog-post
  v-bind:title="post.title + ' by ' + post.author.name"
></blog-post>

传入一个对象的所有 property
使用不带参数的 v-bind 将一个对象的所有 property 都作为 prop 传入。例如,对于一个给定的对象 post:

post: {
  id: 1,
  title: 'My Journey with Vue'
}

下面的模板:

<blog-post v-bind="post"></blog-post>

单向数据流

级 prop 的更新会向下流动到子组件中,但是反过来则不行。防止从子组件意外变更父级组件的状态。
每次父级组件发生变更时,子组件中所有的 prop 都将会刷新为最新的值

两种试图变更一个 prop 的情形:

  1. 父组件传递初始值进来,子组件将其作为初始值保存起来,在自己的作用域下随意使用和修改,这种情况将组件data内再申明一个数据,引用父组件的prop:
props: ['initialCounter'],
data: function () {
  return {
    counter: this.initialCounter
  }
}
  1. prop 作为被转变的原始值传入。使用计算属性就可以了:
props: ['size'],
computed: {
  normalizedSize: function () {
    return this.size.trim().toLowerCase()
  }
}

Prop 验证

定制 prop 的验证方式,可以为 props 中的值提供一个带有验证需求的对象

Vue.component('my-component', {
  props: {
    // 基础的类型检查 (`null` 和 `undefined` 会通过任何类型验证)
    propA: Number,
    // 多个可能的类型
    propB: [String, Number],
    // 必填的字符串
    propC: {
      type: String,
      required: true
    },
    // 带有默认值的数字
    propD: {
      type: Number,
      default: 100
    },
    // 带有默认值的对象
    propE: {
      type: Object,
      // 对象或数组默认值必须从一个工厂函数获取
      default: function () {
        return { message: 'hello' }
      }
    },
    // 自定义验证函数
    propF: {
      validator: function (value) {
        // 这个值必须匹配下列字符串中的一个
        return ['success', 'warning', 'danger'].indexOf(value) !== -1
      }
    }
  }
})

组件通信

子组件用$emit()来触发事件,父组件用$on()来监听子组件的事件

$emit() 例子

父组件也可以直接在子组件的自定义标签上用v-on来监听子组件出发的自定义事件

可以在自定义组件上使用v-model命令

v-model还可以用来创建自定义的表单输入组件,进行数据双向绑定,例如:

	<div id="app">
		<p>总数:{{total}}</p>
		<my-component v-model="total"></my-component>
		<button @click="handleReduce">-1</button>
	</div>
	
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
		Vue.component('my-component',{
			props:['value'],
			template:'<input :value="value" @input="updateValue">',
			methods:{
				updateValue: function(event){
					this.$emit('input', event.target.value);
				}
			}
		});
		var app = new Vue({
			el: '#app',
			data:{
				total:0
			},
			methods:{
				handleReduce:function(){
					this.total--;
				}
			}
		})
</script>

动态组件 & 异步组件

在一个多标签的界面中使用 is 来切换不同的组件:

<component v-bind:is="currentTabComponent"></component>

使用<keep-alive>将动态组件包裹,从而在第一次创建组件时把它们缓存下来

<!-- 失活的组件将会被缓存!-->
<keep-alive>
  <component v-bind:is="currentTabComponent"></component>
</keep-alive>

注意这个 <keep-alive> 要求被切换到的组件都有自己的名字,不论是通过组件的 name 选项还是局部/全局注册。

异步组件

要将应用分割成小的代码块,在需要时从服务器加载模块,可以使用工厂函数定义组件。只有在组件被渲染时,Vue才会触发,然后缓存结果供以后使用
如:

Vue.component('async-example', function (resolve, reject) {
  setTimeout(function () {
    // 向 `resolve` 回调传递组件定义
    resolve({
      template: '<div>I am async!</div>'
    })
  }, 1000)
})

工厂函数会收到一个resolve回调,改回调函数在从服务器得到组件定义时被调用、也可以调用reject来表示加载失败
其中函数的内部内容根据需要编写,这里推荐的做法是将异步组件和wepack的code-splitting功能一起配合使用

Vue.component('async-webpack-example', function (resolve) {
  // 这个特殊的 `require` 语法将会告诉 webpack
  // 自动将你的构建代码切割成多个包,这些包
  // 会通过 Ajax 请求加载
  require(['./my-async-component'], resolve)
})

也可以在工厂函数中返回一个Promise,所以可以这样动态导入

Vue.component(
  'async-webpack-example',
  // 这个动态导入会返回一个 `Promise` 对象。
  () => import('./my-async-component')
)

当使用局部注册的时候,可以直接提供一个返回 Promise 的函数:

new Vue({
  // ...
  components: {
    'my-component': () => import('./my-async-component')
  }
})

访问根实例

根实例可以通过 $root 进行访问
例如:

// Vue 根实例
new Vue({
  data: {
    foo: 1
  },
  computed: {
    bar: function () { /* ... */ }
  },
  methods: {
    baz: function () { /* ... */ }
  }
})
// 获取根组件的数据
this.$root.foo

// 写入根组件的数据
this.$root.foo = 2

// 访问根组件的计算属性
this.$root.bar

// 调用根组件的方法
this.$root.baz()

小型项目中可以用,大项目推荐是用vuex来进行管理

访问子组件实例或子元素

通过ref为子组件赋予一个id

<base-input ref="usernameInput"></base-input>

使用$ref来访问

this.$refs.usernameInput

$refs 只会在组件渲染完成之后生效,并且它们不是响应式的。这仅作为一个用于直接操作子组件的“逃生舱”——应该避免在模板或计算属性中访问 $refs

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值