Vue学习笔记01——Vue开发基础

5 篇文章 2 订阅

一、Vue实例配置选项

选项说明
dataVue实例数据对象
methods定义Vue中的方法
components定义子组件
computed计算属性
filters过滤器
el唯一根标签
watch监听数据变化

1.el唯一根标签

在创建Vue实例时,el表示唯一根标签,class或id选择器可以用来将页面结构与Vue实例对象中的el绑定。

<div id="app">{{name}}</div>
<script>
	var vm=new Vue({
        el:"#app",
        data:{
            name:"Vue实例创建成功!"
        }
    })
</script>

2.data初始数据

Vue实例的数据对象为data,Vue会将data的属性转换为getter,setter,从而让data的属性都能够响应数据变化。

Vue实例创建后,可以通过**vm. d a t a ∗ ∗ 访 问 原 始 数 据 对 象 。 V u e 实 例 也 代 理 了 d a t a 对 象 上 所 有 的 属 性 , 因 此 访 问 v m . n a m e 相 当 于 访 问 v m . data**访问原始数据对象。Vue实例也代理了data对象上所有的属性,因此访问vm.name相当于访问vm. data访Vuedata访vm.name访vm.data.name。

2.1 data赋值方式一

<div id="app">
    <p>
        {{name}}
    </p>
</div>
<script>
	var vm=new Vue({
        el:'#app',
        data:{
            name:'定义初始数据'
        }
    })
    console.log(vm.$data.name);
    console.log(vm.name);
</script>

2.2 data赋值方式二

<div id="vue_data">
    <h3>{{site}}</h3>
    <h3>{{url}}</h3>
    <h3>{{student}}</h3>
</div>
<script>
    // 字典
    var data = {
        site: "菜鸟教程",
        url: "https://www.baidu.com",
        student: "Tom"
    };
    var vm = new Vue({
        el: "#vue_data",
        data: data
    });
    var h3 = document.querySelector('h3');
    h3.addEventListener('click', function () {
        data.site = '百度';
    });
    console.log(vm.site === data.site);
    console.log(vm.$data.site === data.site);
    console.log(vm.$data === data);
</script>

3.methods定义方法

methods属性用来定义方法,通过Vue实例可以访问这些方法。在定义的方法中,this指向Vue实例本身。定义在methods属性中的方法可以作为页面中的事件处理方法使用,当事件被触发后,执行相应的事件处理方法。

<div id="app">
    <button @click="showInfo">
        请单击
    </button>
    <p>
        {{msg}}
    </p>
</div>
<script>
	var vm=new Vue({
        el:'#app',
        data:{
            msg:''
        },
        mehods:{
            //定义时间处理方法showInfo
            showInfo(){
                this.msg='触发单击事件'
            }
        }
    })
</script>

4.computed计算属性

Vue提供了一种更通用的方式来观察和响应Vue实例上的数据变动,当有一些数据需要随着其他数据而变动时,就需要使用computed计算属性

在事件处理方法中,this指向的Vue实例的计算属性结果会被缓存起来,只有依赖的响应式属性变化时,才会重新计算,返回最终结果。

4.1 案例:增加数量计算总价

<div id="app">
    <p> 总价格:{{totalPrice}}</p>
    <p> 单价:{{price}}</p>
    <p> 数量:{{num}}</p>
    <div>
        <button @click="num == 0?0:num--">减少数量</button>
        <button @click="num++">增加数量</button>
    </div>
</div>
<script>
    var vm = new Vue({
        el: "#app",
        data: {
            price: 20,
            num: 0
        },
        methods: {//整个页面重新渲染的时候才会执行
            sum: function () {
                return this.price * this.num;
            }
        },
        computed: {//依赖的缓存被更改的时候就会执行,在有依赖的情况下执行效率要高一点
            //总价格计算
            totalPrice: function () {
                return this.price * this.num;
            }
        }
    });
</script>

5.watch状态监听

Vue提供了watch状态监听功能,只需监听当前Vue实例中的数据变化,就会调用数据所绑定的事件处理方法

5.1 基础使用

<div id="app">
    <input type="text" v-model="cityName">
</div>
<script>
	var vm=new Vue({
        el:'#app',
        data:{
            cityName:'shanghai'
        },
        // 使用watch监听cityName变化
        watch:{
            cityName(newName,oldName){
                // 打印新数据和旧数据
                console.log(newName,oldName);
            }
        }
    })
</script>

5.2 计算总价

<div id="app">
    <p> 总价格:{{sum}}</p>
    <p> 单价:{{price}}</p>
    数量:<input type="number" v-model="num"/>
    <div>
        <button @click="num == 0?0:num--">减少数量</button>
        <button @click="num++">增加数量</button>
    </div>
</div>
<script>
    var vm = new Vue({
        el: "#app",
        data: {
            sum: 0,
            price: 20,
            num: 0
        },
        watch: {
            num(newData, oldData) {
                if (newData < 0) {
                    this.num = 0;
                }
                this.sum = newData * this.price;
            }
        }
    });
</script>

5.3 距离转换km<=>m

<h2>距离转换</h2>
<div id="km_m">
    <input type="number" v-model="km"/>千米<br/>
    <input type="number" v-model="m"/><br/>
</div>
<div id="info"></div>
<script>
    var vm1 = new Vue({
        el: "#km_m",
        data: {
            km: 0,
            m: 0
        },
        watch: {
            km: function (newData, oldData) {
                this.m = newData * 1000;
            },
            m: function (newData, oldData) {
                this.km = newData / 1000;
            }
        }
    });
    vm1.$watch('km', function (newValue, oldValue) {
        var info = document.querySelector('#info');
        info.innerHTML = '修改前的值是' + oldValue + ',修改后的值是' + newValue;
    })
</script>

3-4-5.methods、computed、watch区别

<h2>三个属性的区别</h2>
<div id="name">
    姓:<input type="text" v-model="firstName"/>
    名:<input type="text" v-model="lastName"/>
    <h4>用methods形式打印全名{{methodFullName()}},年龄{{age}}</h4>
    <h4>用computed形式打印全名{{computedFullName}},年龄{{age}}</h4>
    <h4>用watch形式打印全名{{watchFullName}},年龄{{age}}</h4>
</div>
<script>
    var vm2 = new Vue({
        el: '#name',
        data: {
            firstName: '张',
            lastName: '三',
            age: 18,
            watchFullName: '张三'
        },
        methods: {
            methodFullName: function () {
                console.log("这是方法返回的全名");
                return this.firstName + this.lastName;
            }
        },
        computed: {
            computedFullName: function () {
                console.log("这是计算返回的全名");
                return this.firstName + this.lastName;
            }
        },
        watch: {
            firstName: function (newValue) {
                console.log('这是监听属性firstName的返回');
                this.watchFullName = newValue + this.lastName;
            },
            lastName: function (newValue) {
                console.log('这是监听属性lastName的返回');
                this.watchFullName = this.firstName + newValue;
            }
        }
    })
</script>

6.filters过滤器

数据变化除了在Vue逻辑层进行操作外,还可以通过过滤器来实现。

6.1在插值表达式中使用过滤器

通过"{{data}}“语法,可以将data中的数据插入页面中,该语法就是插值表达式,插值表达式中还可以使用过滤器来对数据进行处理,语法为”{{data | filter}}"

<div id="app">
    {{message|toUpcase|toLowcase}}
</div>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            message: "abcdefg"
        },
        filters: {
            // 参数value表示传到过滤器中的数据
            toUpcase: function (value) {
                // 将abcdefg转换为ABCDEFG
                return value ? value.toUpperCase() : '';
            },
            toLowcase: function (value) {
                // 将ABCDEFG转换为abcdefg
                return value ? value.toLowerCase() : '';
            }
        }
    })
</script>

6.2在v-bind属性绑定中使用过滤器

v-bind用于属性绑定,如"v-bind:id=”data““表示绑定id属性,值为data。在data后面可以加过滤器,语法为"data|filter”。

<div id="app">
    <div v-bind:id="dataId | formatId">
        helloworld
    </div>
</div>
<script>
	var vm=new Vue({
        el:'#app',
        data:{
            dataId:'dff1'
        },
        filters:{
            //字符串处理
            return value?vlaue.charAt(1)+value.indexOf('d'):'';
        }
    })
</script>

二、Vue数据绑定

1.绑定样式

1.1 绑定内联样式

在Vue实例中定义的初始数据data,可以通过v-bind将样式数据绑定给DOM元素

<div id="app">
    <!--绑定样式属性值-->
    <div v-bind:style="{backgroundColor:pink,width:width,height:height}">
        <div v-bind:style="myDiv"></div>
    </div>
</div>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            myDiv: {backgroundColor: 'red', width: '100px', height: '100px'},
            pink: 'pink',
            width: '100%',
            height: '200px',
        }
    });
</script>

1.2绑定样式类

样式类即以类名定义元素的样式

<div id="app">
    <div v-bind:class="{box}">
        我是box
        <div v-bind:class="{inner}">我是inner</div>
        <div v-bind:class="{inner,text}">我是inner</div>
    </div>
</div>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            box: 'box',
            inner: 'inner',
            text: 'text'
        }
    });
</script>

1.3样式数组

<!--绑定的是数组-->
<div id="myArr">
    <div v-bind:style="[baseStyle,myStyle]">今天是周四</div>
</div>
<script>
    var myvm = new Vue({
        el: '#myArr',
        data: {
            baseStyle: {
                color: 'red',
                fontSzie: '30px',
            },
            myStyle: {
                'font-weight': 'bold'
            }
        }
    })
</script>

1.4是否加载样式

<!--是否加载类样式-->
<div id="flag_css">
    <div v-bind:class="{inner,active:isActive}"></div>
</div>
<script>
    var flag_css = new Vue({
        el: "#flag_css",
        data: {
            inner: 'inner',
            isActive: true,
            active: 'active'
        }
    })
</script>

1.5样式绑定综合

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>内联样式属性</title>
    <script src="js/vue.js"></script>
    <style>
        .active {
            width: 100px;
            height: 100px;
            background-color: blue;
        }

        .mytext {
            background-color: red;
        }
    </style>
</head>
<body>
<div id="app">
    <div v-bind:class="{'active':isActive,'mytext':hasError}"></div>
    <button @click="upIsActive">isActive</button>
    <button @click="upHasError">hasError</button>
</div>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            isActive: true,
            hasError: true
        },
        methods: {
            upIsActive: function () {
                this.isActive = !this.isActive;
            },
            upHasError: function () {
                this.hasError = !this.hasError;
            }
        }
    })
</script>
<!-- 对象表示形式 -->
<div id="app1">
    <div v-bind:class="obj"></div>
    <button @click="upIsActive">isActive</button>
    <button @click="upHasError">hasError</button>
</div>
<script>
    var vm1 = new Vue({
        el: '#app1',
        data: {
            obj: {
                active: true,
                mytext: true
            }
        },
        methods: {
            upIsActive: function () {
                this.obj.active = !this.obj.active;
            },
            upHasError: function () {
                this.obj.mytext = !this.obj.mytext;
            }
        }
    })
</script>
<!-- 计算属性绑定 -->
<div id="app2">
    <div v-bind:class="comNum"></div>
    <button @click="upIsActive">isActive</button>
</div>
<script>
    var vm2 = new Vue({
        el: '#app2',
        data: {
            isActive: true,
            num: 100
        },
        methods: {
            upIsActive: function () {
                this.isActive = !this.isActive;
            }
        },
        computed: {
            comNum: function () {
                return {
                    active: this.isActive && this.num >= 100,
                    hasError: this.isActive && this.num < 100
                }
            }
        }
    })
</script>
</body>
</html>

2.内置指令

指令说明
v-model双向数据绑定,页面修改同步
v-on监听事件,可简写为“@”
v-bind单向数据绑定,页面修改不同步,可简写为“:”
v-text插入文本内容
v-html插入包含HTML的内容
v-for列表渲染
v-if条件渲染
v-show显示隐藏

2.1 v-model 双向数据绑定

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>内置指令</title>
    <script src="js/vue.js"></script>
</head>
<body>
<!-- v-model双向数据绑定 -->
<div id="app">
    <label>
        姓名
        <input type="text" v-model="name"/>
    </label>
    <label>
        年龄
        <input type="number" v-model="age"/>
    </label>
    <label>
        性别
        <input type="text" v-model="sex"/>
    </label>
    <hr/>
    <p>姓名:{{name}}<br/>年龄:{{age}}<br/>性别:{{sex}}</p>
</div>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            name: '张三',
            age: 18,
            sex: '男'
        }
    })
</script>
</script>
</body>
</html>

2.2 v-bind 单向数据绑定

数据仅可从model端view端,详细请看绑定样式

2.3 v-text 文本填充

向DOM中添加文本内容

<!-- v-text插入文本内容 -->
<div id="app1">
    <p v-text="msg"></p>
</div>
<script>
    var vm = new Vue({
        el: '#app1',
        data: {
            msg: '我是v-text'
        }
    })
</script>

2.4 v-html HTML标签填充

<!-- v-html HTML标签填充 -->
<div id="app2">
    <div v-html="h"></div>
</div>
<script>
    var vm = new Vue({
        el: '#app2',
        data: {
            h: '<h1>我是v-html</h1>'
        }
    })
</script>

2.5 v-on 事件监听指令

<!-- v-on 事件监听 -->
<div id="app3">
    <button @click="showAlert">v-on</button>
    <input type="text" @keyup.enter="submit"/>
</div>
<script>
    var vm = new Vue({
        el: '#app3',
        methods: {
            showAlert: function () {
                alert('v-on')
            },
            submit: function () {
                alert('登录成功!')
            }
        }
    })
</script>

2.6 v-for 列表循环

v-for 可以实现页面列表的渲染,常用来循环数组。

<!-- v-for 列表渲染-->
<div id="app4">
    <div v-for="(item,key) in list" data-id="key">
        索引是:{{key}},元素内容是:{{item}}
    </div>
</div>
<script>
    var vm = new Vue({
        el: '#app4',
        data: {
            list: ['a', 'b', 'c', 'd']
        }
    })
</script>

2.7 v-if 或v-show

控制元素显示隐藏,属性为布尔值。

v-if真正的条件渲染,会触发一些绑定的事件,惰性的,如果初始条件是false原始元素就不会进行渲染。条件不经常切换使用这个

v-show:简单进行css样式切换,初始条件为false也会进行渲染,初始渲染开销大。条件经常改变的话常用这个

<!-- v-if 和 v-show -->
<div id="app5">
    <div v-if="isShow" style="background-color: #ccc;">我是v-if</div>
    <div v-show="isShow" style="background-color: #ccc;">我是v-show</div>

    <button @click="isShow=!isShow">显示/隐藏</button>
</div>
<script>
    var vm = new Vue({
        el: '#app5',
        data: {
            isShow: true
        }
    })
</script>

3.事件修饰符

修饰符说明
.stop阻止事件冒泡
.prevent阻止默认事件行为
.capture事件捕获
.self将事件绑定到自身,只有自身才能触发
.once事件只触发一次

3.1 stop 阻止事件冒泡

<!-- 阻止事件冒泡 -->
<div id="app1" @click="doParent" style="width: 100px;border: solid red 1px;">
    <button @click="doThis">事件冒泡</button>
    <br/>
    <button @click.stop="doThis">阻止事件冒泡</button>
</div>
<script>
    var vm = new Vue({
        el: '#app1',
        methods: {
            doThis: function () {
                alert('this');
            },
            doParent: function () {
                alert('parent');
            }
        }
    })
</script>

3.2 prevent 阻止默认行为

<!-- 阻止默认事件 -->
<div id="app2">
    <a href="https://www.baidu.com">不阻止默认事件</a>
    <br/>
    <a href="https://www.baidu.com" @click.prevent>阻止默认事件</a>
</div>
<script>
    var vm = new Vue({
        el: '#app2'
    })
</script>

3.3 capture 事件捕获

<!-- 改变冒泡顺序,事件由外向内 -->
<div id="app3" @click.capture="doParent" style="width: 100px;border: solid red 1px;">
    <button @click="doThis">事件捕获</button>
</div>
<script>
    var vm = new Vue({
        el: '#app3',
        methods: {
            doThis: function () {
                alert('this');
            },
            doParent: function () {
                alert('parent');
            }
        }
    })
</script>

3.4 self 自身触发

<!-- self 只有自身会触发时间,不会被冒泡触发 -->
<div id="app4" @click.self="doParents" style="width: 100px;height: 100px;background-color: #aaaa;">
    a
    <div @click="doSub" style="width: 70px;height: 70px;background-color: #5555;">
        b
    </div>
</div>
<script>
    var vm = new Vue({
        el: '#app4',
        methods: {
            doParents: function () {
                console.log('调用了doParent');
            },
            doSub: function () {
                console.log('调用了doSub');
            }
        }
    })
</script>

3.5 once 只触发一次

<!-- once 事件只触发一次 -->
<div id="app5">
    <button @click.once="doThis">只触发一次</button>
</div>
<script>
    var vm = new Vue({
        el: '#app5',
        methods: {
            doThis: function () {
                console.log('只触发一次')
            }
        }
    })
</script>

三、Vue组件

在Vue中,组件是构成页面中的独立结构单元,能够减少重复代码的编写,提高开发效率,降低代码之间的耦合程度,使项目更易维护和管理。

举例:如果页面中常常要有公司logo那么可以将logo定义为组件。

1.全局组件

在js内部使用**Vue.component(‘组件名’,{template:‘标签’})**可以定义全局组件

<div id="app">
    <my-component></my-component>
    <my-component></my-component>
    <my-component></my-component>
</div>
<div id="app1">
    <myComponent>aaa</myComponent>
</div>
<script>
    // 全局组件
    Vue.component('myComponent',//组件名称,命名的时候可以用驼峰命名法,引用的时候不能使用驼峰命名法,只能使用连接法
        {
            template: "<h2>这是一个全局组件</h2>"//模板就是组件的内容
        }
    );
    Vue.component('my-abc',
        {
            // data是方法,该方法必须要有返回值,通常该返回值是给模板使用的
            data() {
                return {
                    count: 0
                }
            },
            template: "<button v-on:click='count++'>被单击了{{count}}次</button>"
        }
    );
    new Vue({
        el: '#app'
    });
    new Vue({
        el: '#app1'
    })
</script>

2.局部组件

Vue()内部使用components关键字定义自定义组件

<!-- 局部组件 -->
<div id="app2">
    <my-abc></my-abc>
</div>
<script>
    new Vue({
        el: "#app2",
        components: {
            myAbc: {
                template: "<p>这是一个局部组件</p>"
            }
        }
    })
</script>

3.模板变量

将template模板使用变量装起来,使用的时候直接调用该变量即可。

<div id="app3">
    <my-aaa></my-aaa>
</div>
<script>
    //模板变量
    var mytemp = {
        template: '<h3>这是第二个局部组件</h3>'
    };
    new Vue({
        el: '#app3',
        components: {
            myAaa: mytemp
        }
    });
</script>

4.template模板

template内的内容是使用字符串保存的很容易出错,所以我们可以使用template标签html内部定义自定义组件的内容。

注意:template标签下只能有一个子标签

<!-- template 模板 -->
<div id="app4">
    <my-comp></my-comp>
</div>
<template id="temp1">
    <div>
        <h1>这是一个标题</h1>
        <p>这是一个段落:{{title}}</p>
        <button v-on:click="show">单击我</button>
    </div>
</template>
<script>
    Vue.component('my-comp', {
        template: '#temp1',
        data() {
            return {
                title: '我是组件内的title'
            }
        },
        methods: {
            show: function () {
                alert(this.title)
            }
        }
    });
    new Vue({
        el: '#app4'
    })
</script>

5.数据使用规则

vue定义的标签下面使用的自身data内的变量

template下自定义标签使用的变量是data()函数返回来的数据变量

注意:data()函数必须要有返回值

<div id="app5">
    <p>{{title}}</p>
    <my-comp2></my-comp2>
</div>
<template id="temp2">
    <p>{{title}}</p>
</template>
<script>
    Vue.component('my-comp2',
        {
            template: '#temp2',
            data() {
                return {
                    title: '这是组件中的data'
                }
            }
        }
    );
    new Vue({
        el: '#app5',
        data: {
            title: '我是vm实例的title'
        }
    })
</script>

6.组件传值

在Vue中,组件实例具有局部作用域。组件之间的数据传递需要借助一些工具。

6.1 props传值

props即道具,用来接受父组件中定义的数据,其值为数组,数组中是父组件传递的数据信息。

在调用**自定义组件(父组件)的时候使用“ 自定义属性=‘值’ ”的形式想模板中传递数据,子组件中使用“props:[‘name’]”**形式读取到父组件中的自定义属性值。

<!-- props 传值 -->
<div id="app">
    <my-comp name="Tom"></my-comp>
</div>
<script>
    Vue.component("my-comp",
        {
            props: ['name'],
            template: '<h2>从组件中传递的值是:{{name}}</h2>'
        }
    );
    new Vue({
        el: '#app'
    });
</script>
<div id="app1">
    <my-comp1 props-message="父组件的数据"></my-comp1>
</div>
<template id="temp1">
    <div>
        <h3>父组件传给子组件</h3>
        <p>通过props传递的,用props设置的值是组件(自定义标签)的属性名称</p>
        <h4>父组件传递了:{{propsMessage}}</h4>
        <h4>子组件自生的值:{{dataMessage}}</h4>
    </div>
</template>
<script>
    Vue.component('my-comp1',
        {
            template: '#temp1',
            data() {
                return {
                    dataMessage: '子组件中的数据'
                }
            },
            props: ['propsMessage']
        }
    );
    new Vue({
        el: '#app1'
    })
</script>

6.2 父组件用循环传值

案例一:通过循环创建网站列表
<div id="app">
    <ol>
        <todo-item v-for="item in sites" v-bind:todo="item"></todo-item>
    </ol>
</div>
<script>
    Vue.component('todo-item', {
        template: "<li>{{todo.text}}</li>",
        props: ['todo']
    });
    new Vue({
        el: '#app',
        data: {
            sites: [
                {text: 'www.taobao.com'},
                {text: 'www.jingdong.com'},
                {text: 'www.baidu.com'},
            ]
        }
    })
</script>
案例二:通过循环创建子组件表格
<div id="app1">
    <table>
        <!--此处使用的是标题类-->
        <student-list v-bind:stu="title"></student-list>
        <!--此处使用的是遍历学生信息列表类-->
        <student-list v-for="item in students" v-bind:stu="item"></student-list>
    </table>
</div>
<template id="temp1">
    <!--每一个模板为一行,行内有四个列:ID NAME AGE SEX-->
    <tr>
        <td style="border: 1px solid #000">{{stu.id}}</td>
        <td style="border: 1px solid #000">{{stu.name}}</td>
        <td style="border: 1px solid #000">{{stu.age}}</td>
        <td style="border: 1px solid #000">{{stu.sex}}</td>
    </tr>
</template>
<script>
    Vue.component('student-list', {
        template: '#temp1',
        props: ['stu']
    });
    new Vue({
        el: '#app1',
        data: {
            title: {
                id: 'ID',
                name: 'NAME',
                age: 'AGE',
                sex: 'SEX'
            },
            students: [
                {id: '0001', name: '张三', age: 18, sex: '男'},
                {id: '0002', name: '田媛媛', age: 18, sex: '女'},
                {id: '0003', name: '陈雨', age: 20, sex: '男'},
            ]
        }
    })
</script>

6.3 组件多个属性传值

案例一:v-bind 基本多属性传值
<div id="app">
    <p>第一个值<input type="text" v-model="s1"/></p>
    <p>第二个值<input type="text" v-model="s2"/></p>
    <p>第三个值<input type="text" v-model="s3"/></p>
    <hr/>
    <!--通过设置多个绑定来像子组件传递多个单值-->
    <my-comp v-bind:attr1="s1" v-bind:attr2="s2" v-bind:attr3="s3"></my-comp>
</div>
<template id="my-temp">
    <div>
        <h3>多个属性的传值</h3>
        <p>值1:{{attr1}}</p>
        <p>值2:{{attr2}}</p>
        <p>值3:{{attr3}}</p>
    </div>
</template>
<script>
    Vue.component('my-comp', {
        template: '#my-temp',
        props: ["attr1", "attr2", "attr3"]
    });
    new Vue({
        el: '#app',
        data: {
            s1: '',
            s2: '',
            s3: ''
        }
    })
</script>
案例二:多个属性传值双向绑定
<div id="app">
    <p>第一个值<input type="text" v-model="s1"/></p>
    <p>第二个值<input type="text" v-model="s2"/></p>
    <p>第三个值<input type="text" v-model="s3"/></p>
    <hr/>
    <my-comp v-bind:attr1="s1" v-bind:attr2="s2" v-bind:attr3="s3"></my-comp>
</div>
<template id="my-temp">
    <div>
        <h3>多个属性的传值</h3>
        <p>值1:{{attr1}}</p>
        <p>值2:{{attr2}}</p>
        <p>值3:{{attr3}}</p>
        <p>点击按钮后得到的值:{{content1}}</p>
        <p>及时得到的值:{{content2}}</p>
        <p>计算得到的值:{{contentx}}</p>
        <button @click="show">按钮</button>
    </div>
</template>
<script>
    Vue.component('my-comp', {
        template: '#my-temp',
        props: ["attr1", "attr2", "attr3"],
        data: function () {
            return {
                content1: "",
                content2: ""
            }
        },
        methods: {
            //方法:按钮触发
            show() {
                this.content1 = this.attr1 + this.attr2 + this.attr3;
            }
        },
        watch: {
            //数据监听
            attr1: function () {
                this.content2 = this.attr1 + this.attr2 + this.attr3;
            },
            attr2: function () {
                this.content2 = this.attr1 + this.attr2 + this.attr3;
            },
            attr3: function () {
                this.content2 = this.attr1 + this.attr2 + this.attr3;
            },
        },
        computed:{
            //数据计算
            contentx:function () {
                return this.attr1 + this.attr2 + this.attr3;
            }
        }
    });
    new Vue({
        el: '#app',
        data: {
            s1: '',
            s2: '',
            s3: ''
        }
    })
</script>

6.4 $emit方法 子组件像父组件传值

语法

this.$emit('处理方法', 数据);

案例

<div id="app">
    <!--父组件-->
    <parent></parent>
</div>
<template id="child">
    <!--子组件模板-->
    <div>
        <button @click="click">传值</button>
        <!--绑定了子组件中的message属性-->
        <input type="text" v-model="message"/>
    </div>
</template>
<script>
    //父组件
    Vue.component('parent', {
        //父组件模板,子组件通过@childFn绑定了一个父组件事件处理方法,子组件可以通过该方法改变父组件中message的值
        template: '<div><child @childFn="transContent"></child>子组件传来的值:{{message}}</div>',
        data: function () {
            return {
                // 父组件中的message
                message: ''
            }
        },
        methods: {
            //通过该事件处理方法可以修改父组件中message的值
            transContent: function (payload) {
                this.message = payload;
            }
        }
    });
    //子组件
    Vue.component('child', {
        template: '#child',
        data: function () {
            return {
                //子组件中的message属性
                message: '子组件的消息'
            }
        },
        methods: {
            click() {
                //激活调用父组件中childFn绑定的事件,传的值是message
                this.$emit('childFn', this.message);
                //有点像java里面的super?
            }
        }
    });
    new Vue({
        el: '#app'
    })
</script>

7.组件切换

7.1 v-if v-else形式切换

<div id="app">
    <label>
        第一个页面内容
        <input type="text" v-model="titleLogin"/>
    </label>
    <label>
        第二个页面内容
        <input type="text" v-model="titleRegister"/>
    </label>
    <br/>
    <!--通过点击事件修改flag属性-->
    <a href="#" @click.prevent="flag=true">登录页面</a>
    <a href="#" @click.prevent="flag=false">注册页面</a>
    <!--v-if v-else 配个标志属性进行简单的隐藏切换-->
    <login v-if="flag" :title-name="titleLogin"></login>
    <register v-else="flag" :title-name="titleRegister"></register>
</div>
<script>
    // div的基本样式
    Vue.component('login', {
        props: ['title-name'],
        template: '<div style="width: 100px;height: 100px;background-color: #00ff00;color: red">{{titleName}}</div>'
    });
    Vue.component('register', {
        props: ['title-name'],
        template: '<div style="width: 100px;height: 100px;background-color: #007ff0;color: yellow">{{titleName}}</div>'
    });
    new Vue({
        el: '#app',
        data: {
            flag: true,
            titleLogin: '登录',
            titleRegister: '注册'
        }
    })
</script>

7.2 is属性组件切换

<div id="app">
    <!-- 通过is属性修改模板的名字 -->
    <a href="#" @click.prevent="comName='login'">登录页面</a>
    <a href="#" @click.prevent="comName='register'">注册页面</a>
    <!-- is绑定模板名字,被绑定的名字被修改则显示的模板也会被修改 -->
    <component :is="comName"></component>
</div>
<script>
    Vue.component('login', {
        props: ['title-name'],
        template: '<div style="width: 100px;height: 100px;background-color: #00ff00;color: red">{{登录页面}}</div>'
    });
    Vue.component('register', {
        props: ['title-name'],
        template: '<div style="width: 100px;height: 100px;background-color: #007ff0;color: yellow">{{注册页面}}</div>'
    });
    new Vue({
        el: '#app',
        data: {
            comName: 'login',
        }
    })
</script>

四、Vue的生命周期

1.钩子函数

钩子函数用来描述Vue实例从创建到销毁的的整个生命周期

钩子说明
beforeCreate创建实例对象之前执行
created创建实例对象之后执行
beforeMount页面挂在成功之前执行
mounted页面挂在成功之后执行
beforeUpdate组件更新之前执行
updated组件更新之后执行
beforeDestroy实例销毁之前执行
destroyed实例销毁之后执行

1.1实施创建

<div id="app">{{msg}}</div>
<script>
    new Vue({
        el: '#app',
        data: {
            msg: '张三'
        },
        beforeCreate() {
            console.log('实例创建之前');
            // console.log(this.$data.msg);
        },
        created() {
            console.log('实例创建之后');
            console.log(this.$data.msg);
        }
    })
</script>

1.2实施销毁

<div id="app">
    <!--ref是用来注册引用信息的-->
    <div ref="self">{{msg}}</div>
</div>
<script>
    new Vue({
        el: '#app',
        data: {
            msg: '张三'
        },
        beforeDestroy(){
            console.log('销毁之前');
            console.log(this.$refs.self);
            console.log(this.msg);
            console.log(vm);
        },
        destroyed(){
            console.log('销毁之后')
        }
    })
</script>

1.3实时更新

<div id="app">
    <!--ref是用来注册引用信息的-->
    <div v-if="isShow" ref="self">test</div>
    <button @click="isShow=!isShow">更新</button>
</div>
<script>
    new Vue({
        el: '#app',
        data: {
            isShow: false
        },
        beforeUpdate() {
            console.log('更新之前');
            console.log(this.$refs.self);
        },
        updated() {
            console.log('更新之后');
            console.log(this.$refs.self);
        }
    })
</script>

1.4页面挂载

<div id="app">{{msg}}</div>
<script>
    new Vue({
        el: '#app',
        data: {
            msg: '张三'
        },
        beforeMount() {
            //Vue与DOM关联之前
            console.log('页面挂载之前');
            console.log(this.$el.innerHTML);
        },
        mounted() {
            //Vue与DOM关联之后
            console.log('页面挂载之后');
            console.log(this.$el.innerHTML);
        },
        beforeCreate() {
            console.log('实例创建之前');
            // console.log(this.$data.msg);
        },
        created() {
            console.log('实例创建之后');
            console.log(this.$data.msg);
        }
    })
</script>

1.5案例:实时显示时间

<div id="app">
    <p id="time"></p>
    <h3>格式化时间</h3>
    <p>{{date|formatTime}}</p>
    <p>
        <button @click="stop">停止时间</button>
    </p>
</div>
<script>
    var p1 = document.querySelector('#time');
    p1.innerHTML = new Date();

    function parseDate(val) {
        return val < 10 ? '0' + val : val;//小于10的数字,前面加0
    }

    var vm = new Vue({
        el: '#app',
        data: {
            date: new Date(),
        },
        filters: {
            formatTime: function (time) {
                var year = time.getFullYear();
                var month = parseDate(time.getMonth() + 1);
                var day = parseDate(time.getDate());
                var hours = parseDate(time.getHours());
                var minute = parseDate(time.getMinutes());
                var seconds = parseDate(time.getSeconds());
                return year + '-' + month + '-' + day + " " + hours + ':' + minute + ':' + seconds;
            }
        },
        created: function () {
            var that = this;//保持作用域的一致,此处that就是当前对象
            this.timmer = setInterval(function () {
                that.date = new Date();
            }, 1000);
        },
        methods: {
            stop: function () {
                clearInterval(this.timmer)
            }
        }
    })
</script>

五、插槽

使用方法为:

  1. 在自定义组件标签中间写上预留内容。
  2. 在模板中使用标签,将预留内容引入。(假如模板中未使用标签,那么自定义标签中间的内容将会被忽略。)

1.插槽简单使用

当组件渲染的时候,将会被插槽预留的内容所替换,如下案例:

<div id="app">
    <my-comp>
        <h5>这是组件,在组件中写内容</h5>
    </my-comp>
</div>
<template id="temp1">
    <div>
        <!-- 插槽就是模板预留的接口-->
        <slot></slot><!--会替换为:<h5>这是组件,在组件中写内容</h5>-->
        <p>这是模板内容,段落1</p>
        <p>这是模板内容,段落2</p>
        <p>这是模板内容,段落3</p>
        <slot></slot>
        <p>模板中的数据{{tempData}}</p>
        <slot></slot>
    </div>
</template>
<script>
    Vue.component('my-comp',{
        template: '#temp1',
        data:function () {
            return{
                tempData: new Date()
            }
        }
    });
    new Vue({
        el: "#app",
    })
</script>

2.简单使用2

<div id="app">
    <my-comp1>辣椒炒肉</my-comp1>
    <my-comp1>辣椒炒蛋</my-comp1>
    <my-comp1>空心菜</my-comp1>
    <hr/>
    <!--此处采用v-for循环遍历的形式将foods里面的值引入到自定义标签中-->
    <my-comp1 v-for="item in foods">{{item.name}}</my-comp1>
    <hr/>
    <my-comp1></my-comp1>
</div>
<template id="temp1">
    <dl>
        <dt>
            <!--通过slot标签将自定义标签中的内容引入进来-->
            <slot>默认值,使用时没有给内容</slot>
            <!--默认值:如果自定义标签内部没有内容
						将会使用slot标签中间的内容-->
        </dt>
        <dd>中国湘菜,湘菜最强。</dd>
    </dl>
</template>
<script>
    Vue.component('my-comp1', {
        template: '#temp1'
    });
    new Vue({
        el: '#app',
        data: {
            foods: [
                {name: '辣椒炒肉'},
                {name: '辣椒炒蛋'},
                {name: '辣子鸡'}
            ]
        }
    })
</script>

3.具名插槽

在定义自定义标签的预留内容的时候将标签加上slot='名字’属性,那么在标签调用插槽的时候,就需要用name='名字’匹配使用

<div id="app">
    <my-compl>
        <!--这个标签只有当slot标签name属性为'girl'的时候才会被匹配使用-->
        <span style="background-color: pink;" slot="girl">漂亮、温柔、贤惠</span>
        <!--这个标签只有当slot标签name属性为'boy'的时候才会被匹配使用-->
        <span style="background-color: #007fff" slot="boy">帅气,高大,富有</span>
        <!--默认的内容,如果没有匹配到的对象就会使用该默认内容-->
        <div>
            打工仔、干饭人、舔狗
        </div>
    </my-compl>
</div>
<template id="templ">
    <div>
        <h4>这个世界有男人和女人</h4>
        <p>女人:
            <!--匹配引入了自定义标签中,slot属性为‘girl'的标签-->
            <slot name="girl"></slot>
        </p>
        <p>男人:
            <!--匹配调用了自定义标签中,slot属性为‘boy'的标签-->
            <slot name="boy"></slot>
        </p>
        <!--调用了自定义标签中的默认内容-->
        <slot></slot>
    </div>
</template>
<script>
    Vue.component('my-compl', {
        template: '#templ'
    });
    new Vue({
        el: '#app'
    })
</script>

4.案例:标题、正文、页脚匹配

此处我们也能看出,采用自定义控件+插槽的形式会使得控件格式更好规范添加。

<div id="app">
    <my-compl>
        <!--定义了标题、内容、页脚部分,还有默认内容-->
        <h3 slot="headerName">这是我的主页</h3>
        <p slot="mainName">这是我的主页内容</p>
        <h4 slot="footerName">这是页脚部分</h4>
        <p>今天是2021年的4月25日</p>
    </my-compl>
</div>
<template id="templ">
    <div>
        <header>
            <!--匹配标题部分-->
            <slot name="headerName">页面标题</slot>
        </header>
        <mian>
            <!--匹配正文部分-->
            <slot name="mainName">正文部分</slot>
            <slot>默认插槽</slot>
        </mian>
        <footer>
            <!--匹配页脚部分-->
            <slot name="footerName">页脚部分</slot>
        </footer>
    </div>
</template>
<script>
    Vue.component('my-compl', {
        template: '#templ'
    });
    new Vue({
        el: '#app'
    })
</script>

5.插槽作用域

通过slot-scope(插槽作用域)刻印进行一些数据的传递。slot-scope返回的是一个数据集合,里面有调用者的自定义属性的key:value集合

<div id="app">
    <my-compl>
        <template slot-scope="a">
            {{a}}<!--输出结果为:{ "say": "你好", "n": "我是cy" }-->
        </template>
    </my-compl>
</div>
<script>
    Vue.component('my-compl', {
        template: '<div><slot say="你好" n="我是cy"></slot></div>'
    });
    new Vue({
        el: '#app'
    })
</script>

6.案例:匹配item格式

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>插槽作用域</title>
    <script src="../js/vue.js"></script>
    <style>
        .current {
            color: orange;
        }
    </style>
</head>
<body>
<div id="app">
    <!--父组件(在DOM中使用自定义组件)-->
    <!--1.引入flist数组集合-->
    <fruit :list="flist">
        <!--5.获得调用者的属性集合-->
        <template slot-scope="slotprops">
            <!--6.内部判断插槽作用域内部元素的id值,并匹配样式-->
            <strong v-if="slotprops.info.id==2" class="current">
                {{slotprops.info.name}}
            </strong>
            <span v-else>{{slotprops.info.name}}</span>
        </template>

    </fruit>
</div>
<!--组件部分-->
<template id="temp">
    <div>
        <ul>
            <!--3.通过循环遍历数组集合-->
            <li :key="item.id" v-for="item in list">
                <!--4.将item(集合数据)绑定到插槽作用域里面去,格式为info:{id:'',name:''}-->
                <slot :info="item"></slot>
            </li>
        </ul>
    </div>
</template>
<script>
    Vue.component('fruit', {
        template: '#temp',
        props: ['list'],//2.将父组件的属性list传到子组件
    });
    new Vue({
        el: "#app",
        data: {
            //数据集合
            flist: [
                {id: 1, name: 'apple'},
                {id: 2, name: 'banana'},
                {id: 3, name: 'orange'},
            ]
        }
    })
</script>
</body>
</html>

7.具名插槽结合使用

<div id="app">
    <!--1.获得vue里面的data-->
    <my-comp :items="items">
        <!--4.引用具名插槽,填入数据-->
        <template slot="item" scope="pro">
            <li>
                {{pro.text}}--{{pro}}
                <!--
                输出结果:
                示例1--{ "text": "示例1" }
                示例2--{ "text": "示例2" }
                示例3--{ "text": "示例3" }
                -->
            </li>
        </template>
    </my-comp>
</div>
<template id="temp">
    <div>
        <ul>
            <!--3.得到数据列表items,并遍历items,绑定text属性-->
            <slot name="item" v-for="item in items" :text="item.text"></slot>
        </ul>
    </div>
</template>
<script>
    Vue.component('my-comp', {
        template: '#temp',
        //2.数据传递,传递到子组件
        props: ['items']
    });
    new Vue({
        el: '#app',
        data: {
            items: [
                {text: '示例1'},
                {text: '示例2'},
                {text: '示例3'},
            ],
        }
    })
</script>

8.具名插槽默认内容

<div id="app">
    <my-comp>
        <!--为空的时候不执行slot内的-->
    </my-comp>
    <my-comp>
        <!--有调用的时候启用slot,slot内部的则不启用-->
        <template slot-scope="myslot">
            <span>
                {{myslot.datail.join("-")}}
            </span>
        </template>
    </my-comp>
</div>
<template id="temp">
    <div>
        <slot :datail="books">
            <!--slot被调用的时候,这里面的默认内容就不会显示-->
            <ul>
                <li v-for="item in books">{{item}}</li>
            </ul>
        </slot>
    </div>
</template>
<script>
    Vue.component('my-comp', {
        template: '#temp',
        data() {
            return {
                books: [
                    '唐诗三百首',
                    '宋词',
                    '元曲',
                    '小说',
                ]
            }
        }

    });
    new Vue({
        el: '#app',
        data: {
            books: '父组件数据'
        }
    })
</script>

Vue学习笔记02——Vue路由

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值