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()
// bus.$on
// bus.$emit
Vue.component("filmItem", {
props: ["mydata"],
template: `
<div class="item">
<img :src="mydata.poster"/>
{{mydata.name}}
<div>
<button @click="handleClick">详情</button>
</div>
</div>
`,
methods: {
handleClick() {
// console.log(this.mydata.synopsis)
bus.$emit("zzy", this.mydata.synopsis)
}
}
})
Vue.component("filmDetail", {
//组件刚刚创建好,就开始订阅
data() {
return {
info: ""
}
},
//生命周期
mounted() {
// console.log("当前组件上树后触发")
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">
<!-- <home v-show=" which=== 'home' "></home>
<list v-show=" which=== 'list' "></list>
<shopcar v-show=" which=== 'shopcar' "></shopcar> -->
<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>
`
})
// 单个插槽, <slot></slot>
// 具名插槽 <slot name="a"></slot>
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>
`
})
// 单个插槽, <slot></slot>
// 具名插槽 <slot name="a"></slot>
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>
过渡效果
过渡
<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>
<!-- <link rel="stylesheet" href="lib/animate.css"> -->
</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>
初始元素过渡
<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>
<!-- <link rel="stylesheet" href="lib/animate.css"> -->
</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>
多个元素过渡
<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>
<!-- <link rel="stylesheet" href="lib/animate.css"> -->
</head>
<body>
<!-- <div class="zzy-enter-active">333333333333333</div> -->
<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
}
})
/*
diff算法,
1. 同层级对比
2. 同标签, 组件 对比
3. 同key对比
*/
</script>
多个组件过渡
<!-- <home v-show=" which=== 'home' "></home>
<list v-show=" which=== 'list' "></list>
<shopcar v-show=" which=== 'shopcar' "></shopcar> -->
<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>
多个列表过渡
<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">
<!-- 双向绑定的指令 -->
<!-- {{mytext}} -->
<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 = "" //清空value
},
handleDel(index) {
console.log("del", index)
this.datalist.splice(index, 1)
}
}
})
</script>
可重复过渡
<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() {
// 通知父组件 取反 isShow - 子传父 依靠 事件
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">
// Vue.component("navbar",{
// template:``
// })
//根组件
var vm= new Vue({
el:"#box",
data:{
myname:"zzy",
datalist:[]
},
// template:`<div>root component--{{myname}}</div>`,
beforeCreate(){
console.log("beforeCreate",this.myname)
},
created(){
console.log("created","初始化状态或者挂载到当前实例的一些属性")
this.myname = this.myname+"11111111" //被拦截的状态
this.user =localStorage.getItem("user") // this下面的属性
// 发ajax
},
beforeMount(){
console.log("beforeMount",this.$el) // 模板解析之前最后一次修改模板节点。
},
mounted(){
console.log("mounted","拿到真实的dom节点",document.getElementById("box").innerHTML)
// 依赖于dom创建之后, 才进行初始化工作的插件 (轮播插件)
// 订阅 bus.$on
// 发ajax
setTimeout(()=>{
this.datalist = ["1111","222","333"]
// 虚拟dom创建, diff对比 -- 状态立即更新,dom异步更新
// console.log(document.getElementsByTagName("li").length)
},2000)
},
beforeUpdate(){
console.log("beforeUpdate","更新之前,记录老的dom某些状态,比如滚动条位置记录。")
},
updated(){
console.log("updated","更新完成,获取更新的后dom,才进行swiper工作的插件 ")
// console.log(document.getElementsByTagName("li").length)
}
})
</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>
销毁
<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
静态
<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 class="swiper-scrollbar"></div> -->
</div>
F
<footer>底部内容</footer>
<script>
//初始化 swiper
new Swiper(".zzy", {
// direction:"vertical", //垂直
// 如果需要分页器
pagination: {
el: '.swiper-pagination',
},
loop: true,
autoplay: {
delay: 2500,
disableOnInteraction: false,
},
// 如果需要前进后退按钮
navigation: {
nextEl: '.swiper-button-next',
prevEl: '.swiper-button-prev',
},
})
</script>
动态
<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 class="swiper-scrollbar"></div> -->
</div>
<footer>底部内容</footer>
<script>
//swiper 初始化过早。
setTimeout(() => {
var list = ["aaaa", "bbbbb", "cccc"]
var newlist = list.map(item => `<div class="swiper-slide">${item}</div>`)
// console.log(newlist.join(""))
var owrapper = document.querySelector(".swiper-wrapper")
owrapper.innerHTML = newlist.join('')
//dom插入完之后, new swiper
init()
}, 2000)
//初始化 swiper
function init() {
new Swiper(".zzy", {
// direction:"vertical", //垂直
// 如果需要分页器
pagination: {
el: '.swiper-pagination',
},
loop: true,
autoplay: {
delay: 2500,
disableOnInteraction: false,
},
// 如果需要前进后退按钮
navigation: {
nextEl: '.swiper-button-next',
prevEl: '.swiper-button-prev',
},
})
}
</script>
vue-swiper
<style>
/* img{} */
</style>
</head>
<body>
<div id="box">
<header>导航-{{myname}}</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">3333333333</div> -->
<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>
//初始化 swiper --初始化过早
var vm = new Vue({
el: "#box",
data: {
datalist: [],
myname:"zzy"
},
mounted() {
//ajax
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", {
// direction:"vertical", //垂直
// 如果需要分页器
pagination: {
el: '.swiper-pagination',
},
loop: true,
autoplay: {
delay: 2500,
disableOnInteraction: false,
}
})
}
})
/*
1. 无法复用
2. 如果当前页面 状态不止datalist一个,其他状态更新, update重新运行,new Swiper 执行多次, 出bug
*/
</script>
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>
<!-- <swiper :key="datalist.length"></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>
// console.log(Vue.component)
var obj = {
data() {
return {
myname: "zzy"
}
},
methods: {
},
computed: {
},
created() {
console.log("created")
},
beforeMount() {
},
mounted() {
console.log("mounted")
},
//生命周期替换
// beforeDestroy(){
// console.log("beforedestory")
// },
// destroyed(){
// }
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")
// vue2 (类,this)
// vue3 类(>90% 一样), hooks(函数式)
</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>
<!-- <swiper :key="datalist.length"></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() {
// console.log("mounted")
new Swiper(".kerwin", {
// direction:"vertical", //垂直
// 如果需要分页器
pagination: {
el: '.swiper-pagination',
},
loop: this.loop,
autoplay: {
delay: 2500,
disableOnInteraction: false,
}
})
},
// destroyed() {
// // console.log("destroy")
// //
// }
})
app.mount("#box")
</script>