创建所需的vue文件即可,可放在创建的类似component文件夹下。
1.局部注册
如何注册组件:在需要挂载的父组件内部直接引入子组件
(1)引入子组件文件
//设置的文件名异同都可。
import topnav from './component/topnav';
import leftmenu from './component/leftmenu';
import rightcon from './component/rightcon';
(2)注册局部组件
在components属性中注册
export default{
components:{
"v-topnav":topnav,
"v-leftmenu":leftmenu,
"v-rightcon":rightcon
}
export default{
components:{
topnav,
leftmenu,
rightcon
}
(3)注册完成之后使用局部组件
<template>
<div id="app">
<v-topnav>v-topnav>
<v-leftmenu>v-leftmenu>
<v-rightcon>v-rightcon>
div>
template>
2.全局注册
(1)在main.js
中引入组件
import time from './component/child/time.vue'
(2)使用Vue.component( )
注册全局组件
Vue.component() 第二个参数可以是引入组件,也可是构造函数。
Vue.component("v-time",time);
(3)直接用标签的方式使用全局组件(同局部组件使用法)
或:
Vue.component("counter",{
//data 写函数; template 写组件的内容
//data 必须是有返回值的函数,而不是对象
//可能需要创建多次实例(独立维护,互不冲突)
data:function(){
return {count:0}
},
template:''
})
1.父组件:父组件通过数据绑定的方式进行传值
<v-logo :logosrc="logo" :logoname="name">v-logo>
data(){
return{
logo:"src/assets/logo.png",
name:"后台管理系统"
}
}
2.在子组件中,定义props属性接受父组件传递的数据(3种方式),并引用到标签里
<img src="logosrc" alt="">
<span>{{logoname}}span>
//定义props属性的三种写法:
//第一种:简单式写法
//(传递的数据没有类型的约束)
props:['logosrc','logoname'],
//第二种:约束数据类型式写法
//(如果数据类型不一致,会报警告,但传的值显示)
props:{
logosrc:String,
logoname:String
}
//第三种:带默认值且约束数据类型式写法
//(如果父组件没有传递数据,则走默认值)
props:{
logosrc:{
type:String,
default:
"https://imgpp.ztupic.com/images/202103/OAs2TY1GH21111.jpg"
},
logoname:{
type:String,
default:"系统"
}
}
<v-logo :parentinfo="this">v-logo>
//父组件
methods: {
childsend(){
console.log("子组件在调用");
}
}
//子组件
props:{
parentinfo:Object
},
mounted() {
// 通过定义prop属性,获取父组件内容
let parentcomponent = this.parentinfo;
console.log(parentcomponent);
// 调用父组件方法
parentcomponent.childsend();
}
或使用this.$parent
方法让子组件获取父组件所有的内容:
console.log(this.$parent);//vue给子组件提供获取父组件全部内容的方法
父组件获取子组件的所有内容,使用ref获取虚拟dom来获取子组件
ref 被用来给
元素或子组件注册引用信息
。引用信息将会注册在父组件的$refs
对象上。如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例.
关于 ref 注册时间的重要说明:因为 ref 本身是作为渲染结果被创建的,在初始渲染的时候你不能访问它们 - 它们还不存在!$refs 也不是响应式的,因此你不应该试图用它在模板中做数据绑定。
<v-logo ref="logolist">v-logo>
mounted() {
// 获取到整个子组件
let logoinfo = this.$refs.logolist;
console.log(logoinfo);
// 父组件执行子组件方法
logoinfo.sendmsg();
}
先监听,后触发;在子组件内部做触发,在父组件上提前做监听处理,监听后执行调用的是父组件的方法。使用this直接实现。
父组件:
<v-logo @myevent="dosomething">v-logo>
methods: {
dosomething(){
console.log("监听");
}
}
子组件:
<button @click="emitmsg">触发button>
methods: {
emitmsg(){
//父子组件直接用this.调用,非父子组件不可以
this.$emit("myevent");
}
作用是子组件修改父组件的相关变量。
//非父组件直接使用事件车通信 来源于new Vue()
Vue.prototype.emitEvent = new Vue();
其一组件:
<button @click="sendright">传送到右边button>
methods: {
//发送数据 发布自定义事件 携带数据
// this.emitEvent.$emit(,)第二个参数可以传任意数据类型的数据
sendright(){
this.emitEvent.$emit("go-right",{
name:"jm",
age:12
})
}
}
另一组件:
mounted() {
//该组件渲染完成之后自动监听自定义事件
this.emitEvent.$on("go-right",(res)=>{
console.log(res);
})
}
父组件不能直接在引入的子组件标签中添加dom元素,不会显示。所以需要使用slot插槽。
插槽就是占位置,在子组件加入插槽,父组件给子组件标签添加的元素会自动进入插槽空间,并显示。
提供组件的复用。
子组件:
<template>
<div id="userlist">
<p>我是用户的列表组件p>
<slot>slot>
div>
template>
父组件:
<template>
<div id="rightcon">
<p>我是右边内容区组件p>
<v-userlist> <p>加了slot后我可以显示了p> v-userlist>
div>
template>
可以使用默认插槽(插槽内添加默认数据),如果父组件不在子组件标签内添加元素(没有给插槽内容),会显示默认数据,反之显示新添加的数据。
子组件:
<header>
<slot name="header"> slot>
header>
<main>
<slot name="content"> slot>
main>
<footer>
<slot name="footer"> slot>
footer>
父组件:
<v-userlist>
<template v-slot:header> <p>头部p> template>
<template v-slot:content> <p>内容p> template>
<template v-slot:footer> <p>底部p> template>
v-userlist>
1.在一个多标签的界面中使用
is
attribute 来切换不同的组件;
2.同时在组件之间切换的时候,想保持这些组件的状态,以避免反复重渲染导致的性能问题。使用keep-alive标签。
选项卡1对应1-x页面,选项卡2对应2-x页面。实现的效果是:切换回上一页面,状态仍保持。
<keep-alive>
<component :is="componentId">component>
keep-alive>
并且
具有两个属性:(“变量”是vue组件的name,以字符串或正则表达式形式)
:include="变量"
需要缓存的组件
:exclude=" "
除此组件之外都缓存
在大型应用中,我们可能需要将应用分割成小一些的代码块,并且只在需要的时候才从服务器加载一个模块。为了简化,Vue 允许你以一个工厂函数的方式定义你的组件,这个工厂函数会异步解析你的组件定义。Vue只有在这个组件需要被渲染的时候才会触发该工厂函数,且会把结果缓存起来供未来重渲染。
1.这个工厂函数会收到一个 resolve
回调,这个回调函数会在你从服务器得到组件定义的时候被调用。你也可以调用 reject(reason)
来表示加载失败。
<v-async>v-async>
import Async from './components/async';
export default {
components:{
// 异步加载 引入但没有挂载
'v-async':function(resolve,reject){
setTimeout(function(){
// 返回组件名
resolve(Async);
},2000)
}
}
2.也可以将异步组件和 webpack 的 code-splitting
功能一起配合使用,写成按需加载require
:
<component :is="componentId">component>
export default {
components:{
'async':(resolve,reject)=>{
//resolve是全部引入成功以后的回调函数,第一个参数是依赖,require会先引入依赖模块,再执行回调函数。
return require(['./components/async'],resolve);
}
},
data(){
return{
componentId:'async'
}
}
}
3.也可以在工厂函数中返回一个 Promise,所以把 webpack 2
和 ES2015
语法加在一起,我们可以这样使用动态导入:
<async>async>
components:{
'async':
// 这个动态导入会返回一个 `Promise` 对象。
()=>import('./components/async')
}
}
<async>async>
'async':() => ({
// 需要加载的组件 (应该是一个 `Promise` 对象)
component: import('./components/async'),
// 异步组件加载时使用的组件
// loading: LoadingComponent,
// 加载失败时使用的组件 (引入的组件)
// error: ErrorComponent,
// 展示加载时组件的延时时间。默认值是 200 (毫秒)
delay: 200,
// 如果提供了超时时间且组件加载也超时了,
// 则使用加载失败时使用的组件。默认值是:`Infinity`
timeout: 3000
})
上面代码的component属性也可以这样写:
component: new Promise((resolve,reject)=>{
let data = true;
if(data){
//tabone是引入组件
setTimeout(resolve,2000,tabone);
}
else{
reject(new Error('失败'))
}
})