props和attrs

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>
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值