2.组件基础
2-1父传子props
父传子:水往低处流(单向绑定的原则),子不能修改父传过来的属性,它是只读的,但是可以使用监听和计算属性进行修改
父组件
<template><div><navbar mytitle="电影" isShow="false"></navbar><navbar mytitle="影院"></navbar>//动态绑定状态<navbar :mytitle="parentTitle"></navbar></div>
</template>
<script>
import Navbar from './Navbar.vue'
export default {data() {return {//状态parentTitle: "父组件定义的一个状态",}},components: {Navbar}
}
</script>
子组件
<template><div>//显示内容<p>{{ mytitle }}</p><button @click="handler()" v-if="isShow">按钮</button></div>
</template>
<script>
export default {// props: ["mytitle","left","right"],//通过props接受父组件传过来的内容props:{mytitle: String,isShow:{type:Boolean,default:true,// required:true}},methods: {handler() {// 无法直接访问状态和修改状态console.log(this.parentTitle)}},}
</script>
2-2属性验证&默认属性
export default {props: {// 基础类型检查//(给出 `null` 和 `undefined` 值则会跳过任何类型检查)propA: Number,// 多种可能的类型propB: [String, Number],// 必传,且为 String 类型propC: {type: String,required: true},// Number 类型的默认值propD: {type: Number,default: 100},// 对象类型的默认值propE: {type: Object,// 对象或者数组应当用工厂函数返回。// 工厂函数会收到组件所接收的原始 props// 作为参数default(rawProps) {return { message: 'hello' }}},// 自定义类型校验函数propF: {validator(value) {// The value must match one of these stringsreturn ['success', 'warning', 'danger'].includes(value)}}}
}
2-3子传父:$emit
如果 在vue中要用sass,需要安装这个模块,npm i sass
在子页面通过$emit进行传值,在父页面通过event事件进行获取值
子组件
<template><div>//,在父页面通过event事件进行获取值,//不要写小括号,会有一个event事件<Child @event="handleEvent"></Child> </div>
</template>
<script>import Child from './Child.vue'export default {data() {return {isShow: true}},components: {Child},methods: {//,在父页面通过event事件进行获取值handleEvent(event) {console.log("父组件",event);}},
}</script>
子组件
<template><div><button @click="send()">子传父</button></div>
</template>
<script>
export default {data() {return {childTitle:"子组件的状态"}},methods: {send() {进行传值给父组件 event必须和父页面的一致 this.$emit("event",this.childTitle)}},}
</script>
2-4$refs-父组件的强权
- ref如果绑定在dom节点上,拿到的就是 原生dom节点
- ref如果绑定在组件上,拿到的就是 组件对象,可以实现通信功能
父组件
<template><div>$ref<filed label="用户名" type="text" ref="username"></filed><filed label="密码" type="password" ref="password"></filed><button @click="login">登录</button><button @click="rest" >重置</button></div>
</template>
<script>
import filed from './filed-父子通信.vue'
export default {components: {filed},methods: {login() {//通过$refs获取子组件的值console.log(this.$refs.username.value,this.$refs.password.value);},rest() {this.$refs.username.value="",this.$refs.password.value=""}},
}
</script>
子组件
<template><div><label for="">{{ label}}</label><input :type="type" v-model="value"></div>
</template>
<script>
export default {props: ["label", "type"],data() {return {value:""}},}
</script>
2-5 KaTeX parse error: Expected 'EOF', got '&' at position 7: parent&̲root - 子组件的无法无天
<template><div>parent<Child></Child><div v-show="isShow">sidebar</div></div>
</template>
<script>
import Child from './Child.vue'
export default {components: {Child},data() {return {parentTitle: "父组件11111",isShow: true}},
}
</script>
子组件
<template><div>Child<button @click="handleClick">$parent</button></div>
</template>
<script>
export default {methods: {handleClick() {//----------------子组件无法无天-----------------//在子组件中通过`$parent`访问父组件,通过`$root`访问根组件console.log(this.$parent.parentTitle,this.$root);this.$parent.isShow=!this.$parent.isShow;}},
}
</script>
2-6.跨级通信provide和inject
provide
和 inject
是 Vue.js 中用于跨组件通信的一对高级特性。它们允许祖先组件(提供者)向所有后代组件(使用者)传递数据,而不需要通过 props 或事件的方式。
provide ,inject 搭配组合式api使用,具备响应性
provide ,inject 搭配选项式使用, 没有响应性, 把app组件实例
父组件
<!-- provide ,inject 搭配组合式api使用,具备响应性
provide ,inject 搭配选项式使用, 没有响应性, 把app组件实例-->
<template><div><navbar></navbar><tabber></tabber></div>
</template>
<script>
import navbar from './Navbar.vue'
import tabber from './Tabber.vue'
export default {components: {navbar,tabber},// 是一个函数provide() {return {app:this}},data() {return {title:"首页"}},
}
</script>
navbar
<template><div style="text-align: center;">{{ app.title}}</div>
</template>
<script>
export default {inject: ['app'],}
</script>
tabber
<template><ul><li v-for="(item, index) in list" :key="index" @click="handlerClick(item.name)">{{ item.name }}</li></ul>
</template>
<script>
export default {inject:["app"],data() {return {list: [{ name: "首页" },{ name: "分类" },{ name: "购物车" },{ name: "我的" }]}},methods: {handlerClick(val) {this.app.title=val}},
}
</script>
<style scoped>ul{list-style: none;display: flex;position: fixed;bottom: 0;width: 100%;}
li{flex: 1;text-align: center;height: 60px;line-height: 60px;}
</style>
2-7动态组件 - 墙头草
在切换时创建新的组件实例通常是有意义的,但在这个例子中,我们的确想要组件能在被“切走”的时候保留它们的状态。要解决这个问题,我们可以用 `` 内置组件将这些动态组件包装起来:
<!-- 动态组件方式它允许你根据当前组件的状态或其他条件,动态地选择渲染不同的组件include="Home":这句话的意思,就是Home这个页面,在里面定义了一个名字为Home的,改页面的将会有缓存,没有加的则没有
include,可以包含多个--><keep-alive include="List"><component :is="obj[title]"></component></keep-alive>
<!-- 以英文逗号分隔的字符串 -->
<KeepAlive include="a,b"><component :is="view" />
</KeepAlive><!-- 正则表达式 (需使用 `v-bind`) -->
<KeepAlive :include="/a|b/"><component :is="view" />
</KeepAlive><!-- 数组 (需使用 `v-bind`) -->
<KeepAlive :include="['a', 'b']"><component :is="view" />
</KeepAlive>
2-8异步组件(按需加载)
在大型项目中,我们可能需要拆分应用为更小的块,并仅在需要时再从服务器加载相关组件。Vue 提供了 defineAsyncComponent
方法来实现此功能:
//----------------异步组件(按需加载)提高性能-----------------
import { defineAsyncComponent } from 'vue'components: {navbar,tabber,Center,// 这样定义以后,这两个页面,在一开始不会加载,直到使用了之后才会有缓存// **加载与错误提示**Home: defineAsyncComponent( () => import('./components/Home.vue')),List: defineAsyncComponent({// // 加载组件loader: () => import('./components/List.vue'),// 加载异步组件时使用的组件loadingComponent: LoadingComponent,// 展示加载组件前的延迟时间,默认为 200msdelay: 0,// 加载失败后展示的组件errorComponent: ErrorComponent,// 如果提供了一个 timeout 时间限制,并超时了// 也会显示这里配置的报错组件,默认值是:Infinitytimeout: 3000}),},