attrs
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="./lib/vue.min.js"></script>
<style>
</style>
</head>
<body>
<div id="app">
<son id="box" title="我是title" checked='ture' class="red" style="color: red;"></son>
</div>
<script>
Vue.component('son', {
template: `<div><h1>我是一个son组件</h1><p>我是一个P</P></div>`,
mounted() {
//this.attr这个实例属性,能够取到用在组件上的一些个属性和特性,知识style和class是个例外
console.log(this.$attrs) //{id: "box", title: "我是个title", checked: "true"}
}
})
var vm = new Vue({
el: '#app',
data: {
msg: '我是根'
}
})
</script>
</body>
</html>
props
书写规则
- 驼峰法
- 短横线法
- ps不管你定义的时候使用的是驼峰法还是短横线法,在父亲给儿子传递的时候,都推荐短横线法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="./lib/vue.min.js"></script>
</head>
<body>
<div id="app">
<son id="box" title="我是个title" checked="true" class="red" style="color: red;"></son>
</div>
<script>
Vue.component('son', {
data() {
return {
msg: 'hello'
}
},
//下面这个就规定了。如果使用son这个组件的时候,在son这个标签上面有传title这个属性,那么这个title属性,就会是这个son组件需要的一个props
//这个时候$attrs取不到title了
//props才能取到title
props: ['title', 'checked'],
template: `<div>
<h1>我是个 son 组件</h1>
<p>我是个 屁</p>
</div>`,
mounted() {
//this.$props这个实例属性,能够取到组件定义的props数据
//1现在数组中定义props那么props定义的东西可以直接当做data的数据来使用
console.log(this.$attrs) //{id: "box"}
console.log(this.$props) //checked: "true" title: "我是个title"
console.log(this.msg) //hello
console.log(this.title) //我是个title
console.log(this.$props.title) //我是个title
}
})
var vm = new Vue({
el: '#app',
data: {
msg: '我是根'
}
})
</script>
</body>
</html>
要对props 做类型校验,下面这种数组的写法就不能用了。得要用 对象的写法
props: ['nickName', 'sex', 'age'],
对象写法
nickName: [String, Number], // 一个或多个类型是,使用 数组
sex: String,
age: {
type: Number
},
lvHeight: {
type: Number,
required: true, //必须项
}
//validator是自定义的验证props的函数
//一个参数,这个参数value就是使用props的时候传入的数据
validator: function (value) {
var arr = ['text', 'password', 'email']
//如果通过就返回真,不通过就返回 false控制台会报错
if (arr.indexOf(value) === -1) {
return false
} else {
return true
}
}
props案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="./lib/vue.min.js"></script>
</head>
<body>
<div id="app">
<ye-header title="首页"></ye-header>
<ye-header title="列表页"></ye-header>
<ye-header title="关于叶"></ye-header>
</div>
<script>
//props干的事就是父像子传参
Vue.component('ye-header', {
props: ['title'], //可以当做data来使用
template: `<header>{{ title }}</header>`
})
var vm = new Vue({
el: '#app',
data: {
}
})
</script>
</body>
</html>
单向数据流: vue中 规定了 组件与组件中的 数据的 流转方向
- 只能从上流倒下
- 不能从下流到上
组件不能够自己改变 Props的数据,违反了 Vue 中的单项数据流的定义
子组件与父组件通信-----$emit
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
</head>
<body>
<div id="app">
{{name}}
<son @change-name='fn3'></son>
</div>
<script>
Vue.component('son', {
template: ` <div>
<h1>我是 个 儿子</h1>
<button @click="fn1">名字太丑,我直接给你改了</button>
<button @click="fn2">爸爸,您的名字不好听,您自己看着改一改</button>
</div>
`,
methods: {
fn1() {
console.log(this.$parent.name)
this.$parent.name = '张起灵'
//代码没为题但是Vie不推荐这么使用
},
fn2() {
// 触发父亲的一个事件
// $emit() 触发一个事件
// 1. 先定义一个自定义的事件
// <son @changeName="xxx"></son>
// 2. 在父亲上写好 xxx 这个方法,在方法里面代码父亲自己的东西
// 3. 在儿子那里,来使用 $emit() 触发 changeName 这个事件
// changeMe 这个事件的 xxx 方法就会被执行
//注意:这里的名字要保持一致change-name,比较特殊
this.$emit('change-name', {
name: '叶俊宽',
age: 18
})
}
}
})
var vm = new Vue({
el: '#app',
data: {
name: '张大山'
},
methods: {
fn3(data) {
console.log(data)
console.log('儿子,触发emit,这个方法就行了')
this.name = data.name
}
}
})
</script>
</body>
</html>
解决关系嵌套过深的方法
- 通过一个空的实例对象的方法
- vuex的方法
下面是创建空实例的方法解决兄弟间的嵌套关系
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
</head>
<body>
<div id="app">
<!--
当组件嵌套过深的(爷与孙, 曾祖与曾孙)
再或者 兄弟组件这种关系
有难的解决方法,
1. 通过一个 空的实例对象的方法
2. vuex 的方法
-->
{{ name }}
<son></son>
<son2></son2>
</div>
<script>
//1 new Vue 空实例对象
var bus = new Vue()
//2.bus 定义某个事件
//3.调用bus的事件
Vue.component('son', {
template: `
<div>
<h1>我是 个 儿子</h1>
<button @click="fn1">我要去给弟弟改个名</button>
</div>
`,
methods: {
fn1() {
bus.$emit('son2Gai', '叶俊宽')
}
}
})
Vue.component('son2', {
data() {
return {
name: '张三'
}
},
template: `<div>
<h1>我是个 二儿子 {{ name }}</h1>
</div>`,
mounted() {
// 2. 通过 bus 来自定义一个事件
bus.$on('son2Gai', (data) => {
this.name = data
})
}
})
var vm = new Vue({
el: '#app',
data: {
name: '张大仙'
},
methods: {
}
})
</script>
</body>
</html>
案例评论列表案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<link rel="stylesheet" href="./lib/bootstrap-3.3.7.css">
<script src="./lib/vue-2.4.0.js"></script>
</head>
<body>
<div id="app">
<cmt-box @func='loadComments'> </cmt-box>
<ul class="list-group">
<li class="list-group-item" v-for='item in list' :key='item.id'>
<span class="badge">评论人:{{item.user}}</span>
{{item.content}}
</li>
</ul>
</div>
<template id="tmp1">
<div>
<div class="form-group">
<label>评论人</label>
<input type="text" class="form-control" v-model='user'>
</div>
<div class="form-group">
<label>评论内容</label>
<textarea type="text" class="form-control" v-model='content'></textarea>
</div>
<div class="form-group">
<input type="button" value="发表评论" class="btn btn-primary" @click='postComment'>
</div>
</div>
</template>
<script>
var commentBox = {
data() {
return {
user: '',
content: ''
}
},
template: '#tmp1',
methods: {
postComment() { //发表评论的方法
var comment = {
id: Date.now(),
user: this.user,
content: this.content
}
var list = JSON.parse(localStorage.getItem('cmts') || '[]')
list.unshift(comment)
localStorage.setItem('cmts', JSON.stringify(list))
this.user = this.content = ''
this.$emit('func')
}
}
}
var vm = new Vue({
el: '#app',
data: {
list: [{
id: Date.now(),
user: '李白',
content: '天生我材必有用'
},
{
id: Date.now(),
user: '江小白',
content: '劝君更尽一杯酒'
},
{
id: Date.now(),
user: '小马',
content: '我姓马, 风吹草低见牛羊的马'
}
]
},
created() {
this.loadComments()
},
methods: {
loadComments() {
var list = JSON.parse(localStorage.getItem('cmts') || '[]')
this.list = list
}
},
components: {
'cmt-box': commentBox
}
})
</script>
</body>
</html>