day83 前端框架--Vue基础&Vue组件

一,Vue基础补充

  1.获取DOM对象

    给标签加ref属性,ref="xxx"

    this.$refs.xxx

<body>
<div id="app">
    <div ref="my_box"></div>
    <button @click="my_click">点击显示文本</button>
</div>
<script>
    const app = new Vue({
        el: "#app",
        methods:{
            my_click:function () {
                // 给div标签加入文本
                let ele = this.$refs.my_box; // this=>app
                console.log(ele);
                ele.innerText = "alex"
            }
        }
    })
</script>
</body>

  

  2.Vue对象:计算属性

<body>
<div id="app">
    <table>
        <thead>
            <tr>
                <th>科目</th>
                <th>成绩</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>Python</td>
                <td><input type="text" v-model.number="python"></td>
            </tr>
            <tr>
                <td>Django</td>
                <td><input type="text" v-model.number="django"></td>
            </tr>
            <tr>
                <td>Mysql</td>
                <td><input type="text" v-model.number="mysql"></td>
            </tr>
            <tr>
                <td>总分</td>
                <!--<td>{{python+django+mysql}}</td>-->
                <td>{{total}}</td>
            </tr>
            <tr>
                <td>平均分</td>
                <!--<td>{{(python+django+mysql)/3}}</td>-->
                <td>{{average}}</td>
            </tr>

        </tbody>
    </table>
</div>
<script>
    const app = new Vue({
        el: "#app",
        data: {  // 静态属性
            python: "",
            django: "",
            mysql: "",
            // sum: this.python + this.django + this.mysql, // =>sum:nul,不能实时监听数据的变化
        },
        methods: {

        },
        computed: {  // 计算属性:将所有数据放入缓存,实时监听数据,当数据改变的时候才会重新渲染,否则一直存在缓存
            total: function () {
                return this.python + this.django + this.mysql
            },
            average: function () {
                return this.total()/3
            }
        }
    })
</script>
</body>

  3.Vue对象:数据的监听

watch 监听数据

-- 字符串
    -- 监听到改变新的值和旧的值不同

-- 数组
    -- 只能监听到长度的变化 新旧值相同的
    -- 改变数组的时候监听不到,必须用$set(array,index,value)
        新旧值相同

-- 对象
    -- 只能监听到value的改变 必须深度监听
    -- 增加对象的key 必须用$set(obj,key,value)
    -- 新旧值相同
<body>
<div id="app">
    {{name}}
    <br>
    {{hobby}}
    <br>
    {{obj}}
    <button @click="my_click">点我改变数据</button>
</div>
<script>
    const app = new Vue({
        el: "#app",
        data: {
            name: "alex",
            hobby: ["抽烟","烫头"],
            obj: {
                girl: "nezha",
                age: 36,
            }
        },
        methods: {
            my_click: function () {
                //修改数据
                // this.name = "alexdsb";  // 不可变数据类型,重新开辟内存,可以读两块不同的内存
                // this.hobby.push("腹黑"); // 可变数据类型,会在原内存修改

                // this.hobby[0] = "吸猫";  
                // console.log(this.hobby);//数据被修改,监听不到数据的变化,深度监听也不行

                app.$set(this.hobby,0,"吸猫"); //修改可变数据类型的专用方法,主动通知浏览器有数据修改,并重新渲染页面

                // this.obj.age = 18; //数据被修改,可以监听到数据的变化
                // this.obj["sex"] = "女";  //添加数据,监听不到数据的变化,深度监听也不行
                app.$set(this.obj,"sex","") //修改可变数据类型的专用方法
            }
        },
        watch:{  // 监听器
            name: {
                handler: function (val,oldval) {  // hander 回调函数
                    console.log(val);
                    console.log(oldval)
                    // 可以做某些操作
                }
            },
            hobby: { //只能监听数组的长度变化,所有即使值修改了,也不会重新渲染页面
                handler: function (val,oldval) {
                    // 改变数组的长度的时候新旧值相同
                    console.log(val);
                    console.log(oldval);
                    console.log(this.hobby)
                },
                // deep: true  //深度监听
            },
            obj: { //在深度监听的情况,可以监听到value的变化,其他情况监听不了
                handler: function (val,oldval) {
                    console.log(val);
                    console.log(oldval);
                    console.log(this.obj)
                },
                // deep: true
            }
        }
    })
</script>
</body>

二,Vue的组件

  1.组件的全局注册

Vue.component("组件名称",{
    // 也就是不能同时有两个div
    template:`只识别一个块级作用域`,
    data() {
        return {
            name: xxx
        }
    },
    methods:{},
})
-- 任何Vue实例里用<组件名称></组件名称>
<body>
<div id="app">
    <my_header></my_header>
</div>
<hr>
<div id="app2">
    <my_header></my_header>
</div>
<script>
    //全局注册的组件 可以被在其他根实例的作用域中使用
    Vue.component("my_header",{ // 每一个组件都是vue可复用的实例,但是没有一些根实例的属性
        template:`<div><h1>{{title}}</h1></div>`,
        // template:`<div>{{title}}</div><div>{{title}}</div>`, //只能识别第一个div

        data(){ // 对象的单体模式   ==> data function (){}
            return {
                title:"这是头部",
            }
        },
        methods: {

        }
    });
    const app = new Vue({  // 根实例
        el: "#app",
        data: {},
    });
    const app2 = new Vue({
        el: "#app2",

    })
</script>
</body>

  2.组件的局部注册

-- let com_config = {......}
-- const app = new Vue({
    el: "#app",
    components: {
        组件名称: com_fig
    }
})
-- <div><组件名称></组件名称></div>
<body>
<div id="app">
    <div><my_com></my_com></div>

</div>
<div id="app2">
    <my_com></my_com>
</div>

<script>
    let my_com_config = {
        template: `<div><h1>这是局部组件</h1></div>`,
    };
    const app = new Vue({
        el: "#app",
        data: {},
        components: {
            my_com: my_com_config
        },
    });
    const app2 = new Vue({
        el: "#app2",
        data: {},
        components: {
            my_com: my_com_config
        },
    })
</script>
</body>

  3.子组件的注册

-- 在父组件里 components: {
    子组件的名称: 子组件的配置信息
}
-- 在父组件的template里展示子组件
    <child></child>
<body>
<div id="app">
    <my_com></my_com>
</div>

<script>
    let child_config = {
        template: `<div><h2>这是一个子组件</h2></div>`
    };
    let my_com_config = {
        template: `<div>
                    <child></child>
                    <h1>这是一个组件</h1>
                    <child></child>
                    </div>`,//子组件只识别一个作用域块
        components: {
            child:child_config
        }
    };
    const app = new Vue({
        el: "#app",
        data: {},
        components: {
            my_com: my_com_config
        }
    });

</script>
</body>

  4.父子组件的通信

    先给子组件绑定属性

    在子组件通过props:["属性名称"]

<body>
<div id="app">
    <my_com></my_com>
</div>
<script>
    let child_config = {
        template: `<div>
                    <h2>这是一个子组件</h2>
                    <p>父亲跟你们说~~{{father_say}}}</p>
                    </div>`,
        props: ["father_say",]  //父子通信桥梁
    };
    let my_com_config = {
        template: `<div>
                    <h1>这是一个组件</h1>
                    <child :father_say="f_say"></child>  //子组件值识别一个作用域块
                    </div>`,    // f_say不能直接传字符串
        components: {
            child:child_config
        },
        data(){  //对象的单体模式
            return {
                f_say: "滚~~~"
            }
        }
    };
    const app = new Vue({
        el: "#app",
        data: {},
        components: {
            my_com: my_com_config
        }
    })
</script>
</body>

  

  5.子父组件的通信

    子组件先提交数据:this.$emit("事件名称",data)

    父组件,给子组件绑定事件:自己处理这个事件

<body>
<div id="app">
    <my_com></my_com>
</div>
<script>
    let child_config = {
        template: `<div>
                    <h2>这是一个子组件</h2>
                    <button @click="my_click">点击向父亲说话</button>
                    </div>`,
        methods: {
            my_click() {
                //向父亲说话
                //子组件提交事件
                this.$emit("son_say","父皇,儿臣有事启奏");
// 组件就是一个Vue实例,并且this就是指本身这个组件,但是this同时包含Vue根实例的属性
} }, }; let my_com_config = {//子组件值识别一个作用域块 template: `<div> <h1>这是一个组件</h1> <child @son_say="my_son_say"></child> <p>儿子给我说~~{{s_say}}</p> </div>`, components: { child:child_config }, methods: { my_son_say:function (data) { //这里需要接收参数,标签中可以不接受参数 this.s_say = data; //修改数据 } }, data(){ //对象的单体模式 return { s_say: "" } } }; const app = new Vue({ el: "#app", data: {}, components: { my_com: my_com_config, } }) </script> </body>

  6.非父子组件通信

    定义一个中间调度器:let Event = new Vue();

    其中一个组件向中间调度器提交事件:Event.$emit("事件名称",data)

    另一个组件要监听中间调度器的时间:Event.$on("事件的名称",function(data) { })

<body>
<div id="app">
    <com1></com1>
    <com2></com2>
</div>
<script>
    let Event = new Vue(); // 充当中间调度器

    let com1_config = {
        template: `<div>
                    <h1>这是com1</h1>
                    <button @click="my_click">点击给com2打电话</button>
                    </div>`,
        methods:{
            my_click(){
                //给com2打电话,今晚等我
                // 向Event提交事件
                Event.$emit("call","今晚等我~~")
            }
        }
    };
     let com2_config = {
         template: `<div>
                    <h1>这是com2</h1>
                    <p>com1跟我说~{{com1_say}}</p>
                    </div>`,
         data(){
           return{
               com1_say: ""
           }
         },
         mounted() {
             // 组件加载完成后,执行的方法
             // 监听Event的事件
             let that = this;
             Event.$on("call",function (data) {
                 console.log(data);
                 that.com1_say = data
                 // 当前的this => Event
             })
         }

    };
    const app = new Vue({
        el: "#app",
        data: {},
        components: {
            com1: com1_config,
            com2: com2_config,
        }
    })
</script>
</body>

  7.混合

    复用共用的代码块:mixins:[base]

<body>
<div id="app">

<com1></com1>
<com2></com2>
</div>
<script>
    let base ={
        data() {
            return {
                is_show: false
            }
        },
        methods:{
            show_text(){
                this.is_show = true
            },
            hide_text(){
                this.is_show = false
            }
        }
    };

    let com1 = {
        template:`<div>
                <button @click="show_text">点击显示文本</button>
                <button @click="hide_text">点击隐藏文本</button>
                <div v-show="is_show">点我</div>
                </div>`,
        mixins:[base],
        data() {  //可以重写base的data,以设置is_show的值
            return {
                is_show: true
            }
        },
    };

    let com2 = {
        template:`<div>
                 <button @mouseenter="show_text" @mouseleave="hide_text">提示框</button>
                <div v-show="is_show">点我</div>
                </div>`,
        mixins:[base],
    };
    const app = new Vue({
        el: "#app",
        components:{
            com1:com1,
            com2:com2
        },
    })
</script>
</body>

  8.插槽 

    实现组件内容的分发:

      slot:

        直接用slot标签

      命名的slot:

        先给slot加name属性

        给标签元素添加slot属性 = name属性值   

<body>
<div id="app">
    <com>
        <!--<solt></solt>-->
        <h3 slot="title">python</h3>
        <p slot="brief">从入门到放弃</p>
    </com>
    <com>
        <h3 slot="title">Mysql</h3>
        <p slot="brief">从删库到跑路</p>
    </com>
</div>

<template id="my_com">
    <div>
        <h1>这是一个组件</h1>
        <hr>
        <!--<slot></slot>-->
        <slot name="title"></slot>
        <slot name="brief"></slot>
    </div>
</template>

<script>
    let com = {
        template:"#my_com"
    };
    const app = new Vue({
        el: "#app",
        data: {},
        components:{
            com:com,
        }
    })
</script>
</body>

        

    

原文地址:https://www.cnblogs.com/lianyeah/p/10065385.html