一、组件-非父子通信
<div id="box">
<child1></child1>
<child2></child2>
</div>
<script type="text/javascript">
var bus = new Vue()
Vue.component("child1", {
template: `
<div>child1</div>
`,
mounted() {
console.log("moutend", "8个生命周期中一个,组件上树后触发")
bus.$on("zzy", (data) => {
console.log("child1监听的函数", data)
})
}
})
Vue.component("child2", {
template: `
<div>child2
<button @click="handleClick">click</button>
</div>
`,
methods: {
handleClick() {
bus.$emit("zzy", "1111111111111111111")
}
}
})
var vm = new Vue({
el: "#box",
methods: {
}
})
</script>
二、bus案例
<div id="box">
<button @click="handleAjax">ajax</button>
<film-item v-for="item in datalist" :key="item.filmId" :mydata="item"></film-item>
<film-detail></film-detail>
</div>
<script>
var bus = new Vue()
Vue.component("filmItem", {
props: ["mydata"],
template: `
<div class="item">
<img :src="mydata.poster"/>
{{mydata.name}}
<div>
<button @click="handleClick">详情</button>
</div>
</div>
`,
methods: {
handleClick() {
bus.$emit("zzy", this.mydata.synopsis)
}
}
})
Vue.component("filmDetail", {
data() {
return {
info: ""
}
},
mounted() {
bus.$on("zzy", (data) => {
console.log("1111111", data)
this.info = data
})
},
template: `
<div class="filminfo">
{{info}}
</div>
`
})
new Vue({
el: "#box",
data: {
datalist: [],
},
methods: {
handleAjax() {
fetch("./json/test.json")
.then(res => res.json())
.then(res => {
console.log(res.data.films)
this.datalist = res.data.films
})
}
}
})
</script>
三、props修改
<div id="box">
<div v-once>
{{title}}
</div>
<child :mytitle="title"></child>
</div>
<script>
Vue.component("child", {
props: ["mytitle"],
template: `
<div >
child-{{mytitle}}
<button @click="handleClikc">click</button>
</div>
`,
methods: {
handleClikc() {
this.mytitle = "22222222222222"
}
}
})
var vm = new Vue({
el: "#box",
data: {
title: "11111111111111"
}
})
</script>
四、动态组件
<div id="box">
<keep-alive>
<component :is="which"></component>
</keep-alive>
<footer>
<ul>
<li @click=" which='home' ">
首页
</li>
<li @click=" which='list' ">
列表
</li>
<li @click=" which='shopcar' ">
购物车
</li>
</ul>
</footer>
</div>
<script type="text/javascript">
Vue.component("home", {
template: `
<div>
home
<input type="search"/>
</div>
`
})
Vue.component("list", {
template: `
<div>
list
</div>
`
})
Vue.component("shopcar", {
template: `
<div>
shopcar
</div>
`
})
var vm = new Vue({
el: "#box",
data: {
which: 'home'
}
})
</script>
五、slot
<div id="box">
<child>
<div slot="a">11111111111111</div>
<div slot="b">22222222222222</div>
<div slot="c">33333333333333</div>
<div>44444444444444</div>
</child>
<navbar>
<button slot="left">aaa</button>
<i class="iconfont icon-all" slot="right">字体图标</i>
</navbar>
</div>
<script>
Vue.component("navbar", {
template: `
<div>
<slot name="left"></slot>
<span>navbar</span>
<slot name="right"></slot>
</div>
`
})
Vue.component("child", {
template: `
<div>
child
<slot name="a"></slot>
<slot name="b"></slot>
<slot name="c"></slot>
<slot></slot>
</div>
`
})
new Vue({
el: "#box"
})
</script>
六、slot例子
<div id="box">
<navbar>
<button @click="isShow=!isShow">click</button>
</navbar>
<sidebar v-show="isShow"></sidebar>
</div>
<script>
Vue.component("navbar", {
template: `
<div style="background:yellow">
nabbar- <slot></slot>
</div>
`,
})
Vue.component("sidebar", {
template: `
<ul style="background-color: yellow;width: 200px;height: 500px;" >
<li>首页</li>
<li>钱包</li>
<li>设置</li>
</ul>
`
})
new Vue({
el: "#box",
data: {
isShow: false
}
})
</script>
七、新slot
<div id="box">
<child>
<template v-slot:a>
<div>1111111111</div>
</template>
<template #b>
2222222222222222222
</template>
<div slot="c">33333333333333</div>
<div>44444444444444</div>
</child>
<navbar>
<template #left>
<button>aaa</button>
</template>
<template #right>
<i class="iconfont icon-all">字体图标</i>
</template>
</navbar>
</div>
<script>
Vue.component("navbar", {
template: `
<div>
<slot name="left"></slot>
<span>navbar</span>
<slot name="right"></slot>
</div>
`
})
Vue.component("child", {
template: `
<div>
child
<slot name="a"></slot>
<slot name="b"></slot>
<slot name="c"></slot>
<slot></slot>
</div>
`
})
new Vue({
el: "#box"
})
</script>
八、过渡效果
<1>.过度
<style>
.zzy-enter-active {
animation: aaa 1.5s;
}
.zzy-leave-active {
animation: aaa 1.5s reverse;
}
@keyframes aaa {
0% {
opacity: 0;
transform: translateX(100px);
}
100% {
opacity: 1;
transform: translateX(0px);
}
}
</style>
</head>
<body>
<div id="box">
<button @click="isShow= !isShow">change</button>
<transition enter-active-class="zzy-enter-active" leave-active-class="zzy-leave-active">
<div v-show="isShow">1111111111111111</div>
</transition>
<transition name="zzy">
<div v-if="isShow">
<div>222222222222222222</div>
<div>333333333333333</div>
<div>44444444444444444</div>
<div>55555555555555555</div>
</div>
</transition>
</div>
<script>
new Vue({
el: "#box",
data: {
isShow: false
}
})
</script>
<2>.初始元素过渡
<style>
.zzy-enter-active {
animation: aaa 1.5s;
}
.zzy-leave-active {
animation: aaa 1.5s reverse;
}
@keyframes aaa {
0% {
opacity: 0;
transform: translateX(100px);
}
100% {
opacity: 1;
transform: translateX(0px);
}
}
</style>
</head>
<body>
<div id="box">
<button @click="isShow= !isShow">change</button>
<transition enter-active-class="zzy-enter-active" leave-active-class="zzy-leave-active">
<div v-show="isShow">1111111111111111</div>
</transition>
<transition name="zzy" appear>
<div v-if="isShow">222222222222222222</div>
</transition>
</div>
<script>
new Vue({
el:"#box",
data:{
isShow:true
}
})
</script>
<3>.多个元素过渡
<style>
.zzy-enter-active {
animation: aaa 1.5s;
}
.zzy-leave-active {
animation: aaa 1.5s reverse;
}
@keyframes aaa {
0% {
opacity: 0;
transform: translateX(100px);
}
100% {
opacity: 1;
transform: translateX(0px);
}
}
</style>
</head>
<body>
<div id="box">
<button @click="isShow = !isShow">change</button>
<transition name="zzy" mode="out-in">
<div v-if="isShow" key="1">111111111111111</div>
<div v-else key="2">2222222222222222222222222</div>
</transition>
</div>
<script type="text/javascript">
var vm = new Vue({
el: "#box",
data: {
isShow: true
}
})
</script>
<4>.多个组件过渡
<style type="text/css">
* {
margin: 0px;
padding: 0px;
}
html,
body {
width: 100%;
height: 100%;
overflow-x: hidden;
}
footer ul {
display: flex;
position: fixed;
left: 0px;
bottom: 0px;
width: 100%;
height: 40px;
}
footer ul li {
flex: 1;
text-align: center;
list-style: none;
height: 40px;
line-height: 40px;
background: gray;
color: white;
}
</style>
<style>
.zzy-enter-active {
animation: aaa 1.5s;
}
.zzy-leave-active {
animation: aaa 1.5s reverse;
}
@keyframes aaa {
0% {
opacity: 0;
transform: translateX(100px);
}
100% {
opacity: 1;
transform: translateX(0px);
}
}
</style>
</head>
<body>
<div id="box">
<keep-alive>
<transition name="zzy" mode="out-in">
<component :is="which"></component>
</transition>
</keep-alive>
<footer>
<ul>
<li @click=" which='home' ">
首页
</li>
<li @click=" which='list' ">
列表
</li>
<li @click=" which='shopcar' ">
购物车
</li>
</ul>
</footer>
</div>
<script type="text/javascript">
Vue.component("home", {
template: `
<div>
home
<input type="search"/>
</div>
`
})
Vue.component("list", {
template: `
<div>
list
</div>
`
})
Vue.component("shopcar", {
template: `
<div>
shopcar
</div>
`
})
var vm = new Vue({
el: "#box",
data: {
which: 'home'
}
})
</script>
<5>.多个列表过渡
<style>
.zzy-enter-active {
animation: aaa 1.5s;
}
.zzy-leave-active {
animation: aaa 1.5s reverse;
}
@keyframes aaa {
0% {
opacity: 0;
transform: translateX(100px);
}
100% {
opacity: 1;
transform: translateX(0px);
}
}
</style>
</head>
<body>
<div id="box">
<input type="text" v-model="mytext" />
<button @click="handleAdd()">add</button>
<div v-show="!datalist.length">待办事项空空如也</div>
<transition-group name="zzy" tag="ul" v-show="datalist.length">
<li v-for="(item,index) in datalist" :key="item">
{{item}}--{{index}}
<button @click="handleDel(index)">del</button>
</li>
</transition-group>
</div>
<script>
var vm = new Vue({
el: "#box",
data: {
mytext: "11111",
datalist: ["111", "222", "333"]
},
methods: {
handleAdd() {
console.log("add", this.mytext)
this.datalist.push(this.mytext)
this.mytext = ""
},
handleDel(index) {
console.log("del", index)
this.datalist.splice(index, 1)
}
}
})
</script>
<6>.可复用过渡
<style>
.left {}
.right {
position: fixed;
right: 0px;
top: 0px;
}
.left-enter-active {
animation: aaa 1.5s;
}
.left-leave-active {
animation: aaa 1.5s reverse;
}
@keyframes aaa {
0% {
opacity: 0;
transform: translateX(-100%);
}
100% {
opacity: 1;
transform: translateX(0px);
}
}
.right-enter-active {
animation: bbb 1.5s;
}
.right-leave-active {
animation: bbb 1.5s reverse;
}
@keyframes bbb {
0% {
opacity: 0;
transform: translateX(100px);
}
100% {
opacity: 1;
transform: translateX(0px);
}
}
</style>
</head>
<body>
<div id="box">
<navbar @myevent="handleEvent"></navbar>
<sidebar v-show="isShow" mode="right"></sidebar>
</div>
<script>
Vue.component("navbar", {
template: `
<div>
nabbar-<button @click="handleClick">click</button>
</div>
`,
methods: {
handleClick() {
this.$emit("myevent")
}
}
})
Vue.component("sidebar", {
props: ["mode"],
template: `
<transition :name="mode">
<ul style="background-color: yellow;width: 200px;height: 500px;" :class="mode">
<li>首页</li>
<li>钱包</li>
<li>设置</li>
</ul>
</transition>
`
})
new Vue({
el: "#box",
data: {
isShow: false
},
methods: {
handleEvent() {
console.log("父组件", "1111111")
this.isShow = !this.isShow
}
}
})
</script>
九、组件生命周期
<div id="box">
{{myname}}
<button @click=" myname='xiaoming' ">change</button>
<ul>
<li v-for="data in datalist" :key="data">
{{data}}
</li>
</ul>
</div>
<script type="text/javascript">
var vm= new Vue({
el:"#box",
data:{
myname:"zzy",
datalist:[]
},
beforeCreate(){
console.log("beforeCreate",this.myname)
},
created(){
console.log("created","初始化状态或者挂载到当前实例的一些属性")
this.myname = this.myname+"11111111"
this.user =localStorage.getItem("user")
},
beforeMount(){
console.log("beforeMount",this.$el)
},
mounted(){
console.log("mounted","拿到真实的dom节点",document.getElementById("box").innerHTML)
setTimeout(()=>{
this.datalist = ["1111","222","333"]
},2000)
},
beforeUpdate(){
console.log("beforeUpdate","更新之前,记录老的dom某些状态,比如滚动条位置记录。")
},
updated(){
console.log("updated","更新完成,获取更新的后dom,才进行swiper工作的插件 ")
}
})
</script>
十、销毁
<div id="box">
<child v-if="isCreated"></child>
</div>
<script>
Vue.component("child", {
data() {
return {
time: 1000
}
},
created() {
this.id = null
},
mounted() {
this.id = setInterval(() => {
console.log("倒计时")
this.time--
}, 1000)
window.onresize = () => {
console.log("resize")
}
},
template: `
<div>
抢购倒计时组件
<div>{{time}}</div>
</div>
`,
beforeDestroy() {
console.log("beforeDestroy", "清除定时器, 事件解绑,,,,")
clearInterval(this.id)
window.onresize = null
},
destroyed() {
console.log("destroyed", "清除定时器, 事件解绑,,,,")
}
})
var vm = new Vue({
el: "#box",
data: {
isCreated: true
}
})
</script>
十一、swiper
<1>.静态
<style>
.zzy {
height: 500px;
}
</style>
</head>
<body>
<header>导航</header>
<div class="swiper-container zzy">
<div class="swiper-wrapper">
<div class="swiper-slide">111111111111</div>
<div class="swiper-slide">222222222222</div>
<div class="swiper-slide">333333333333</div>
</div>
<div class="swiper-pagination"></div>
<div class="swiper-button-prev"></div>
<div class="swiper-button-next"></div>
</div>
F
<footer>底部内容</footer>
<script>
new Swiper(".zzy", {
pagination: {
el: '.swiper-pagination',
},
loop: true,
autoplay: {
delay: 2500,
disableOnInteraction: false,
},
navigation: {
nextEl: '.swiper-button-next',
prevEl: '.swiper-button-prev',
},
})
</script>
<2>.动态
<style>
.zzy {
height: 500px;
}
</style>
</head>
<body>
<header>导航</header>
<div class="swiper-container zzy">
<div class="swiper-wrapper">
</div>
<div class="swiper-pagination"></div>
<div class="swiper-button-prev"></div>
<div class="swiper-button-next"></div>
</div>
<footer>底部内容</footer>
<script>
setTimeout(() => {
var list = ["aaaa", "bbbbb", "cccc"]
var newlist = list.map(item => `<div class="swiper-slide">${item}</div>`)
var owrapper = document.querySelector(".swiper-wrapper")
owrapper.innerHTML = newlist.join('')
init()
}, 2000)
function init() {
new Swiper(".zzy", {
pagination: {
el: '.swiper-pagination',
},
loop: true,
autoplay: {
delay: 2500,
disableOnInteraction: false,
},
navigation: {
nextEl: '.swiper-button-next',
prevEl: '.swiper-button-prev',
},
})
}
</script>
<3>.vue-swiper
<style>
</style>
</head>
<body>
<div id="box">
<header>导航-{{myname}}</header>
<div class="swiper-container zzy">
<div class="swiper-wrapper">
<div class="swiper-slide" v-for="data in datalist" :key="data">
<img :src="data" />
</div>
</div>
<div class="swiper-pagination"></div>
</div>
<footer>底部内容</footer>
</div>
<script>
var vm = new Vue({
el: "#box",
data: {
datalist: [],
myname:"zzy"
},
mounted() {
setTimeout(() => {
this.datalist = ["https://static.maizuo.com/pc/v5/usr/movie/e856bdc65507b99800f22e47801fa781.jpg",
"https://static.maizuo.com/pc/v5/usr/movie/47aa5a3ad2ebff403d073288e4365694.jpg",
"https://static.maizuo.com/pc/v5/usr/movie/8b0755547313706883acc771bda7709d.jpg"
]
}, 2000)
},
updated(){
console.log(document.querySelectorAll(".swiper-slide").length)
new Swiper(".zzy", {
pagination: {
el: '.swiper-pagination',
},
loop: true,
autoplay: {
delay: 2500,
disableOnInteraction: false,
}
})
}
})
</script>
<4>.vue-swiper-组件
<div id="box">
<swiper v-if="datalist.length" :loop="false">
<swiper-item v-for="data in datalist" :key="data">
<img :src="data"/>
</swiper-item>
</swiper>
</div>
<script>
new Vue({
el:'#box',
data:{
datalist:[]
},
mounted(){
setTimeout(()=>{
this.datalist = ["https://static.maizuo.com/pc/v5/usr/movie/e856bdc65507b99800f22e47801fa781.jpg",
"https://static.maizuo.com/pc/v5/usr/movie/47aa5a3ad2ebff403d073288e4365694.jpg",
"https://static.maizuo.com/pc/v5/usr/movie/8b0755547313706883acc771bda7709d.jpg"
]
},2000)
}
})
</script>
十二、Vue3 组件写法
<div id="box">
{{myname}}
<navbar myname="aaaa">
<div>111111111111111</div>
</navbar>
<sidebar></sidebar>
</div>
<script>
var obj = {
data() {
return {
myname: "zzy"
}
},
methods: {
},
computed: {
},
created() {
console.log("created")
},
beforeMount() {
},
mounted() {
console.log("mounted")
},
beforeUnmount() {
},
unmounted() {
}
}
var app = Vue.createApp(obj)
app.component("navbar", {
props: ["myname"],
template: `
<div>
navbar-{{myname}}
<slot></slot>
</div>
`
})
app.component("sidebar", {
template: `<div>
sidebar
</div>`
})
app.mount("#box")
</script>
十三、Vue3生命周期
<div id="box">
<swiper v-if="datalist.length" :loop="false">
<swiper-item v-for="data in datalist" :key="data">
<img :src="data" />
</swiper-item>
</swiper>
</div>
<script>
var obj = {
data() {
return {
datalist: []
}
},
mounted() {
setTimeout(() => {
this.datalist = ["https://static.maizuo.com/pc/v5/usr/movie/e856bdc65507b99800f22e47801fa781.jpg",
"https://static.maizuo.com/pc/v5/usr/movie/47aa5a3ad2ebff403d073288e4365694.jpg",
"https://static.maizuo.com/pc/v5/usr/movie/8b0755547313706883acc771bda7709d.jpg"
]
}, 2000)
}
}
var app = Vue.createApp(obj)
app.component("swiperItem", {
template: `
<div class="swiper-slide">
<slot></slot>
</div>
`
})
app.component("swiper", {
props: {
loop: {
type: Boolean,
default: true
}
},
template: `
<div class="swiper-container kerwin">
<div class="swiper-wrapper">
<slot></slot>
</div>
<div class="swiper-pagination"></div>
</div>`,
mounted() {
new Swiper(".kerwin", {
pagination: {
el: '.swiper-pagination',
},
loop: this.loop,
autoplay: {
delay: 2500,
disableOnInteraction: false,
}
})
},
})
app.mount("#box")
</script>