组件
定义与使用 vue 组件
组件就是应用里面一块可以重复使用的界面。
定义一个组件:
1 2 3
| <template> <button>按钮</button> </template>
|
在其他地方使用的时候,需要先在 script 中引入并声明
1 2 3 4 5 6 7 8
| import AppButton from './components/app-button'; export default { data() { }, components: { AppButton, }, };
|
然后在 template 中就可以使用了,以下几种写法都可。
1 2 3 4 5 6 7
| <template> <AppButton></AppButton> //可以写结束标签 <AppButton /> //也可以写成自关闭
<app-button></app-button> //还可以写成串串 <app-button /> </template>
|
vue 组件的样式
组件的样式可以直接写在 style 标签里,也可以写在样式表里,在 style 中用@import 的方式引入。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <style> .button { outline: none; border: none; background: #e1e1e1; color: #5a5a5a; padding: 8px 16px; margin: 4px; cursor: pointer; border-radius: 3px; } .button:active { opacity: 0.8; } </style>
|
scoped 限定组件样式的应用范围
默认情况下,组件间的样式会相互影响。如果想限定样式只在当前组件内有效的话,可以在组件的 style 标签上添加 scoped,这样组件的样式就私有化了。加了这个东西以后,会在这个组件的模板元素上面添加一个特定的 data 属性。
props vue 组件的属性
父组件可以通过 props 把数据传递给子组件。
组件中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <template> <button class="button">{{ text }}</button> </template>
<script> export default { props: { text: { type: String, default: '按钮', }, }, }; </script>
|
使用的时候:
1 2 3 4 5 6 7 8
| <template> <h3>{{ name }}</h3> <AppButton text="确定"></AppButton> <AppButton />
<app-button></app-button> <app-button /> </template>
|
监听子组件的事件
在一个组件里使用了另一个组件,他们之间就有了父子关系。子组件发生的事情可以通过自定义的事件告诉给父组件。
子组件:
1
| <button class="button" @click="$emit('tap', text)">{{ text }}</button>
|
父组件:
1 2 3 4
| <AppButton text="确定" @tap="onTapAppButton" ></AppButton>
|
1 2 3 4 5
| methods: { onTapAppButton(text) { console.log('on tap app button', text); } }
|
slot 在 vue 组件里用插槽分发内容
在定义组件的时候可以添加一些 slot,这样在使用组件的时候,可以设置插槽的内容。
子组件:
1 2 3
| <button class="button" @click="$emit('tap', text)"> <slot></slot> </button>
|
父组件:
1
| <AppButton @tap="onTapAppButton" @init="onInitAppButton">提交</AppButton>
|
动态组件
在页面中如果你想切换使用不同的组件,可以使用动态组件功能。
举个栗子:新建三个子组件,user-login.vue 用户登录,user-register.vue 用户注册,user-profile.vue 界面
user-login.vue:
1 2 3 4 5
| <template> <div>用户登录</div> <input type="text" /> <input type="text" /> </template>
|
user-register.vue:
1 2 3 4 5
| <template> <div>注册用户</div> <input type="text" /> <input type="text" /> </template>
|
user-profile.vue:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| <template> <component :is="currentComponent"></component> <small @click="onClickHintText">{{ hintText }}</small> </template>
<script> import UserLogin from './user-login'; import UserRegister from './user-register'; export default { data() { return { currentComponent: 'UserLogin', //要显示的子组件 hintText: '还没有账户,点击注册', //提示信息 }; }, methods: { onClickHintText() { switch (this.currentComponent) { case 'UserRegister': this.currentComponent = 'UserLogin'; this.hintText = '还没有账户,点击注册'; break; case 'UserLogin': this.currentComponent = 'UserRegister'; this.hintText = '已有账户,点击登录'; break; } }, }, components: { UserRegister, UserLogin, }, }; </script>
|
父组件中使用:
1
| <UserProfile></UserProfile>
|
1 2 3 4
| import UserProfile from './components/user-profile'; components: { UserProfile, },
|
这样在页面中点击的时候就可以在登录和注册之间切换了。
keep-alive 保持动态组件的活动状态
比如上面动态组件的栗子,在一个组件里填写后切换到另一个组件,再切换回来,你会发现刚才填写的东西不见了。如果你想保存组件的状态,可以使用 keep-alive。
1 2 3
| <keep-alive> <component :is="currentComponent"></component> </keep-alive>
|
$refs 引用模板
有时候我们希望可以直接访问到子组件,或者某一个具体的 html 元素,这时候我们可以在子组件或者 html 元素上使用 ref,去分配一个引用的 id,然后在代码里使用这个引用的 id 就可以访问到这个组件或者 html 元素。比如我希望在组件挂在后,让文本框自动进入焦点状态。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <template> <div>用户登录</div> <input type="text" ref="username" /> <input type="text" /> </template>
<script> export default { mounted() { console.log(this.$refs.username); this.$refs.username.focus(); }, }; </script>
|
在自定义组件上使用 v-model
在自定义组件上使用 v-model 需要额外处理一下。
子组件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <template> <input type="text" :value="modelValue" @input="$emit('update:modelValue', $event.target.value)" /> </template>
<script> export default { props: { modelValue: String, }, }; </script>
|
父组件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| <template> <div>用户登录 {{ username }}</div> <AppInput v-model="username" /> </template>
<script> import AppInput from './app.input'; export default { data() { return { username: '', }; }, components: { AppInput, }, }; </script>
|
组件的生命周期方法
beforeCreate:组件创建前
beforeMount:组件挂载前
beforeUpdate:组件更新前
created:组件创建后
mounted:组件挂载后
updated:组件更新后
unmounted:组件卸载后