Vue学习笔记

计算属性computed与方法methods对比

computed内部具有缓存,当页面重复执行时只会执行一次;除非依赖的数据发生变动,否则不会重新计算

methods中的函数调用不具有缓存,使用多少次,执行多少次;依赖的数据发生变动,重新计算

通过methods中定义方法,供@click调用时,参数问题

1、当方法不需要参数时,可省略();若需传递一个参数,但未传递,则会将原生事件event传递进去

2、当方法需要同时传递参数和event时间时,可通过$event传参

<div id="app">
    <button @click="handler">click me!!</button>
    <button @click="handler('cxf',$event)">click me!!</button>
</div>
<script src="../js/vue.js"></script>
<script>
    const app = new Vue({
        el: '#app',
        data: {
            message: '你好啊'
        },
        methods:{
            handler:function (event) {
                console.log(event);
            },
            handler:function (abc,event) {
                console.log(abc);
                console.log(event);
            },
        }
    })	
</script>

第一个Vue基础案例 — 购物车案例

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<div id="app">
    <div v-if="books.length">
        <table border="1">
            <thead>
            <tr>
                <th></th>
                <th>书籍名称</th>
                <th>出版日期</th>
                <th>价格</th>
                <th>购买数量</th>
                <th>操作</th>
            </tr>
            </thead>
            <tbody>
            <tr v-for="(item,index) in books">
                <td>{{item.id}}</td>
                <td>{{item.name}}</td>
                <td>{{item.date}}</td>
                <td>{{item.price | getPrice}}</td>
                <td>
                    <button @click="decrement(index)" v-bind:disabled="item.count <= 1">-</button>
                    {{item.count}}
                    <button @click="increment(index)">+</button>
                </td>
                <td>
                    <button @click="remove(index)">移除</button>
                </td>
            </tr>
            </tbody>
        </table>
        <h2>总价格:{{getFinalPrice | getPrice}}</h2>
    </div>
    <h2 v-else>购物车为空</h2>
</div>

<script src="../js/vue.js"></script>
<script src="main.js"></script>
</body>
</html>

main.js

const app = new Vue({
    el: '#app',
    data: {
        books: [
            {
                id: 1,
                name: '《算法导论》',
                date: '2016-8-8',
                price: 85.00,
                count: 1
            },
            {
                id: 2,
                name: '《UNIX编程艺术》',
                date: '2016-8-8',
                price: 59.00,
                count: 1
            },
            {
                id: 3,
                name: '《编程珠玑》',
                date: '2016-8-8',
                price: 39.00,
                count: 1
            },
            {
                id: 4,
                name: '《代码大全》',
                date: '2016-8-8',
                price: 128.00,
                count: 1
            },
        ]
    },
    methods: {
        decrement(index) {
            this.books[index].count--;
        },
        increment(index) {
            this.books[index].count++;
        },
        remove(index) {
            this.books.splice(index, 1);
        },
    },
    computed: {
        getFinalPrice() {
            let finalPrice = 0;
            for (let i = 0; i < this.books.length; i++) {
                finalPrice += this.books[i].price * this.books[i].count;
            }
            return finalPrice;
        }
    },
    filters: {
        getPrice(price) {
            return "¥" + price.toFixed(2);
        }
    }
})

v-model “值绑定” 含义:通过v-bind从网络或data中绑定数据

<div id="app">
    <label v-for="item in originHobbies" :for="item">
        <input type="checkbox" :value="item" :id="item" v-model="hobbies">{{item}}
    </label>
    <h2>你选择的水果有:{{hobbies}}</h2>
</div>

<script src="../js/vue.js"></script>
<script>
    const app = new Vue({
        el: '#app',
        data: {
            hobbies: [],
            originHobbies: ['篮球', '足球', '乒乓球', '高尔夫球']
        }
    })
</script>

组件使用(非语法糖)

<body>
<div id="app">
    //3.使用组件
    <my-con></my-con>
    <my-con></my-con>
</div>

<script src="../js/vue.js"></script>
<script>
    //1.创建组件构造器
    const myComponent = Vue.extend({
        template: `
        <div>
            <h2>组件标题</h2>
            <p>组件内容1</p>
            <p>组件内容2</p>
        </div>
        `
    });
    //2.注册组件,定义组件标签名称
    Vue.component('my-con', myComponent);
    const app = new Vue({
        el: '#app'
    })
</script>
</body>

全局组件 and 局部组件

全局组件:使用 Vue.component()注册,可在任意Vue实例使用

局部组件:在Vue实例中使用components:{}注册,只能在该实例中使用

父子组件

<body>
<div id="app">
    <cp2></cp2>
    <mycp1></mycp1>
</div>

<script src="../js/vue.js"></script>
<script>
    //创建组件构造器(子组件)
    const myComponent1 = Vue.extend({
        template: `
        <div>
            <h2>组件标题1</h2>
            <p>组件内容1</p>
        </div>
        `
    });

    //创建组件构造器(父组件)
    const myComponent2 = Vue.extend({
        template: `
        <div>
            <h2>组件标题2</h2>
            <p>组件内容2</p>
            <cp1></cp1>
        </div>
        `,
        components: {
            cp1: myComponent1
        }
    });
    const app = new Vue({
        el: '#app',
        components: {
            cp2: myComponent2,
   			//子组件只能在父组件作用域中使用,若想全局使用子组件,需在Vue实例中注册
            mycp1: myComponent1
        }
    })
</script>
</body>

组件模板分离的两种写法

<body>
<div id="app">
    <cp1></cp1>
</div>
//1.script标签
<!--<script type="text/x-template" id="mytp">-->
<!--<div>-->
    <!--<h2>我是标题</h2>-->
    <!--<p>我是内容</p>-->
<!--</div>-->
<!--</script>-->
//2.template标签
<template id="mytp">
    <div>
        <h2>我是标题</h2>
        <p>我是内容</p>
    </div>
</template>
<script src="../js/vue.js"></script>
<script>
    //注册为全局组件
    Vue.component('cp1',{
        template:'#mytp'
    });
    const app = new Vue({
        el: '#app',
    })
</script>
</body>

Vue组件data必须是函数

<body>
<div id="app">
    <!--多个组件实例-->
    <cp1></cp1>
    <cp1></cp1>
    <cp1></cp1>
</div>
<template id="mytp">
    <div>
        <h2>当前计数:{{count}}</h2>
        <button @click="increment">+</button>
        <button @click="decrement">-</button>
    </div>
</template>
<script src="../js/vue.js"></script>
<script>
    //注册为全局组件
    Vue.component('cp1',{
        template:'#mytp',
        data:function () {
            //返回一个唯一的对象,不要和其他组件共用一个对象进行返回
            //每个vue组件的data都因为函数有了自己的作用域,互不干扰
            return{
                count:0
            }
        },
        methods:{
            increment(){
                this.count++
            },
            decrement(){
                this.count++
            }
        }
    });
    const app = new Vue({
        el: '#app',
    })
</script>
</body>

父子组件的通信

组件化开发时,页面请求完数据后,并非由页面的大组件进行展示,而是需要下面的子组件进行展示;这个时候,不可能让子组件再次发送请求,而是让大组件将数据传递给子组件

父传子:通过props

子传父:通过自定义事件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Vava6B7t-1587276236226)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1580289637171.png)]

父传子:

<body>
<!--使用-->
<div id="app">
    <cp v-bind:cmessage="message"></cp>
</div>
<!--分离模板-->
<template id="mypt">
    <div>
        <h2>{{cmessage}}</h2>
    </div>
</template>
<script src="../js/vue.js"></script>
<script>
    //子
    const cp = {
        template: '#mypt',
        props: ['cmessage'],
        data: function () {
            return {}
        },
        methods: {}
    };
    //父
    const app = new Vue({
        el: '#app',
        data: {
            message: '你好啊'
        },
        //注册子(组件)
        components: {
            cp//增强写法
        }
    })
</script>
</body>

子传父:

<body>
<!--使用-->
<div id="app">
    <!--绑定父级方法,参数默认携带-->
    <cp @item-click="cpclick"></cp>
</div>
<!--分离模板-->
<template id="mypt">
    <div>
        <button v-for="item in categories" @click="btnclick(item)">{{item.name}}</button>
    </div>
</template>
<script src="../js/vue.js"></script>
<script>
    //子
    const cp = {
        template: '#mypt',
        props: {},
        data: function () {
            return {
                categories: [
                    {id: 1, name: '热门推荐'},
                    {id: 2, name: '手机数码'},
                    {id: 3, name: '家电办公'},
                    {id: 4, name: '台式手提'}
                ]
            }
        },
        methods: {
            btnclick(item) {
                //发射自定义事件给到父级,可带参数
                this.$emit('item-click', item)
            }
        }
    };
    //父
    const app = new Vue({
        el: '#app',
        data: {},
        //注册子(组件)
        components: {
            cp: cp
        },
        methods: {
            cpclick(item) {
                console.log("cpclick");
                console.log(item);
            }
        }
    })
</script>
</body>

父级访问子级($children and $refs)

子级访问父级($parent)

<body>
<div id="app">
    <cpn ref="aaa"></cpn>
    <button @click="btnClick">按钮</button>
</div>
<template id="cpn">
    <div>
        <h2>我是子组件</h2>
    </div>
</template>
<script src="../js/vue.js"></script>
<script>
    const app = new Vue({
        el: '#app',
        data: {
            message: '你好啊'
        },
        methods: {
            btnClick() {
                //1.$children
                // this.$children[0].showMessage();
                // console.log(this.$children[0].name)

                //2.$refs 为对象属性,默认为空对象,需在组件实例添加ref标识
                this.$refs.aaa.showMessage();
                console.log(this.$refs.aaa.name)
            }
        },
        components: {
            cpn: {
                template: '#cpn',
                data() {
                    return {
                        name: 'it is name',
                    }
                },
                methods: {
                    showMessage() {
                        console.log("it is showMessage");
                    }
                }
            }
        }
    })
</script>
</body>

编译作用域

父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的。

<body>
<div id="app">
    <!--父级作用域-->
    <cpn v-show="isShow"></cpn>
</div>
<template id="tp">
    <div>
        <h2>我是组件标题1,我是显示还是不显示?</h2>
        <!--子作用域-->
        <h2 v-show="isShow">我是组件标题2,我是显示还是不显示?</h2>
    </div>
</template>
<script src="../js/vue.js"></script>
<script>
    const app = new Vue({
        el: '#app',
        data: {
            isShow: true
        },
        components: {
            cpn: {
                template: '#tp',
                data() {
                    return {
                        isShow: false
                    }
                }
            }
        }
    })
</script>
</body>

具体使用组件内的那个插槽?— 具名插槽

<body>
<div id="app">
    <cpn><span slot="left">new left</span></cpn>
    <cpn><span slot="center">new center</span></cpn>
    <cpn><span slot="right">new right</span></cpn>
</div>
<template id="tp">
    <div>
        <slot name="left"><span>left</span></slot>
        <slot name="center"><span>center</span></slot>
        <slot name="right"><span>right</span></slot>
    </div>
</template>
<script src="../js/vue.js"></script>
<script>
    const app = new Vue({
        el: '#app',
        data: {
            message: '你好啊'
        },
        components: {
            cpn: {
                template: '#tp',
            }
        }
    })
</script>
</body>

作用域插槽

父组件不满意子组件展示数据的方式,需要替换插槽的标签,但仍需要子组件的数据内容

<body>
<div id="app">
    <!--使用原本插槽展示-->
    <cpn></cpn>

    <cpn>
        <!--获取子组件中Languages-->
        <template slot-scope="slot">
            <!--自定义展示-->

            <!--<span v-for="item in slot.data">{{item}} - </span>-->
            <span>{{slot.data.join(' - ')}}</span>
        </template>
    </cpn>
</div>
<template id="tp">
    <div>
        <slot :data="Languages">
            <ul>
                <li v-for="item in Languages">{{item}}</li>
            </ul>
        </slot>
    </div>
</template>
<script src="../js/vue.js"></script>
<script>
    const app = new Vue({
        el: '#app',
        data: {
            message: '你好啊'
        },
        components: {
            cpn: {
                template: '#tp',
                data() {
                    return {
                        Languages: ['JS', 'Java', 'Go', 'PHP']
                    }
                }
            }
        }
    })
</script>
</body>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值