一、组件化开发介绍
1.组件是什么?有什么用?
组件就是:扩展 HTML 元素,封装可重用的代码
,目的是复用
例如:有一个轮播图,可以在很多页面中使用,一个轮播有js,css,html
组件把js,css,html放到一起,有逻辑,有样式,有html
组件的分类:
- 全局组件:可以放在根中
- 局部组件:
工程化开发之后:
1个组件 就是1个xx.vue
2.什么是组件化?
如果我们将一个页面中所有的处理逻辑全部放在一起,处理起来就会变得非常复杂,而且不利于后续的管理以及扩展。
但如果,我们讲一个页面拆分成一个个小的功能块,每个功能块完成属于自己这部分独立的功能,那么之后整个页面的管理和维护就变得非常容易了。
组件化定义:
- 我们将一个完整的页面分成很多个组件。
- 每个组件都用于实现页面的一个功能块。
- 而每一个组件又可以进行细分。
3.Vue组件化思想
组件化是Vue.js中的重要思想
- 它提供了一种抽象,让我们可以开发出一个个独立可复用的小组件来构造我们的应用。
- 任何的应用都会被抽象成一颗组件树。
组件化思想的应用:
- 有了组件化的思想,我们在之后的开发中就要充分的利用它,目的是复用。
- 尽可能的将页面拆分成一个个小的、可复用的组件。
- 这样让我们的代码更加方便组织和管理,并且扩展性也更强。
所以,组件是Vue开发中,非常重要的一个篇章,要认真学习。
二、组件注册
1.组件注册基本步骤
组件的使用分成三个步骤:
- 创建组件构造器
- 注册组件
- 使用组件
2.注册组件步骤解析
1.Vue.extend():
- 调用Vue.extend()创建的是一个组件构造器。
- 通常在创建组件构造器时,传入template代表我们自定义组件的模板。
- 该模板就是在使用到组件的地方,要显示的HTML代码。
- 事实上,这种写法在Vue2.x的文档中几乎已经看不到了,它会直接使用下面我们会讲到的语法糖,但是在很多资料还是会提到这种方式,而且这种方式是学习后面方式的基础。
2.Vue.component():
- 调用Vue.component()是将刚才的组件构造器注册为一个组件,并且给它起一个组件的标签名称。
- 所以需要传递两个参数:
- 注册组件的标签名
- 组件构造器
- 组件必须挂载在某个Vue实例下,否则它不会生效。
3. 定义全局组件,绑定事件,编写样式
全局组件:当我们通过调用Vue.component()注册组件时,组件的注册是全局的,这意味着该组件可以在任意Vue示例下使用。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>全局组件</title> <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script> </head> <body> <div id="box"> <div @click="handleClick">我是根部组件</div> <global></global> <ul> <li v-for="i in 4"> <global></global> </li> </ul> </div> </body> <script> // 创建1个组件对象(全局组件) Vue.component('global', { template: ` <div> <div style="background: rgba(255,104,104,0.7); padding: 5px;" @click="handleClick">我是头部组件</div> <div v-if="isShow">显示消失</div> </div> `, methods: { handleClick() { console.log('我被点击了') this.isShow = !this.isShow } }, data() { return { isShow: true } } }) let vm = new Vue({ el: '#box', data: { isShow: true }, methods: { handleClick() { console.log('我被点击了 我是根组件') } } }) </script> </html>
4.定义局部组件
局部组件:如果我们注册的组件是挂载在某个实例中, 那么就是一个局部组件
① 局部组件 放在 Vue实例(根组件) 中
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>局部组件</title> <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script> </head> <body> <div id="box" style="max-width: 300px"> <local></local> <global></global> </div> </body> <script> // 创建1个组件对象(全局组件) Vue.component('global', { template: ` <div> <div style="background: rgba(255,104,104,0.7); padding: 5px 10px; border-radius: 5px;margin: 5px 0;"> 我是全局组件 </div> </div> `, }) let vm = new Vue({ el: '#box', data: {}, // 创建1个组件对象(局部组件) components: { local: { // local 组件名 template: ` <div> <div style="background: rgba(104,255,104,0.7); padding: 5px 10px; border-radius: 5px; margin: 3px 50px 3px 0;" @click="handleClick">我是局部组件 </div> </div> `, // 组件的模板 methods: { handleClick() { console.log('我被点击了') } } } } }) </script> </html>
② 局部组件 放在 全局组件 中
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>局部组件</title> <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script> </head> <body> <div id="box" style="max-width: 300px"> <ul> <li v-for="i in 3"> <global></global> </li> </ul> </div> </body> <script> // 创建1个组件对象(全局组件) Vue.component('global', { template: ` <div> <div style="background: rgba(255,104,104,0.7); padding: 5px 10px; border-radius: 5px;margin: 5px 0;"> 我是全局的组件 </div> <local></local> <local></local> <br> </div> `, // 创建1个组件对象(局部组件) components: { local: { template: ` <div> <div style="background: rgba(104,255,104,0.7); padding: 5px 10px; border-radius: 5px; margin: 3px 50px 3px 0;">我是局部组件</div> </div> `, } } }) let vm = new Vue({ el: '#box', }) </script> </html>
注意点:
- 定义的组件(body中的位置)必须要放在Vue实例(这也是一个组件 根组件)中
- 局部组件 必须放在 全局组件/根组件 中,无法单独使用
- 定义的组件必须在Vue实例的上方
二:组件 与 Vue实例的区别
Vue实例(其实,它也是1个组件,是1个根组件)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script> </head> <body> <div id="box"> <ul> <li>字符串:{{name}}</li> <li>数值:{{age}}</li> <li><button @click="handleClick()">Click Here</button></li> </ul> </div> </body> <script> let vm = new Vue({ el: '#box', data: { name: 'Darker', age: 18, }, methods: { handleClick() { alert('按钮被点击') } } }) </script> </html>
组件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>局部组件</title> <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script> </head> <body> <div id="box" style="max-width: 300px"> <ul> <li v-for="i in 3"> <global></global> </li> </ul> </div> </body> <script> // 创建1个组件对象(全局组件) Vue.component('global', { template: ` <div> <div style="background: rgba(255,104,104,0.7); padding: 5px 10px; border-radius: 5px;margin: 5px 0;"> 我是全局组件 </div> <local></local> <br> </div> `, // 创建1个组件对象(局部组件) components: { local: { template: ` <div> <div style="background: rgba(104,255,104,0.7); padding: 5px 10px; border-radius: 5px; margin: 3px 50px 3px 0;">我是局部组件</div> </div> `, } } }) let vm = new Vue({ el: '#box', }) </script> </html>
区别:
1. 自定义组件需要有1个 root element
,一般包裹在 1个div
中
2. 父子组件的data
是无法共享的
- 这一点就像Docker的容器一样,是相互隔离的
- 就算父子的data中数据相同,拥有相同的方法,也是互不影响的
3. 组件可以有data、methods、computed…,但是 data
必须是一个函数
Vue实例:data是1个键值对,用来存放属性的
var vm = new Vue({
el: '#box',
data: {
isShow: true
}
})
组件:data是1个函数,需要有返回值(return
)
Vue.component('global', {
template: `
<div>
<div style="background: rgba(255,104,104,0.7); padding: 5px;" @click="handleClick">我是头部组件</div>
<div v-if="isShow">显示消失</div>
</div>
`,
methods: {
handleClick() {
console.log('我被点击了')
this.isShow = !this.isShow
}
},
data() {
return {
isShow: true
}
}
})
三、组件通信
1.父传子
- 在全局组件中自定义属性:
<global :myname="name" :myage="19"></global>
- 在组件中获取:
{{myname}}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>组件</title>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
</head>
<body>
<div id="box">
<!-- myName是自定义属性 -->
<global myname="name" myage="18"></global>
<global :myname="name" :myage="19"></global>
<global :myname="'Ben'" :myage="20"></global>
</div>
</body>
<script>
// 创建1个组件对象(全局组件/子组件)
Vue.component('global', {
template: `
<div>
<div style="background: rgba(255,104,104,0.7); padding: 5px;">全局组件/子组件</div>
{{myname}}
{{myage}}
</div>
`,
props: ['myname', 'myage']
})
// 父组件
let vm = new Vue({
el: '#box',
data: {
name: 'darker'
},
})
</script>
</html>
属性验证
- 限制父传子的变量类型
props: {
myname: String,
isshow: Boolean
}
- 父传子时候注意以下区别
<global :myname="name" :is_show="'false'"></global>
<global :myname="name" :is_show="false"></global>
<global :myname="name" :is_show="is_show"></global>
- 实例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>组件</title>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
</head>
<body>
<div id="box">
<!-- myName是自定义属性 -->
<!-- <global :myname="name" :myage="19" :isshow="'false'"></global>-->
<global :my_name="name" :is_show="is_show"></global>
<global :my_name="name" :is_show="false"></global>
</div>
</body>
<script>
// 创建1个组件对象(全局组件/子组件)
Vue.component('global', {
template: `
<div>
<div style="background: rgba(255,104,104,0.7); padding: 5px;">我是子组件:{{is_show}}</div>
<span>{{my_name}}</span>
</div>
`,
props: {
my_name: String,
is_show: Boolean
}
})
// 父组件
let vm = new Vue({
el: '#box',
data: {
name: 'darker',
is_show: true
},
})
</script>
</html>
2.子传父(通过事件)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>子传父</title>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
</head>
<body>
<div id="box">
<global @my_event="handleClick($event)"></global>
</div>
</body>
<script>
// 创建1个组件对象(全局组件/子组件)
Vue.component('global', {
template: `
<div>
<div style="background: rgba(255,104,104,0.7); padding: 5px;">全局组件/子组件</div>
<button @click="handleNav">点我</button>
</div>
`,
data() {
return {
name: 'Darker'
}
},
methods: {
handleNav() {
console.log('我是子组件的函数')
this.$emit('my_event', 666, 777, this.name)
}
}
})
// 父组件
let vm = new Vue({
el: '#box',
data: {},
methods: {
handleClick(a,b,c) {
console.log('我是父组件的函数')
console.log(a)
console.log(b)
console.log(c)
}
}
})
</script>
</html>
3.子传父(控制子组件的显示和隐藏)
点击子组件,就会触发父组件的某个函数执行
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>子传父</title>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
</head>
<body>
<div id="box">
<global @my_event="handleClick($event)"></global>
</div>
</body>
<script>
// 创建1个组件对象(全局组件/子组件)
Vue.component('global', {
template: `
<div>
<div style="background: rgba(255,104,104,0.7); padding: 5px;">全局组件/子组件</div>
<button @click="handleNav">点我</button>
</div>
`,
data() {
return {
name: 'Darker'
}
},
methods: {
handleNav() {
console.log('我是子组件的函数')
this.$emit('my_event', 666, 777, this.name)
}
}
})
// 父组件
let vm = new Vue({
el: '#box',
data: {},
methods: {
handleClick(a,b,c) {
console.log('我是父组件的函数')
console.log(a)
console.log(b)
console.log(c)
}
}
})
</script>
</html>
小案例
- 子组件有1个按钮 和 1个输入框,子组件输入完内容后,数据在父组件中展示
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>子传父 小案例</title>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
</head>
<body>
<div id="box">
<global @my_event="handleShow($event)"></global>
<br>
<div>父组件接收到的数据:{{name}}</div>
</div>
</body>
<script>
// 创建1个组件对象(全局组件/子组件)
Vue.component('global', {
template: `
<div>
<input type="text" v-model="myText">
<button @click="handleClick">点我传数据</button>
</div>
`,
data() {
return {
myText: ''
}
},
methods: {
handleClick() {
this.$emit('my_event', this.myText)
}
}
})
// 父组件
let vm = new Vue({
el: '#box',
data: {
name: ''
},
methods: {
handleShow(a) {
this.name = a
}
}
})
</script>
</html>
4.ref属性(也可以实现组件间通信:子和父都可以实现通信)
- ref放在
标签
上,拿到的是原生的DOM节点
- ref放在
组件
上,拿到的是组件对象
,对象中的数据、函数 都可以直接使用 - 通过这种方式实现子传父(this.$refs.mychild.text)
- 通过这种方式实现父传子(调用子组件方法传参数)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>子传父</title>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
</head>
<body>
<div id="box">
<input type="text" ref="myRef">
<button @click="handleButton">点我</button>
</div>
</body>
<script>
// 创建1个组件对象(全局组件/子组件)
Vue.component('global', {
template: `
<div>
<input type="text" v-model="myText">
</div>
`,
data() {
return {
myText: ''
}
},
methods: {
handleClick() {
this.$emit('my_event', this.myText)
this.$emit('my_event', this.innerHTML)
}
}
})
// 父组件
let vm = new Vue({
el: '#box',
data: {
name: ''
},
methods: {
handleShow(a) {
this.name = a
},
handleButton() {
console.log(this.$refs)
console.log(this.$refs.myRef)
console.log(this.$refs.myRef.value)
}
}
})
</script>
</html>
[
5.事件总线(不同层级的不同组件通信)
原本的通信方式
事件总线的通信方式
实例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>子传父</title>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
</head>
<body>
<div id="box">
<global1></global1>
<hr>
<global2></global2>
</div>
</body>
<script>
// 定义1个事件总线
let bus = new Vue({})
// 组件1
Vue.component('global1', {
template: `
<div>
<h3>组件1</h3>
<input type="text" v-model="myText">
<button @click="handleClick1">点我传递数据到另一个组件</button>
</div>
`,
data() {
return {
myText: ''
}
},
methods: {
handleClick1() {
console.log(this.myText)
bus.$emit('any', this.myText) // 通过事件总线发送
}
}
})
// 组件2
Vue.component('global2', {
template: `
<div>
<h3>组件2</h3>
收到的消息是:{{recvText}}
</div>
`,
data() {
return {
recvText: ''
}
},
mounted() { // 组件的挂载(生命周期钩子函数中的1个),开始监听时间总线上的:any
bus.$on('any', (item) => {
console.log('收到了', item,)
this.recvText = item
})
},
methods: {}
})
// 父组件
let vm = new Vue({
el: '#box',
data: {},
})
</script>
</html>
四:动态组件
1.基本使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>动态组件</title>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
</head>
<body>
<div id="box">
<ul>
<li>
<button @click="who='child1'">首页</button>
</li>
<li>
<button @click="who='child2'">订单</button>
</li>
<li>
<button @click="who='child3'">商品</button>
</li>
</ul>
<component :is="who"></component>
</div>
</body>
<script>
let vm = new Vue({
el: '#box',
data: {
who: 'child1'
},
components: {
child1: {
template: `
<div>
<span style="border-bottom: 5px solid rgba(255,104,104,0.7)">我是首页</span>
</div>
`,
},
child2: {
template: `
<div>
<span style="border-bottom: 5px solid rgba(255,104,255,0.7)">我是订单</span>
</div>
`,
},
child3: {
template: `
<div>
<span style="border-bottom: 5px solid rgba(104,255,104,0.7)">我是商品</span>
</div>
`,
}
}
})
</script>
</html>
[](https://gitee.com/xuexianqi/img/raw/master/img/16 dynamic01.gif)
2.keep-alive的使用
keep-alive
可以让输入框内有的内容一致保持,不会因为切换而重置
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="box">
<ul>
<li>
<button @click="who='child1'">首页</button>
</li>
<li>
<button @click="who='child2'">订单</button>
</li>
<li>
<button @click="who='child3'">商品</button>
</li>
</ul>
<keep-alive>
<component :is="who"></component>
</keep-alive>
</div>
</body>
<script>
let vm = new Vue({
el: '#box',
data: {
who: 'child1'
},
components: {
child1: {
template: `
<div>
<span style="border-bottom: 5px solid rgba(255,104,104,0.7)">我是首页</span>
<input type="text">
</div>
`,
},
child2: {
template: `
<div>
<span style="border-bottom: 5px solid rgba(255,104,255,0.7)">我是订单</span>
<input type="text">
</div>
`,
},
child3: {
template: `
<div>
<span style="border-bottom: 5px solid rgba(104,255,104,0.7)">我是商品</span>
<input type="text">
</div>
`,
}
}
})
</script>
</html>
[](https://gitee.com/xuexianqi/img/raw/master/img/17 dynamic02.gif)
五:slot 插槽
- 一般情况下,编写完1个组件之后,组件的内容都是写死的,需要加数据 只能去组件中修改,扩展性很差
- 然后就出现了插槽这个概念,只需在组件中添加
<slot></slot>
,就可以在body的组件标签中添加内容
1.基本使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>slot 插槽</title>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
</head>
<body>
<div id="box">
<child>
<h6>Hello World</h6>
</child>
</div>
</body>
<script>
let vm = new Vue({
el: '#box',
data: {
who: 'child1'
},
components: {
child: {
template: `
<div>
<slot></slot>
<span style="border-bottom: 5px solid rgba(255,104,104,0.7)">我是组件的原内容</span>
<slot></slot>
</div>
`,
},
}
})
</script>
</html>
2.小案例(通过插槽实现在1个组件中控制另1个组件的显示隐藏)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>slot 插槽</title>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
</head>
<body>
<div id="box">
<!--通过插槽实现在一个组件中控制另一个组件的显示隐藏-->
<child1>
<button @click="isShow=!isShow">显示/隐藏组件2</button>
</child1>
<child2 v-if="isShow"></child2>
</div>
</body>
<script>
Vue.component('child1', {
template: `<div>
组件1
<slot></slot>
</div>`,
})
Vue.component('child2', {
template: `<div>
<h3>组件2</h3>
</div>`,
})
var vm = new Vue({
el: '#box',
data: {
isShow: true
}
})
</script>
</html>
3.具名插槽
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>具名插槽</title>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
</head>
<body>
<div id="box">
<!-- 具名插槽,把p标签给a插槽,div标签给b插槽-->
<child>
<p slot="a">我是具名插槽a插入的内容</p>
<div slot="b">我是具名插槽b插入的内容</div>
</child>
</div>
</body>
<script>
Vue.component('child', {
template: `<div>
<slot name="a"></slot>
<hr>
<span style="border-bottom: 5px solid rgba(255,104,104,0.7)">我是组件的原内容</span>
<hr>
<slot name="b"></slot>
</div>`,
})
var vm = new Vue({
el: '#box',
data: {}
})
</script>
</html>
可以指定标签放在某个插槽的位置
六:自定义组件的封装
详情见:http://www.xuexianqi.top/archives/732.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="https://unpkg.com/swiper/swiper-bundle.css">
<script src="https://unpkg.com/swiper/swiper-bundle.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
<style>
.swiper-container {
width: 600px;
height: 200px;
}
</style>
</head>
<body>
<div id="box">
<swipper>
<div class="swiper-wrapper">
<div class="swiper-slide" v-for="data in dataList1"><h1 style="text-align: center">{{data}}</h1></div>
</div>
</swipper>
<swipper :key="dataList2.length">
<div class="swiper-wrapper">
<div class="swiper-slide" v-for="data in dataList2"><h1 style="text-align: center">{{data}}</h1></div>
</div>
</swipper>
</div>
</body>
<script>
Vue.component('swipper', {
template: `
<div>
<div class="swiper-container">
<slot></slot>
<div class="swiper-pagination"></div>
</div>
</div>
`,
mounted() {
// 每次更新都会执行该代码,会耗费资源
let mySwiper = new Swiper('.swiper-container', {
direction: 'horizontal', // 垂直切换选项
loop: true, // 循环模式选项
// 如果需要分页器
pagination: {
el: '.swiper-pagination',
},
})
}
})
let vm = new Vue({
el: '#box',
data: {
dataList1: [],
dataList2: []
},
mounted() {
setTimeout(() => {
this.dataList1 = ['11111', '22222', '33333']
this.dataList2 = ['66666', '77777', '88888']
}, 3000)
},
})
</script>
</html>
七:自定义指令
1.基本使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>自定义指令 基本使用</title>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
</head>
<body>
<div id="box">
<div v-mystyle>我是1个DIV</div>
</div>
</body>
<script>
// 自定义指令,使用的时候 v-自定义指令名
Vue.directive('mystyle', {
inserted(ev) { // 在标签上使用这个指令,就会触发 inserted
console.log('我执行了')
}
})
let vm = new Vue({
el: '#box'
})
</script>
</html>
[](https://gitee.com/xuexianqi/img/raw/master/img/23 zdyzhiling.gif)
2.让所有使用自定义指令的标签背景都变红色
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>自定义指令 基本使用</title>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
</head>
<body>
<div id="box">
<div v-mystyle>我是1个DIV</div>
<br>
<div v-mystyle>我也是1个DIV</div>
</div>
</body>
<script>
// 自定义指令,使用的时候 v-自定义指令名
Vue.directive('mystyle', {
inserted(ev) { // 在标签上使用这个指令,就会触发 inserted
ev.style.background='red'
}
})
let vm = new Vue({
el: '#box'
})
</script>
</html>
3.用户指定自定义指令的背景色,修改变量,背景变化
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>自定义指令</title>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
</head>
<body>
<div id="box">
<!-- <div v-mystyle>我是1个DIV</div>-->
<div v-mystyle>我是1个DIV</div>
<div v-mystyle="'red'">我是1个DIV</div>
<div v-mystyle="'green'">我是1个DIV</div>
<div v-mystyle="'blue'">我是1个DIV</div>
<div v-mystyle="myColor">我是1个DIV</div>
</div>
</body>
<script>
Vue.directive('mystyle', {
inserted(ev, color) { // 这里的ev就是DOM对象
console.log(ev)
console.log(color)
ev.style.backgrond = color.value
},
updated(el, color) {
el.style.background = color.value
}
})
let vm = new Vue({
el: '#box',
data: {
myColor: 'purple'
}
})
</script>
</html>
八:过滤器
json数据:film.json
{
"coming": [
{
"id": 1240838,
"haspromotionTag": false,
"img": "http://p1.meituan.net/w.h/movie/38dd31a0e1b18e1b00aeb2170c5a65b13885486.jpg",
"version": "",
"nm": "除暴",
"preShow": false,
"sc": 8.6,
"globalReleased": true,
"wish": 76513,
"star": "王千源,吴彦祖,春夏",
"rt": "2020-11-20",
"showInfo": "今天50家影院放映79场",
"showst": 3,
"wishst": 0,
"comingTitle": "11月20日 周五"
},
{
"id": 1228788,
"haspromotionTag": false,
"img": "http://p0.meituan.net/w.h/movie/b16c1c0d5ac9e743c6ffbbf7eba900522725807.jpg",
"version": "",
"nm": "一秒钟",
"preShow": false,
"sc": 8.6,
"globalReleased": true,
"wish": 54493,
"star": "张译,刘浩存,范伟",
"rt": "2020-11-27",
"showInfo": "今天11家影院放映12场",
"showst": 3,
"wishst": 0,
"comingTitle": "11月27日 周五"
},
{
"id": 1358968,
"haspromotionTag": false,
"img": "http://p0.meituan.net/w.h/movie/d33858dbfc207da3b36c0dc7fff7a8bb2028677.jpg",
"version": "",
"nm": "汪汪队立大功之超能救援",
"preShow": false,
"sc": 8.3,
"globalReleased": true,
"wish": 24833,
"star": "杨鸥,韩娇娇,李敏妍",
"rt": "2020-11-13",
"showInfo": "今天5家影院放映7场",
"showst": 3,
"wishst": 0,
"comingTitle": "11月13日 周五"
},
{
"id": 345809,
"haspromotionTag": false,
"img": "http://p1.meituan.net/w.h/moviemachine/7c4ba9633635503044a8f8fb6426aa8d416264.jpg",
"version": "v2d imax",
"nm": "隐形人",
"preShow": false,
"sc": 8.4,
"globalReleased": true,
"wish": 9894,
"star": "伊丽莎白·莫斯,奥利弗·杰森-科恩,阿尔迪斯·霍吉",
"rt": "2020-12-04",
"showInfo": "今天21家影院放映30场",
"showst": 3,
"wishst": 0,
"comingTitle": "12月4日 周五"
},
{
"id": 1330790,
"haspromotionTag": false,
"img": "http://p0.meituan.net/w.h/movie/88e54f3e670789ba1f08e48a5f1170c1188102.jpg",
"version": "",
"nm": "明天你是否依然爱我",
"preShow": false,
"sc": 0,
"globalReleased": false,
"wish": 217699,
"star": "杨颖,李鸿其,黄柏钧",
"rt": "2020-12-24",
"showInfo": "2020-12-24 下周四上映",
"showst": 4,
"wishst": 0,
"comingTitle": "12月24日 周四"
},
{
"id": 1277751,
"haspromotionTag": false,
"img": "http://p0.meituan.net/w.h/movie/303c2e671cc4df875c151d688ecbd8962085989.jpg",
"version": "v2d imax",
"nm": "赤狐书生",
"preShow": false,
"sc": 7.7,
"globalReleased": true,
"wish": 177525,
"star": "陈立农,李现,哈妮克孜",
"rt": "2020-12-04",
"showInfo": "今天26家影院放映43场",
"showst": 3,
"wishst": 0,
"comingTitle": "12月4日 周五"
},
{
"id": 1225578,
"haspromotionTag": false,
"img": "http://p0.meituan.net/w.h/moviemachine/cf7d6942f2aa9189cce20519b490b6b1879487.jpg",
"version": "",
"nm": "野性的呼唤",
"preShow": false,
"sc": 9.2,
"globalReleased": true,
"wish": 14703,
"star": "哈里森·福特,丹·史蒂文斯,凯伦·吉兰",
"rt": "2020-11-13",
"showInfo": "今天暂无场次",
"showst": 3,
"wishst": 0,
"comingTitle": "11月13日 周五"
},
{
"id": 1302281,
"haspromotionTag": false,
"img": "http://p0.meituan.net/w.h/moviemachine/1d2b4985d0187b437d41a73994ba2e191607376.jpg",
"version": "",
"nm": "奇妙王国之魔法奇缘",
"preShow": true,
"sc": 0,
"globalReleased": false,
"wish": 20309,
"star": "卢瑶,张洋,陈新玥",
"rt": "2020-12-26",
"showInfo": "2020-12-26 下周六上映",
"showst": 4,
"wishst": 0,
"comingTitle": "12月26日 周六"
},
{
"id": 1301902,
"haspromotionTag": false,
"img": "http://p0.meituan.net/w.h/movie/f686425a1ad1f502254abef593d508bf428685.jpg",
"version": "",
"nm": "沉默东京",
"preShow": false,
"sc": 5.8,
"globalReleased": true,
"wish": 52,
"star": "佐藤浩市,石田百合子,西岛秀俊",
"rt": "2020-12-04",
"showInfo": "今天暂无场次",
"showst": 3,
"wishst": 0,
"comingTitle": ""
},
{
"id": 1286015,
"haspromotionTag": false,
"img": "http://p0.meituan.net/w.h/moviemachine/a0c6d6e130abe399e4cba58be2b1f871840268.jpg",
"version": "",
"nm": "宝可梦:超梦的逆袭 进化",
"preShow": false,
"sc": 8.2,
"globalReleased": true,
"wish": 53255,
"star": "松本梨香,大谷育江,市村正亲",
"rt": "2020-12-04",
"showInfo": "今天10家影院放映10场",
"showst": 3,
"wishst": 0,
"comingTitle": "12月4日 周五"
}
]
}
前端:index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>过滤器</title>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.0/axios.min.js"></script>
</head>
<body>
<div id="box">
<ul>
<li v-for="item in dataList">
<h2>{{item.nm}}</h2>
<p>主演:{{item.star}}</p>
<img :src="item.img | repUrl" alt="">
</li>
</ul>
</div>
</body>
<script>
// 过滤器
Vue.filter('repUrl', function (url) {
return url.replace('w.h','128.180')
})
let vm = new Vue({
el: '#box',
data: {
dataList: ''
},
mounted() {
axios.get("http://127.0.0.1:5000/").then(res => {
console.log(res.data.coming)
this.dataList = res.data.coming
}).catch(err => {
console.log(err);
})
}
})
</script>
</html>
后端:main.py
import json
from flask import Flask, jsonify
app = Flask(__name__)
@app.route('/')
def index():
print('请求来了')
with open('film.json', mode='rt', encoding='utf-8') as f:
dic = json.load(f)
res = jsonify(dic)
res.headers['Access-Control-Allow-Origin'] = '*'
return res
if __name__ == '__main__':
app.run()
标签:el,Vue,template,组件,new,data From: https://www.cnblogs.com/chen-ao666/p/17131569.html