vue进阶 组件函数中this的区别
1 计算属性
计算属性将方法不写在methods中写在computed中即可
复杂逻辑,模板难以维护
(1) 基础例子
(2) 计算缓存 VS methods-计算属性是基于它们的依赖进行缓存的。-计算属性只有在它的相关依赖发生改变时才会重新求值
(3) 计算属性 VS watch
- v-model3
通过计算属性实现名字首字母大写
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="app">
<!--大段的代码写在这里不好,使用计算属性-->
{{mytext.substring(0, 1).toUpperCase() + mytext.substring(1)}} <!---substring用于截取字符串-->
<p>计算属性:{{getname}}</p>
<!--普通方法要加括号-->
<p>普通方法:{{getNameMethod()}}</p>
<!--区别是在同一个页面中使用多次计算属性,不会多次执行-->
<input type="text" v-model="name">---->{{name.substring(0,1).toLocaleUpperCase() + name.substring(1)}}
<input type="text" v-model="name1">---->{{name1.slice(0,1).toLocaleUpperCase() + name1.slice(1)}}
</div>
</body>
<script>
var vm = new Vue({
el: '#app',
data: {
mytext: 'lqz',
name: '',
name1:''
},
computed: {
getname() {//依赖的状态改变了,会重新计算
console.log('计算属性')
return this.mytext.substring(0, 1).toUpperCase() + this.mytext.substring(1)
}// 返回什么方法就显示什么
},
methods: {
getNameMethod() {
console.log('普通方法')
return this.mytext.substring(0, 1).toUpperCase() + this.mytext.substring(1)
}
}
})
</script>
</html>
通过计算属性重写过滤案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="box">
<p><input type="text" v-model="mytext" @input="handleChange"></p>
<ul>
<li v-for="data in newlist">{{data}}</li> <!--使用计算属性的值直接使用不加括号-->
</ul>
</div>
</body>
<script>
var vm = new Vue({
el: '#box',
data: {
mytext: '',
datalist: ['aaa', 'abc', 'abcde', 'abcdef', 'bbb', 'bac'],
},
computed: {
newlist() {
var newlist = this.datalist.filter(item => {
return item.indexOf(this.mytext) > -1
})
return newlist //计算属性必须返回一个值
},
},
})
</script>
</html>

2监听属性

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="app">
<div><span><button @click="type='少妇'">少妇</button>|<button @click="type='学生'">学生</button>|<button @click="type='空姐'">空姐</button></span>
</div>
<br>
{{type}}
</div>
</body>
<script>
var vm = new Vue({
el: '#app',
data: {
type: '暂无数据'
},
watch: {
type(val) {
'点击了:', console.log(val)
}
}//监听type的变化点击什么变成type的值通过内部的形参传入
})
</script>
</html>
3组件化开发基础
扩展 HTML 元素,封装可重用的代码,目的是复用
-例如:有一个轮播,可以在很多页面中使用,一个轮播有js,css,html
-组件把js,css,html放到一起,有逻辑,有样式,有html
组件拥有vue 生命周期八个方法 同样拥有组件的数据方法默认组件之间的数据不互通
组件注册方式
- 全局组件,任意位置使用
Vue.component - 局部组件只能在定义组件的内部使用
定义全局组件,绑定事件,编写样式
全局组件的定义使用直接在vue 对象中当标签插入即可 可重复使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="app">
我是第一种<navbar></navbar>
我是第二种<navbar1></navbar1>
</div>
</body>
<script>
// 第一种写法
Vue.component('navbar', {
template: `
<div>
<button @click="handleClick">点我修改局部组件数据</button>
{{ mytext }}
<button style="background: red">主页</button>
<br>
点上面的按钮可以修改数据:------>{{ xxxx }}
</div>
`,
data() {
return {mytext: '我是组件中的数据', xxxx: '你好啊'} // 全局组件数据写成函数需要返回对象 返回什么就显示什么
},
methods: {
handleClick() {
this.xxxx = '修改了局部组件的数据'
}
}
})
// 第二种写法 将对象写写好然后通过Vue.component初始化组件
var obj = {
template: `
<div>
<button @click="handleClick">点我修改局部组件数据</button>
{{ mytext }}
<button style="background: red">主页</button>
<br>
点上面的按钮可以修改数据:------>{{ xxxx }}
</div>
`,
data() {
return {mytext: '我是组件中的数据', xxxx: '你好啊'} // 全局组件数据写成函数需要返回对象 返回什么就显示什么
},
methods: {
handleClick() {
this.xxxx = '修改了局部组件的数据'
}
}
}
Vue.component('navbar1', obj)
var vm = new Vue({
el: '#app',
data: {},
})
</script>
</html>

局部组件定义
使用的时候在哪里定义的就在哪里使用
var obj2 = {
template: `
<div>
{{ name }}
</div>`,
data() {
return {name: '局部组件2'}
}
}
var vm = new Vue({
el: '#app',
data: {},
components: {
'lqz': {
template: `
<div>
{{ name }}
</div>`,
data() {
return {name: '局部组件'}
}
},
'tyx': obj2
} // 局部组件与全局类似 只能在vm组件内使用
})

组件之间通信
- 父传子
![image]()
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/vue.js"></script>
</head>
<body>
<!--1。子组件定义自定义属性 冒号数据绑定 传入子组件中-->
<!--2。子组件用props接收 即可使用在子组件中写父组件自定义的属性-->
<!--3。props写成对象形式可以验证传入的数据是什么如果不是想要的直接报错-->
<div id="app">
<xxx :myname="name"></xxx>
</div>
</body>
<script>
var vm = new Vue({
el: '#app',
data: {name: '西施'},
components: {
'xxx': {
template: `
<div>
<h1>我是组件</h1>
父组件传入的---> {{ myname }}
</div>`,
props: ['myname']
// props:{myname:String}
},
}
})
</script>
</html>

- 子组件数据传父
![image]()
![image]()
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/vue.js"></script>
</head>
<body>
<!--1。在父组件中定义自定义事件@myclick="handleclick"事件执行接收传的参数传几个就写几个参数-->
<!--2。子组件按钮绑定点击事件@click="sendmessage"-->
<!--3。一点击子组件按钮执行this.$emit('myclick',this.name)查找父组件中自定义的事件执行第二个参数是子组件传给父组件的数据-->
<div id="app">
<xxx @myclick="handleclick"></xxx>
父组件数据值:{{name}}
</div>
</body>
<script>
var vm = new Vue({
el: '#app',
data: {name:'我是父组件的数据'},
methods: {
handleclick(name) {
this.name = name
}
},
components: {
'xxx': {
template: `
<div>
<h1>子组件传父组件</h1>
<input type="text" v-model="name">----->{{ name }}
<br>
<button @click="sendmessage">点击传数据给父组件</button>
</div>`,
data() {
return {name: ''}
},
methods: {sendmessage(){
this.$emit('myclick',this.name)
}}
},
}
})
</script>
</html>
- ref属性
ref放在标签上,拿到的是原生节点
ref放在组件上,拿到的是组件对象,
通过这种方式实现子传父(this.$refs.mychild.text)
通过这种方式实现父传子(调用子组件方法传参数)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="box">
<!-- 通过ref,获取input的值-->
<input type="text" ref="mytext">
<button @click="handleClick">点我</button>
<child ref="mychild"></child> <!--子组件-->
</div>
</body>
<script>
Vue.component('child', {
template: `
<div>child</div>`,
data() {
return {
text: '子组件数据'
}
},
methods: {
add(args) {
console.log('子组件的add方法')
console.log(args)
}
}
})
var vm = new Vue({
el: '#box',
data: {},
methods: {
handleClick() {
console.log(this)
//this.$refs.mytext 获取到input控件,取出value值
console.log('原生标签',this.$refs.mytext.value) //标签上ref属性取到原生标签
console.log(this.$refs.mychild.text)//通过子组件ref属性取出子组件文本数据
// this.$refs.mychild.add()
this.$refs.mychild.add('传递参数')
}
}
})
</script>
</html>

- 动态组件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/vue.js"></script>
</head>
<body>
<!--1。动态组件使用component标签绑定is属性 绑定点击事件点哪个显示哪个内容的数据-->
<!--2。 缓存输入的搜索内容使用keep-alive标签包一下可以保持之前填写的内容存在-->
<div id="app">
<div>
<span @click="name='index'" class="btn">首页</span>
<span @click="name='goods'" class="btn">商品</span>
<span @click="name='order'" class="btn">订单</span>
</div>
<div>
<keep-alive>
<component :is="name"></component>
</keep-alive>
</div>
</div>
</body>
<script>
// 第一种写法
Vue.component('goods', {
template: `
<div>
<h1>商品</h1>
<input type="text" placeholder="请输入搜索的内容">
<button>搜素</button>
</div>
`,
data() {
return {mytext: '我是组件中的数据', xxxx: '你好啊'} // 全局组件数据写成函数需要返回对象 返回什么就显示什么
},
methods: {
handleClick() {
this.xxxx = '修改了局部组件的数据'
}
}
})
Vue.component('index', {
template: `
<div>
<h1>主页</h1>
</div>
`,
})
// 第二种写法 将对象写写好然后通过Vue.component初始化组件
var obj = {
template: `
<div>
<h1>订单</h1>
</div>
`,
data() {
return {mytext: '我是组件中的数据', xxxx: '你好啊'} // 全局组件数据写成函数需要返回对象 返回什么就显示什么
},
methods: {
handleClick() {
this.xxxx = '修改了局部组件的数据'
}
}
}
Vue.component('order', obj)
var vm = new Vue({
el: '#app',
data: {name: 'index'},
})
</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>
<!--在组件中定义slot标签留槽位将标签或者数据写在组件标签中就会显示在组件留的槽位中-->
<!--可以给槽位起名name=xxx 使用的时候写上slot=xxx即可-->
<div id="box">
<index>
<span>无名插槽只有一个的情况</span><!--将标签内的数据写在slot标签中-->
</index>
<hr>
<index>
<span slot="top">有名插槽</span>
</index>
</div>
</body>
<script>
var obj = {
template: `
<div>
<slot name="top"></slot>
<h1>插槽</h1>
<hr>
<slot></slot>
</div>
`,
data() {
return {}
}
}
Vue.component(
'index', obj
)
var vm = new Vue({
el: '#box',
data: {},
})
</script>
</html>
组件函数中this的区别

箭头函数
setTimeout(() => {
console.log(this); //this绑定的是b函数中的this对象
}, 100);




浙公网安备 33010602011771号