昨日回顾
1 购物车案例
2 v-model之lazy,number,trim
-lazy:input框的数据绑定等失去焦点以后再变化
-number:input框中333dsda,变成333
-trim:input去前后空格
3 与后端交互
-jq的ajax
-fetche
-axios:get,put,post,delete..(带头,带数据。。。)
-跨域问题(如何处理)
4 与后端交互之fetche
5 与后端交互之axios
6 计算属性之首字母大写
-函数当作变量来使用,有缓存,在页面上使用多次,只执行一次
7 通过计算属性重写过滤案例
8 组件定义
-组件化开发:全局组件,局部组件
-组件中有html,css,js:数据是独立的
## vue的开源项目,在本地运行起来(别人开源了一个djago项目,跑在本地)
1 vue项目:安装node(python解释器)---》一路下一步--》(node:python3,npm:pip)
2 使用pycharm打开vue项目
3 terminal中输入:npm install (安装这个vue项目所有的依赖:pip3 install -r requ.txt)
4 命令行下执行:npm run serve / npm run start / npm run dev 等同于:python manage.py runserver
今日内容
1 定义局部组件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script src="js/vue.js"></script>
<title>Title</title>
</head>
<body>
<div id="box">
<child></child>
<child1></child1>
</div>
</body>
<script>
Vue.component('child1', {
template: `
<div>
<div style="background: red" @click="handleClick">我是头部</div>
<div v-if="isShow">显示消失</div>
<child></child>
</div>
`,
methods: {
handleClick() {
console.log('我被点击了')
this.isShow = !this.isShow
}
},
data() {
return {
isShow: true
}
},
})
var vm = new Vue({
el: '#box',
data: {
isShow: true,
},
methods: {
handleClick() {
console.log('根组件我被点击了')
}
},
//局部组件
components:{
child:{ //child组件名
template:`
<div @click="handleClick">{{name}}</div>
`, //组件模板
methods:{
handleClick(){
console.log('我被点了')
}
},
data(){
return{
name:'lqz'
}
},
},
}
})
</script>
</html>
2 组件编写方式与Vue实例的区别
1 自定义组件需要有一个root element,一般包裹在一个div中,跟vue实例一样
2 父子组件的data是无法共享
3 组件可以有data,methods,computed....,但是data 必须是一个函数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script src="js/vue.js"></script>
<title>Title</title>
</head>
<body>
<div id="box">
<navbar></navbar>
{{aa}}
</div>
</body>
<script>
Vue.component('navbar', {
template: `
<div>
<button @click="handleClick">返回</button>
我是NavBar{{aa}}
<button style="background: red">主页</button>
<br>
<child></child>
</div>
`,
methods: {
handleClick() {
console.log('nav nav')
},
},
components: {
child: {
template: `<button>儿子</button>`,
}
},
data() {
return {
aa: 'lqz'
}
},
})
var vm = new Vue({
el: '#box',
data: {
isShow: true,
},
methods: {
handleClick() {
console.log('根组件我被点击了')
}
},
})
</script>
</html>
3 组件通信之父传子通信
1 父子通信
2 在全局组件上自定义属性
<navbar myname="lqz" age="18"></navbar>
3 在组件中获取
props: ['myname','age'] #myname=lqz age=18
4 区分开这两种赋值方式
<navbar myname="lqz" age="18"></navbar>
<navbar :myname="'ffff'" age="19"></navbar>
<navbar :myname="name" age="19"></navbar>
3.1父传子通信
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script src="js/vue.js"></script>
<title>Title</title>
</head>
<body>
<div id="box">
<!--myname是自定义属性-->
<navbar myname="lqz" age="18"></navbar>
<navbar :myname="'ffff'" age="19"></navbar>
</div>
</body>
<script>
Vue.component('navbar', {
template: `
<div>
<button @click="handleClick">返回</button>
我是NavBar---{{age}}
<button style="background: red">{{myname}}</button>
</div>
`,
props: ['myname','age']
})
var vm = new Vue({
el: '#box',
data: {
name: 'xxx',
},
})
</script>
</html>
3.2 属性验证
1 限制父传子的变量类型
props: {
myname:String,
isshow:Boolean,
varies:'' //传递,但不验证类型
}
2 父传子时注意以下的区别
<navbar myname="lqz" :isshow="isshow"></navbar>
<navbar myname="lqz" :isshow="false"></navbar>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script src="js/vue.js"></script>
<title>Title</title>
</head>
<body>
<div id="box">
<!--myname是自定义属性-->
<!-- <navbar myname="lqz" isshow="false"></navbar>-->
<navbar myname="lqz" :isshow="isshow"></navbar>
<navbar myname="lqz" :isshow="false"></navbar>
</div>
</body>
<script>
Vue.component('navbar', {
template: `
<div>
<button>返回</button>
我是NavBar---{{isshow}}
<button style="background: red">{{myname}}</button>
</div>
`,
props: {
myname:String,
isshow:Boolean
}
})
var vm = new Vue({
el: '#box',
data: {
name: 'xxx',
isshow:true,
},
})
</script>
</html>
4 组件通信之子传父通信
1 通过事件实现:
点击一下子组件,就会触发父组件某个函数的执行
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script src="js/vue.js"></script>
<title>Title</title>
</head>
<body>
<div id="box">
<navbar @myevent="handleClick"></navbar>
</div>
</body>
<script>
Vue.component('navbar', {
template: `
<div>
<button @click="handleNav">点我,触发父组件的某个函数执行</button>
</div>
`,
data(){
return {
name:'lqz'
}
},
methods:{
handleNav(){
console.log('我是nav的函数,我执行了')
this.$emit('myevent',100,this.name,99)
}
}
})
var vm = new Vue({
el: '#box',
data: {
},
methods:{
handleClick(ev,a,b){
console.log('我是父组件的函数,我执行了')
console.log(ev)
console.log(a)
console.log(b)
}
}
})
</script>
</html>
4.2 小案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script src="js/vue.js"></script>
<title>Title</title>
</head>
<body>
<div id="box">
<child @myevent="handle"></child>
<hr>
{{name}}
</div>
</body>
<script>
Vue.component('child', {
template: `
<div>
<input type="text" v-model="mytext">
<button @click="handleClick">点我</button>
</div>
`,
data() {
return {
mytext: ''
}
},
methods: {
handleClick() {
this.$emit('myevent', this.mytext)
}
}
})
var vm = new Vue({
el: '#box',
data: {
name: ''
},
methods: {
handle(a) {
this.name = a
}
}
})
</script>
</html>
5 ref属性(也可实现组件间通信,子父,父子都可以使用)
ref放在标签上,拿到的是原生节点
ref放在组件上,拿到的是组件对象,
通过这种方式实现子传父(this.$refs.mychild.text)
通过这种方式实现父传子(调用子组件方法传参数)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script src="js/vue.js"></script>
<title>Title</title>
</head>
<body>
<div id="box">
<input type="text" ref="myref">
<child ref="mychild"></child>
<hr>
<button @click="handleButton">点我</button>
</div>
</body>
<script>
Vue.component('child', {
template: `
<div>
<input type="text" v-model="mytext">
<hr>
我是子组件的input
</div>
`,
data() {
return {
mytext: ''
}
},
methods:{
add(a){
console.log('我是子组件的add方法')
console.log(a)
return '返回了'
}
}
})
var vm = new Vue({
el: '#box',
data: {
name: 'asdf'
},
methods: {
handle(a) {
this.name = a
},
handleButton(){
console.log(this.$refs.mychild.mytext)
console.log(this.$refs.mychild.add(this.name))
}
}
})
</script>
</html>
6 事件总线bus
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script src="js/vue.js"></script>
<title>Title</title>
</head>
<body>
<div id="box">
<child1></child1>
<hr>
<child2></child2>
</div>
</body>
<script>
//定义一个事件总线
var bus=new Vue()
//组件1
Vue.component('child1', {
template: `
<div>
<input type="text" v-model="text">
<button @click="handleClick">点我传递数据到另一个组件</button>
</div>
`,
data() {
return {
text: ''
}
},
methods: {
handleClick() {
console.log(this.text)
bus.$emit('suibian',this.text) //通过事件总线发送
}
}
})
//组件2
Vue.component('child2', {
template: `
<div>
收到的消息是:{{recv_text}}
</div>
`,
data(){
return {
recv_text:''
}
},
mounted(){//组件挂载(生命周期钩子函数中的一个),开始监听事件总线上的随便
bus.$on('suibian',(item)=>{
console.log('收到了',item)
this.recv_text=item
})
},
})
var vm = new Vue({
el: '#box',
data: {},
})
</script>
</html>
7 动态组件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script src="js/vue.js"></script>
<title>Title</title>
</head>
<body>
<div id="box">
<ul>
<li @click="who='child1'">首页</li>
<li @click="who='child2'">商品</li>
<li @click="who='child3'">订单</li>
</ul>
<!--<component :is="who"></component>-->
<keep-alive>
<component :is="who"></component>
</keep-alive>
</div>
</body>
<script>
var vm = new Vue({
el: '#box',
data: {
who: 'child1'
},
components: {
child1: {
template: `
<div>我是首页
<input type="text">
</div>
`,
},
child2: {
template: `
<div>我是商品 </div>
`,
},
child3: {
template: `
<div>我是订单 </div>
`,
}
}
})
</script>
</html>
8 slot插槽
8.1 基本使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script src="js/vue.js"></script>
<title>Title</title>
</head>
<body>
<div id="box">
<child1>
<ul>
<li v-for="i in 4">{{i}}</li>
</ul>
</child1>
<hr>
<child2></child2>
<hr>
<child3></child3>
</div>
</body>
<script>
var vm = new Vue({
el: '#box',
data: {
who: 'child1'
},
components: {
child1: {
template: `
<div>
<slot></slot>
<hr>
我是首页
<input type="text">
</div>
`,
},
child2: {
template: `
<div>我是商品 </div>
`,
},
child3: {
template: `
<div>我是订单 </div>
`,
}
}
})
</script>
</html>
8.2 插槽案例(一个组件通过插槽控制另一个组件的显示隐藏)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script src="js/vue.js"></script>
<title>Title</title>
</head>
<body>
<div id="box">
<child1>
<button @click="isShow=!isShow">点我隐藏child2</button>
</child1>
<hr>
<child2 v-if="isShow"></child2>
</div>
</body>
<script>
var vm = new Vue({
el: '#box',
data: {
isShow: true,
},
components: {
child1: {
template: `
<div>
<slot></slot>
</div>
`,
},
child2: {
template: `
<div>
<ul>
<li v-for="i in 4">{{i}}</li>
</ul>
</div>
`,
},
}
})
</script>
</html>
8.3 具名插槽(指定标签放到组件的某个插槽中)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script src="js/vue.js"></script>
<title>Title</title>
</head>
<body>
<div id="box">
<child1>
<button @click="isShow=!isShow" slot="button1">点我隐藏child2</button>
<div slot="div1">我是div</div>
</child1>
<hr>
<child2 v-if="isShow"></child2>
</div>
</body>
<script>
var vm = new Vue({
el: '#box',
data: {
isShow: true,
},
components: {
child1: {
template: `
<div>
<slot name="button1"></slot>
<hr>
我是华丽的分割线
<hr>
<slot name="div1"></slot>
</div>
`,
},
child2: {
template: `
<div>
<ul>
<li v-for="i in 4">{{i}}</li>
</ul>
</div>
`,
},
}
})
</script>
</html>