Vue入门[3]指令与传值

126 阅读2分钟

6b8c14f8gy1gpns8px4y1j21ow0sytlk.jpg

一 指令

1.数据劫持

<body>
    <button id ="btn">修改msg</button>
</body>
</html>
<script>
    let obj ={};
    let aaa = "你好世界"

    Object.defineProperty(obj,"msg",{
        get(){
            //返回msg 的数据
            return aaa;
        },
        set(newVal){
            aaa = newVal;
        }
    })
    console.log(obj.msg);

    // 点击按钮修改msg的值
    btn.onclick = function(){
        obj.msg = " hello world " ; //一旦修改msg就会触发set方法,并且获取到一个新的值
        console.log(obj.msg);
    }
</script>

111.gif

2.属性配置

<script>
    let obj = {};

    Object.defineProperty(obj, "msg", {
        value: '你好世界',   //给某个key添加值
        writable: true,  //设置某个key的值可以被修改 (默认值为false,不能修改)
        configurable:true,  //设置某个key可否被删除 (默认值为false,不能删除)
        enumerable:true,   //设置当前对象能否枚举所有属性 (默认值为false,不能遍历)
    })
    console.log(obj.msg);  //你好世界

    // obj.msg = "hello world"
    // console.log(obj.msg);   //hello world
   
    // 删除一个属性
    // delete obj.msg;
    // console.log(obj.msg);  //undefined

    // 枚举(罗列)一个对象的属性
    console.log(Object.keys(obj));  //['msg']
</script>

3.自定义指令

// 注册一个全局自定义指令 v-focus
Vue.directive('demo', {
	inserted: function (el, binding, vnode) {
		console.log(el, binding, vnode);
	}
})
// 组件中注册局部指令
new Vue({
	el: '#app',
	data: {},
	directives: {
		demo: {
			inserted: function (el, binding, vnode) {
				cosnole.log(el, binding, vnode);
			}
		}
	}
})
// 在模板中使用自定义指令
<div v-demo>
    
</div>

二 Vue 组件化开发

1.全局组件化

<body>
    <div id="app">
        <my-list></my-list>
        <my-list />
    </div>
</body>
</html>
<!-- 抽离模板 方便操作修改 -->
<template id="list">
    <ul><li><span>你好世界</span><a href="http://baidu.com">百度</a></li></ul>
</template>
<script src="./vue.js"></script>
<script>
    // 全局组件 [template : 模板 component:组件]
    Vue.component("my-list", {
        template: "#list"
    })
    new Vue({
        el: "#app",
        data: {}
    })
</script>

注意: 组件中data必须是函数

    //多次调用一个数据,就需要维护,所以需要套上一个作用域 防止被外部数据污染,ES5 里只有函数才有作用域
    Vue.component("my-list", {
        template: "#list",
        data(){  // 所以组件中data必须是函数
            return {msg:'你好 世界'}
        }
    })

2.局部组件化

// 局部组件
components: {
  "my-list": {
     template: "#list",
     data() {  //组件中data必须是函数
         return {msg: '你好 世界'}
    },
     methods: {
         btnclick() {console.log(yes)}
    }
  }
}

3.父子之间的通讯

3.1 父传子

html

<div id="app">
        <my-list :con="content" :myhref="link"></my-list>
        <my-list />
    </div>

模板

<template id="list">
    <ul>
        <li>
            <span>{{msg}}</span>
            <a :href="myhref">{{con}}</a>
            <button @click="btnclick">按钮</button>
        </li>
    </ul>
</template>

script

new Vue({
        el: "#app",
        data: {
            content: "跳转到百度",
            link: "http://baidu.com"
        },
        // 局部组件
        components: {
            "my-list": {
                template: "#list",
                //props 以数组的形式接受,是简写 的形式 
                // props: ["con", "myhref"],
                props:{
                    con:{
                        type:String,
                        default:"跳转到新浪"
                    },
                    myhref:{
                        type:String,
                        default:"http://sina.com.cn"
                    }
                },
                data() {  //组件中data必须是函数
                    return {
                        msg: '你好 世界'
                    }
                },
                methods: {
                    btnclick() {
                        console.log(yes);
                    }
                }
            }
        }
    })

3.2 子传父

html

 <div id="app">
        <my-list :con="content" :myhref="link" v-on:changecontent="changeContent" @changelink = "changeLink"></my-list>
    </div>

模板

<!-- 抽离模板 方便操作修改 -->
<template id="list">
    <ul>
        <li>
            <span>{{msg}}</span>
            <a :href="myhref">{{con}}</a>
            <button @click="btnclick">按钮</button>
        </li>
    </ul>
</template>

script

new Vue({
        el: "#app",
        data: {
            content: "跳转到百度",
            link: "http://baidu.com"
        },
        methods:{
            changeContent(val){
                this.content = val
            },
            changeLink(val){
                this.link = val
            }
        },
        // 局部组件
        components: {
            "my-list": {
                template: "#list",
                props: ["con", "myhref"],
                data() { return {msg: '你好 憨憨'}},
                methods: {
                    btnclick() {
                      // vue中对象数据的维护要求非常严格,原始数据在那个组件中,就必须在哪一个组件里修改
                      // 子组件不能直接修改props,因为vue是单向数据流
                      // 通知父级修改content和link - emit发射
                      // this.$emit(事件名称, 传递的参数)
                      this.$emit('changecontent', "跳转到新浪");
                      this.$emit('changelink', "http://sina.com.cn")
                    }
                }
            }
        }
    })

三 插槽(slot)

1.匿名插槽

html
<div id="app">
    <my-nav>
        <input type="text">
    </my-nav>
</div>

<template id="mynav">
    <div class="nav">
        <span>&lt;</span>
        <section>
            <slot></slot>
        </section>
        <span>...</span>
    </div>
</template>

<script src="./vue.js"></script>
<script>
new Vue({
    el: "#app",
    data: {
    
    },
    components:{
        MyNav:{
            template:"#mynav",
        }
    }
})
</script>

Snipaste_2021-10-12_18-22-19.jpg

2.具名插槽

html

<div id="app">
        <my-nav :slotname="slotname">
            <input type="text" slot="ipt">
            <h3 slot="title">标题</h3>
            <div slot="list">
                <a href="">百度</a>
                <a href="">新浪</a>
                <a href="">淘宝</a>
            </div>
        </my-nav>
    </div>
<template id="mynav">
    <div class="nav">
        <span>&lt;</span>
        <section>
            <!-- <slot name='title'></slot> -->
            <slot :name='slotname'></slot>
            <!-- <slot name='ipt'></slot> -->
        </section>
        <span>...</span>
    </div>
</template>
<script src="./vue.js"></script>
<script>
    let vm=new Vue({
        el: "#app",
        data: {
            slotname:"ipt",
        },
        components: {
            MyNav: {
                template: "#mynav",
                props:["slotname"],
            }
        }
    })
</script>

Snipaste_2021-10-12_18-22-19.jpg

3.作用域插槽

html

<div id="app">
        <my-nav>
            <input type="text" slot="ipt">
            <h3 slot="title" slot-scope="scope">{{scope.msg}}</h3>
            <div slot="list">
                <a href="">百度</a>
                <a href="">新浪</a>
                <a href="">淘宝</a>
            </div>
        </my-nav>
    </div>
<template id="mynav">
    <div class="nav">
        <span>&lt;</span>
        <section>
            <slot :msg="msg" name="title"></slot>
        </section>
        <span>...</span>
    </div>
</template>
<script src="./vue.js"></script>
<script>
    let vm=new Vue({
        el: "#app",
        components: {
            MyNav: {
                template: "#mynav",
                // 子组件有数据,想要把这个数据共享给插槽
                data(){
                    return {
                        msg:"新的标题"
                    }
                }
            }
        }
    })
</script>

Snipaste_2021-10-12_18-26-45.jpg

4.作用域插槽的多种写法

<my-nav v-slot:title="scope">
            <!-- <h3 slot="title" slot-scope="scope">{{scope.msg}}</h3> -->

            <!-- <template slot="title" slot-scope="scope">
                <h3>{{scope.msg}}</h3>
            </template> -->

            <!-- <template v-slot:title="scope">
                <h3>{{scope.msg}}</h3>
            </template> -->

            <h3>{{scope.msg}}</h3>
        </my-nav>