1.组件其他
根组件 和 组件 一些问题
-new Vew()---->管理div----》根组件
-自己再定义的全局,局部是组件
-组件有自己的html,css,js ---》数据,事件,。。。。。
-在组件中,this 代指当前组件
-父子组件的data是无法共享的
-data是1个函数,需要有返回值(return)
2.组件通信之父传子
我们本意是想定义一个组件,里面声明一个name,在全局声明一个age,用组件在页面显示name和age,但是却只能拿到数据name,无法拿到age,因为父子之间数据不共享。我们需要通过自定义自定义属性方式实现数据的子传父:
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="app">
<h1>div标签</h1>
<child></child>
</div>
<script>
var child = {
template: `
<div>
<h2>姓名:{{ name }}</h2>
<h2>年龄:{{ age }}</h2>
</div>
`,
data() {
return {
name: 'max'
}
} // 子标签的数据
}
var vm = new Vue({
el:'#app',
data:{
age:18
},
components:{
child
}
})
</script>
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="app">
<h1>div标签</h1>
<child :myage="age"></child> <!--在child标签中拿到age,并且赋值给变量myage(这个变量不能用驼峰体)-->
</div>
<script>
var child = {
template: `
<div>
<h2>姓名:{{ name }}</h2>
<h2>年龄:{{ myage }}</h2> <!--用声明过的变量名来拿到div标签中的数据-->
</div>
`,
data() {
return {
name: 'max'
}
}, // 子标签的数据
props:['myage'] // 在组件中用关键字props注册刚才声明的变量名,
}
var vm = new Vue({
el:'#app',
data:{
age:18
},
components:{
child
}
})
</script>
"""
<child age="age"></child> 在页面上会显示age:age,传的是字符串
<child age="19"></child> 不加:相当于传了固定的值,是一个字符串,和上面由于
<child :age="19"></child> 加了age显示在页面上的是19,但是加:是一个数字,并且加:可以写简单的表达式
"""
如果我们想控制父传子的数据类型,可以将props写成一个字典,键是接收到的数据,值是数据类型。如果接收到的数据类型和控制的不一样,也可以正常在前端页面显示,但是会有提示:
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="app">
<h1>div标签</h1>
<child :myage="age"></child> <
</div>
<script>
var child = {
template: `
<div>
<h2>姓名:{{ name }}</h2>
<h2>年龄:{{ myage }}</h2>
</div>
`,
data() {
return {
name: 'max'
}
}, // 子标签的数据
props: {myage: Number} // 接收类型为数值类型
}
var vm = new Vue({
el:'#app',
data:{
age:'18' // 父标签传递给子组件的是一个字符串
},
components:{
child // child是一个局部组件
}
})
</script>
3.组件通信之子传父
父组件也无法直接拿到字组件中的内容,需要通过自定义事件来拿到。数据子传父需要借助$emit,该方法可以触发子组件中的方法
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="app">
<h2>父组件中的myText:{{myText}}</h2> <!--1.在父组件中定义好要接收的myText-->
<hr>
<child @myevent="handEvent"></child> <!--5.编辑触发事件,该事件将子组件的值赋值给父组件。触发该事件的方法写在子组件中,该事件绑定的函数写在父组件methods中-->
</div>
</body>
<script>
var child = {
template:`
<div>
<h2>子组件中的myText:<input type="text" v-model="myText"></h2>
<button @click="handSend">点我将子组件数据传递给父组件</button> <!--2.定义好子组件,在子组件button中加入点击事件,该事件绑定的函数不需要传形参-->
</div>
`,
data(){
return {
myText: ''
}},
methods:{
handSend(){
this.$emit('myevent',this.myText) // 3.点击事件绑定$emit,$emit绑定会触发的事件,第二个参数是要传递给父组件的参数
}
}
}
var vm = new Vue({
el:'#app',
data:{
myText:''
},
methods:{
handEvent(myText){
this.myText=myText // 6.将子组件中的myText值赋值给父组件中的myText,在通过插值语法传递到前段页面
}
},
components:{
child // 4.app标签内加入child 子组件
}
})
</script>
4.ref属性
1.ref属性对的作用:拿到原生的html标签。
定义两个标签,都绑上ref属性。打印$refs属性,发现是一个对象,键是ref的值,值是标签名称。
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="app">
我是input标签<input type="text" ref="myinput">
<div ref="mydiv">我是div标签</div>
<button @click="handClick">点击</button>
</div>
</body>
<script>
var vm = new Vue({
el:'#app',
data:{
},
methods:{
handClick(){
console.log(this.$refs)
}
}
})
</script>
2.属性放在组件上,拿到的是组件对象,可以使用组件对象的属性和方法。两个标签和一个child组件都绑定了ref值:
<body>
<div id="app">
我是input标签<input type="text" ref="myinput" v-model="name">
<div ref="mydiv">我是div标签</div>
<button @click="handClick">点击</button>
<child ref="mychild"></child>
</div>
</body>
<script>
var child = {
template:`
<div>
<h2>姓名:{{name}}</h2>
<h2>年龄:{{age}}</h2>
</div>
`,
data(){
return {
name:'max',
age:18
}
},
methods: {
handClick() {
alert(this.name)
}
}
}
var vm = new Vue({
el:'#app',
data:{
name:''
},
methods:{
handClick(){
console.log(this.$refs)
// console.log(this.$refs.mychild) 拿到的就是组件对象
}
},
components:{
child
}
})
</script>
在父标签可以通过ref属性拿到子标签中的值,此后就不需要关注是子传父还是父传子,而且还可以
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="app">
输入您的姓名<input type="text" ref="myinput" v-model="name">
<div ref="mydiv">我是div标签</div>
<button @click="handClick">点击</button>
<child ref="mychild"></child>
</div>
</body>
<script>
var child = {
template: `
<div>
<h2>姓名:{{ name }}</h2>
<h2>年龄:{{ age }}</h2>
</div>
`,
data() {
return {
name: 'max',
age: 18
}
}
}
var vm = new Vue({
el: '#app',
data: {
name: ''
},
methods: {
handClick() {
this.name = this.$refs.mychild.name
} // this.$refs.mychild是组件对象,拿到子组件对象之后就可以点到子组件的属性和方法
},
components: {
child
}
})
</script>
利用ref属性还可以拿到子标签中的方法:
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="app">
<button @click="handClick">父标签按钮</button>
<child ref="mychild"></child>
</div>
</div>
</body>
<script>
var child = {
template: `
<div>
<button @click="handClick">子标签按钮</button>
</div>
`,
data() {
return {
name: 'max',
age: 18
}
},
methods: {
handClick(){
alert('我是子标签中的handClick方法')
}
}
}
var vm = new Vue({
el: '#app',
data: {
name: ''
},
methods: {
handClick() {
this.$refs.mychild.handClick() // 将父标签的点击事件绑定为触发子标签handClick()方法
}
},
components: {
child
}
})
</script>
5.动态组件
需求:现需要搭建一个页面,有三个选择框:首页、商品订单、结算页面,每点击一个小标题跳到该页面(用字来模拟):
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="app">
<span @click="handClick('home')">首页</span>| <span @click="handClick('order')">商品订单</span>| <span
@click="handClick('buy')">结算页面</span>
<home v-if="type=='home'"></home>
<order v-else-if="type=='order'"></order>
<buy v-else></buy> <!--v-if判断来决定显示哪个组件-->
</div>
</body>
<script>
var home = {
template: `
<h1>
<div>首页</div>
</h1>
`
}
var order = {
template: `
<h1>
<div>订单页面</div>
</h1>
`
}
var buy = {
template: `
<h1>
<div>结算页面</div>
</h1>
`
}
var vm = new Vue({
el: '#app',
data: {
type: 'home'
},
methods: {
handClick(type) {
this.type = type
console.log(this.type)
}
},
components: {
home,
order,
buy
}
})
</script>
用动态组件来写可以减少代码,动态组件每种方式和每个组件匹配得到原理是:component标签参数'who'需要和组件名称保持一致,也就是点击事件的handClick参数需要和组件名称保持一致:
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="app">
<span @click="handClick('home')">首页</span>| <span @click="handClick('order')">商品订单</span>| <span
@click="handClick('buy')">结算页面</span>
<component :is="who"></component>
</div>
</body>
<script>
var home = {
template: `
<h1>
<div>首页</div>
</h1>
`
}
var order = {
template: `
<h1>
<div>订单页面</div>
</h1>
`
}
var buy = {
template: `
<h1>
<div>结算页面</div>
</h1>
`
}
var vm = new Vue({
el: '#app',
data: {
who: 'home'
},
methods: {
handClick(type) {
this.who = type
console.log(this.who)
}
},
components: {
home,
order,
buy
}
})
</script>
6. keep-alive保持组件不销毁
在每个组件上设置一个input输入框,但是当我们跳转到另一个组件再回去时,input输入框内的内容会被清空,在component组件上套上keep-alive组件,就可以保持input输入框不会被清除掉。
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="app">
<span @click="handClick('home')">首页</span>| <span @click="handClick('order')">商品订单</span>| <span
@click="handClick('buy')">结算页面</span>
<keep-alive>
<component :is="who"></component>
</keep-alive>
</div>
</body>
<script>
var home = {
template: `
<h1>
<div>首页</div>
搜索商品:<input type="text">
</h1>
`
}
var order = {
template: `
<h1>
<div>订单页面</div>
搜索商品:<input type="text">
</h1>
`
}
var buy = {
template: `
<div>
<h1>
<div>结算页面</div>
</h1>
搜索商品:<input type="text">
</div>
`
}
var vm = new Vue({
el: '#app',
data: {
who: 'home'
},
methods: {
handClick(type) {
this.who = type
}
},
components: {
home,
order,
buy
}
})
</script>
"""
报错提示:outside root element will be ignored.
这个代码表示我们在父组件或者子组件中都要用一个大的标签(div或者其他任意都可以)包起来,否则会报错:
"""
7.插槽
7.1 匿名插槽
1.匿名插槽就是将标签<slot></slot>插在组件中后期可能扩展内容的地方,在body标签中直接在组件名标签中插入内容即可:
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="app">
<home>
<h2>
通过插槽插入的数据
</h2>
</home>
</div>
</body>
<script>
var home = {
template:`
<div>
<h1>home页面</h1>
<slot></slot>
<h1>home结束了</h1>
</div>
`
}
var vm = new Vue({
el:'#app',
data:{},
components:{
home
}
})
</script>
插入前后对比:
7.2 匿名插槽
给每个插槽加入name属性,插入数据时直接在标签中插入slot="slot名"来指定插入位置:
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="app">
<home>
<div slot="s2">我是s2插槽得到内容</div>
<div slot="s1">我是s1插槽得到内容</div>
</home>
</div>
</body>
<script>
var home = {
template:`
<div>
<h1>home页面</h1>
<slot name="s1"></slot>
<h1>home结束了</h1>
<slot name="s2"></slot>
</div>
`
}
var vm = new Vue({
el:'#app',
data:{},
components:{
home
}
})
</script>
8.计算属性
8.1计算属性基本使用
需求:建立一个将输入内容首字母大写输入框,再建立一个数字输入框,我们在输入字符的时候会一直执行getUpper()函数,因为会随时监测字符的编号。但是当我们不输入字符,只输入数字时,发现console.log('getUpper()执行了')也在一直执行,说明getUpper()只要页面上任何一个地方刷新,都会重新执行:
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="app">
字符输入框<input type="text" v-model="myText">{{getUpper()}}
数字输入框<input type="number" v-model="myNum">
</div>
</body>
<script>
var vm = new Vue({
el:'#app',
data:{
myText:'',
myNum:''
},
methods:{
getUpper(){
console.log('getUpper()执行了')
return this.myText.slice(0,1).toUpperCase()+this.myText.slice(1)
}
}
})
</script>
为了效率起见,我们需要与之无关的函数不再执行,也就是字符框不输入内容时,getUpper()函数不再执行。因此我们再建立一个函数,返回值和getUpper()一样,但是这个函数写在computed内,调用该函数不需要加括号,当成属性用,并且要有返回值。可以看出与之无关的页面在刷新时,newText()函数不再执行:
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="app">
字符输入框<input type="text" v-model="myText">{{newText}}
数字输入框<input type="number" v-model="myNum">
</div>
</body>
<script>
var vm = new Vue({
el:'#app',
data:{
myText:'',
myNum:''
},
methods:{
getUpper(){
console.log('getUpper()执行了')
return this.myText.slice(0,1).toUpperCase()+this.myText.slice(1)
}
},
computed:{
newText(){
console.log('getUpper()执行了')
return this.myText.slice(0,1).toUpperCase()+this.myText.slice(1)
}
}
})
</script>
8.2 改良版过滤案例
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="d1">
<p>请输入您要查询的单词:<input type="text" v-model="text"></p>
<ul>
<li v-for="item in newdataList">{{item}}</li>
</ul>
</div>
</body>
<script>
var vm = new Vue({
el: '#d1',
data:{
text:'',
dataList:['accustomed','suddenly','altogether','arrange','knowledge'],
},
computed:{
newdataList(){
return this.dataList.filter(
item=>item.indexOf(this.text)>=0
) // 将newdataList包装成一个属性,可以对其进行for循环,与之无关的页面局部刷新也不会使其刷新
}
}
})
</script>
9.监听属性
当我们检测data中的某个值是否变化时,我们可以用一个watch()方法,该方法和methods平级,里面的函数名必须和data中的数据保持一致,当该数据发生变化时,就会触发watch()中的方法:
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="app">
<span @click="handClick('python')">python</span>| <span @click="handClick('linux')">linux</span>
<component :is="who"></component>
</div>
<script>
var python = {
template: `
<h1>
<div>python</div>
</h1>
`
}
var linux = {
template: `
<h1>
<div>linux</div>
</h1>
`
}
var vm = new Vue({
el: '#app',
data: {
who: 0
},
methods: {
handClick(type) {
this.who = type
}
},
components:{
python,
linux
},
watch:{
who(){
console.log('who变了')
}
}
})
</script>
</body>
标签:vue,name,标签,var,template,组件,data,属性
From: https://www.cnblogs.com/ERROR404Notfound/p/17131660.html