Vue笔记-03

Vue中的指令、事件和生命周期

01、Vue中常见的指令

参考网站:https://v2.cn.vuejs.org/v2/api/

  • 文本指令:
    • v-html
    • v-text
  • 条件指令
    • v-if
    • v-else-if
    • v-else
  • 循环指令
    • v-for
  • 隐藏显示指令
    • v-show
  • 事件指令
    • v-on
  • 表单指令
    • v-model
  • 属性指令
    • v-bind
  • 插槽指令(组件的时候在来讲解)
    • v-slot
  • 杂项
    • v-clocak
    • v-once
    • v-pre

对指令的认识?

  • 1:插值表达式是不可能完成所有的事情 {{}},它仅仅值是负责把响应式数据(data)取出来渲染到视图上去,可以做一些四则运算或者三目运算。
  • 2:其实vue是通过js语言封装出来一个js组件库,他的核心思想:去dom化,去dom必须也使用不同的方式来达到和js一样功能
    • 比如:如何绑定事件
    • 比如:如何添加属性,如何获取属性,如何删除删除
    • 比如:如何添加样式(style/id/class)
    • 比如:如何获取表单的值
    • 比如:如何添加子元素
    • 等等。。。。。。
  • 3:所以我们在vue中提供了一些列的指令来完成上面的工作和事情。

指令和插值表达式能混用吗?

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>常用指令的学习和掌握</title>
</head>
<body>


    <div id="app">
        <h1>{{title}}</h1>
        <div v-html="title"></div>
    </div>

    <script src="js/vue.js"></script>
    <script>
        var app = new Vue({
            el:"#app",
            data:{
                title:"<strong>我是一个Vue</strong>"
            }
        })
    </script>
    
</body>
</html> 

答案告诉:在指令中,是绝对不可能去使用插值表达式。

{{title}}
<span v-html="{{title}}"></span>这个错误的

指令和插值表达式和什么关?

和响应式数据有关。

不抡是指令和插值表达式,永远都在围绕这响应式数据进行处理,要么就是响应式数据取出来,要么就改变响应式数据。

01、文本指令

  • v-text : 不支持解析标签,支持:运算和取值

  • v-html: 支持解析标签,支持:运算和取值

  • ```html

    常用指令的学习和掌握
    <div id="app">
        <h1>{{bbs.title}}</h1>
        <div>{{bbs.content}}</div>
        性别是:{{bbs.male==1?"男":"女"}}
        性别是:<span v-text='bbs.male==1?"男":"女"'></span>
        <div v-html="bbs.content"></div>
    </div>
    
    <script src="js/vue.js"></script>
    <script>
        var app = new Vue({
            el:"#app",
            data:{
               bbs:{
                    id:1324194891442282498,
                    title:"Spring Bean生命周期",
                    male:1,
                    content:"<p>网上把前后<strong>端分离版的</strong>若依拉下来跑</p><p><br></p>"
               }
            }
        })
    </script>
    
    ```

文本指令是获取data的响应式数据,渲染到视图的文本节点上。说明未来你只要在data定义的响应式数据,想放到视图中,就可以通过此指令或者插值表达式,也就说:指令上不能够写一个在响应式数据data中不存在的属性,否则就报错。

Property or method “age” is not defined

这个错误就是告诉,在指令中你定义的某个属性或者方法找不到,vue的底层会在data中先查找以一次,如果找不到就去methods中找一次看又没有定义这个对应的方法,如果定义了也会返回这个定义这个函数的引用,如果你要执行,请加括号即可:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>常用指令的学习和掌握</title>
</head>
<body>


    <div id="app">
        {{age()}}
    </div>

    <script src="js/vue.js"></script>
    <script>
        var app = new Vue({
            el:"#app",
            methods: {
                age(){
                    return 100
                }
            },
        })
    </script>
    
</body>
</html>

02、条件指令

  • v-if
  • v-else-if
  • v-else
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>常用指令的学习和掌握</title>
</head>
<body>


    <div id="app">
        <p>id是:{{user.id}}</p>
        <p>名字是:{{user.username}}</p>
        
        <fieldset>
        <p>性别是:{{user.male==1?"男":"女"}}</p>
        <hr>
        <p>性别是:
            <span v-if="user.male==1"></span>
            <span v-if="user.male==0"></span>
        </p>
        <hr>
        <p>性别是:
            <span v-if="user.male==1"></span>
            <span v-else></span>
        </p>
        </fieldset>

        <fieldset>
            <p>性别是:{{user.male==1?"男":(user.male==1?"女":"保密")}}</p>
            <p>性别是:
                <span v-if="user.male==1"></span>
                <span v-if="user.male==0"></span>
                <span v-if="user.male==2">保密</span>
            </p>
            <hr>
            <p>性别是:
                <span v-if="user.male==1"></span>
                <span v-else-if="user.male==0"></span>
                <span v-else>保密</span>
            </p>
        </fieldset>
        
    </div>

    <script src="js/vue.js"></script>
    <script>
        var app = new Vue({
            el:"#app",
            data:{
                user:{
                    id:1,
                    male:0,/*1男 0女 2保密*/
                    username:"飞哥"
                }
            }
        })
    </script>
    
</body>
</html>
  • 条件指令:其实在开发中,响应式数据中可能存在一些数据的逻辑判断和处理的。所以如果你想要对响应式数据的中一些数据进行判断和改造就使用条件指令,比如上面的性别是数字,但是展示是:文字,你就可以使用:条件指令。
  • 条件指令,如果是使用v-if/v-else-if/v-else连续使用,不允许插入元素,否则就出现断层,可以插入文本,插入文本会自动删除
  • 如果未来一段代码不先想要,也不想在源码中体现出来。确实你可以使用v-if=“false”

v-if 控制的元素,只有true才会显示在源码中,为false自动删除。

03、循环指令

  • v-for : 循环数组,循环对象
    • 下表
    • 元素
    • key
  • v-for不要和v-if同时作用一个标签
  • v-for循环的标签元素,一定要增加key属性

04、隐藏显示指令

  • v-show 是控制css样式的display:none/block的切换。
  • 没有v-hidden指令。只能通过v-show=“true/false”来达到隐藏和显示
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>常用指令的学习和掌握</title>
    <style>
        .commentbox{margin: 20px;}
        .comment-item{box-shadow: 0 0 1em #ccc;margin-bottom: 20px;padding:10px}
        .comment-item.odd{background:#000;color:#fff}
        .comment-item.even{background:red;color:#fff}
    </style>
</head>

<body>


    <div id="app">
        <div class="commentbox">
            <div v-show="false">隐藏起来了</div>
            <div v-show="true">显示了</div>
        </div>
    </div>

    <script src="js/vue.js"></script>
    <script>
        var app = new Vue({
            el: "#app",
            data: {
                
            },
            methods:{

               
            }
        })
    </script>

</body>

</html>

v-if和v-show

  • v-if 满足条件节点在源码中显示,不满足不显示
  • v-show: 都会显示,只不过false的情况,是隐藏起来起来。
  • v-show是绝对不可能去替代v-if。 v-show做不到v-if/v-else的功能

05、表单指令

  • v-model
  • 给响应式数据赋值的指令。
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>常用指令的学习和掌握</title>
    <style>
        .commentbox{margin: 20px;}
        .comment-item{box-shadow: 0 0 1em #ccc;margin-bottom: 20px;padding:10px}
        .comment-item.odd{background:#000;color:#fff}
        .comment-item.even{background:red;color:#fff}
    </style>
</head>

<body>


    <div id="app">
        <form action="">
            {{form}}
            <p>账号: <input type="text" v-model="form.username"></p>
            <p>密码: <input type="password" v-model="form.password"></p>
            <p>手机: <input type="text" v-model="form.phone"></p>
            <p>邮箱: <input type="text" v-model="form.email"></p>
            <p>性别: 
                <input type="radio" v-model="form.male" name="male" value="0"><input type="radio" v-model="form.male" name="male" value="1"></p>
            <p>兴趣爱好: 
                <input type="checkbox" v-model="form.hobbys" name="hobbys" value="1">旅游 
                <input type="checkbox" v-model="form.hobbys" name="hobbys" value="2">看书
                <input type="checkbox" v-model="form.hobbys" name="hobbys" value="3">打游戏
            </p>
            <p><button @click.prevent="handleLogin">登录</button></p>
        </form>
    </div>

    <script src="js/vue.js"></script>
    <script>
        var app = new Vue({//现任
            el: "#app",
            data: {

                queryParams:{
                    pageNo:1,
                    pageSize:10,
                    total:0
                },

                form:{}
            },
            methods:{
                handleLogin(){
                    var username = this.username;
                    var password = this.password;

                    // 重置
                    this.reset();
                },
                reset(){
                    this.form = {
                        username:"",
                        password:"",
                        phone:"",
                        email:"",
                        male:1,
                        hobbys:[]
                    };
                }
            }
        })
    </script>

</body>

</html>

v-model : 底层会自动给data中的属性赋值,如果属性过多建议大家一定学会使用对象进行包裹,然后隔离。

06、v-bind 属性指令

  • v-bind
    • class
    • style
  • 在元素,肯定会存在元素属性,属性分为两种一种自定义属性,一种是自带的属性
    • 自带属性,一般就是指:class/style/id等等.
  • 简写::
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>

    <div id="app">
        <div v-bind:title="title" v-bind:opid="opid"></div>
        <div :title="title" :opid="opid"></div>
    </div>

    <span>文本域</span>

    <script src="js/vue.js"></script>
        
    <script>
        var vue = new Vue({
            el:"#app",
            data:{
                title:"我是一个标题",
                opid:100
            }
        })
    </script>
</body>
</html>

v-bind的特殊处理class和style

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        a {
            text-decoration: none;
            color: #333
        }

        ul,li{list-style: none;}
        .tab-box{width: 640px;border:2px solid #ccc;margin: 10px;}
        .tab-box .list{display: flex;border-bottom:2px solid #ccc;padding:10px}
        .tab-box .list li{margin: 0 10px;}
        .tab-box .list li.actived{color:red;font-weight: bold;}
        .tab-box .contentbox{padding: 10px;}
    </style>
</head>

<body>  
 
    <div id="app">

        <div class="tab-box">
           <ul class="list">
                <li :class="[currentIndex==0?'actived':'']" @click="handleChange(0)">User</li>
                <li :class="[currentIndex==1?'actived':'']" @click="handleChange(1)">Config</li>
                <li :class="[currentIndex==2?'actived':'']" @click="handleChange(2)">Role</li>
                <li :class="[currentIndex==3?'actived':'']" @click="handleChange(3)">Task</li>
           </ul>
           <div class="contentbox">
                <div v-if="currentIndex==0">user</div>
                <div v-if="currentIndex==1">config</div>
                <div v-if="currentIndex==2">role</div>
                <div v-if="currentIndex==3">task</div>
           </div>
        </div>

    </div>

    <script src="js/vue.js"></script>

    <script>
        var vue = new Vue({
            el: "#app",
            data: {
                currentIndex: 10,
                currentIndex:1
            },
            methods:{
                handleChange(tabIndex){
                   this.currentIndex = tabIndex
                }
            }
        })
    </script>
</body>

</html>

07、事件指令

  • v-on
  • 事件定义在methods中
  • 但是事件是:改变响应式数据的一种方式

08、生命周期

01、场景

现在我有一个需求,就是页面初始化完毕的时候,我就需要把接口的数据通过异步的方式加载出来。这里就有二个问题:

  • 我加载这个接口的方法定义在哪里?—methods
  • 定义好这个方法以后,我在哪里去加载呢?—>?
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        * {
            padding: 0;
            margin: 0;
        }

        .container {
            margin: 50px auto;
            width: 960px;
            background: #eee;
            padding:30px;
        }

        .container table{width: 100%;border-collapse: collapse;}
        .container table th,
        .container table td{border:1px solid #ddd;text-align: left;padding:8px;}
    </style>
</head>

<body>


    <div id="app">
        <div class="container">
            <h1 style="margin-bottom: 10px;">{{title}}</h1>
            <h1 style="margin-bottom: 10px;" v-text="title"></h1>
            <table>
                <thead>
                    <tr>
                        <th>ID</th>
                        <th>封面</th>
                        <th>标题</th>
                        <th>描述</th>
                        <th>价格</th>
                        <th>状态</th>
                        <th>操作</th>
                    </tr>
                </thead>
                <tbody>
                    <tr v-for="(course,index) in courseList" :key="course.id" @click="handleParent">
                        <td>{{course.id}}</td>
                        <td>
                            <img :src="course.img" alt="">
                        </td>
                        <td>{{course.title}}</td>
                        <td>
                  
                            <span>{{course.desc.substring(0,10)}}</span>
                            <span v-show="!course.showMore">{{course.desc.substring(10)}}</span>
                            <a v-show="course.desc.length > 10" @click="handleExpand(index)" href="javascript:void(0);">
                                {{course.showMore?"展开":"收起"}}
                            </a>
                        </td>
                        <td>¥{{course.price}}</td>
                        <td>
                            <span style="color:green" v-if="course.status==1">上架</span>
                            <span style="color:red" v-else>下架</span>
                            <!-- {{course.status==1?"上架":"下架"}} -->
                        </td>
                        <td>
                            <a href="javascript:void(0);" v-on:click.stop="handleUpdate(index)">编辑</a>
                            <a href="javascript:;" @click.stop="handleDelete(index)">删除</a>

                            <a href="#" v-on:click.prevent.stop="handleUpdate(index)">编辑1</a>
                            <a href="#" @click.prevent.stop="handleDelete(index)">删除2</a>
                            <a v-bind:href="'/detail/'+course.id" target="_blank">查看明细</a>
                        </td>
                    </tr>
                </thead>
            </table>
        </div>
    </div>


    <script src="js/vue.js"></script>
    <script>
        var vue = new Vue({
            el: "#app",
            data: {
                title: "我是课程列表",
                courseList: []
            },
            methods:{
                // 数据加载的方法
                handleLoadData(){
                    //执行查询课程的异步请求
                    //axios.get("/xxxx").then(res=>{
                     // this.courseList = res.data;
                     this.courseList = [{ 
                            id: "1498123423423423423",
                            title: "预科阶段", 
                            desc:" 平台刚上线",
                            price:25,
                            status:1,
                            showMore:true,
                            img: "https://www.kuangstudy.com/assert/course/c1/02.jpg" 
                        },
                        { 
                            id: "1498123423423423424",
                            title: "入门环境搭建55", 
                            desc:" 平台刚上线的时候有人说我们最多活不过一年,现在都快两年了,我相信10年后,我们还在,不忘初心!",
                            price:49,
                            status:0,
                            showMore:false,
                            img: "https://www.kuangstudy.com/assert/course/c1/03.jpg" 
                        },
                        { 
                            id: "1498123423423423425",
                            title: "基础语法学习", 
                            desc:" 平台刚上线的时候有人说我们最多活不过一年,现在都快两年了,我相信10年后,我们还在,不忘初心!",
                            price:12,
                            status:1,
                            showMore:false,
                            img: "https://www.kuangstudy.com/assert/course/c1/04.jpg" 
                        },
                        { 
                            id: "1498123423423423425",
                            title: "基础语法学习", 
                            price:12,
                            showMore:false,
                            desc:" 平台刚上线的时候有人说我们最多活不过一年,现在都快两年了,我相信10年后,我们还在,不忘初心!",
                            status:1,
                            img: "https://www.kuangstudy.com/assert/course/c1/04.jpg" 
                        }]
                    //})


                },

                handleExpand(index){
                    this.courseList[1].showMore = !this.courseList[1].showMore;
                },

                handleUpdate(index){
                    var course = this.courseList[index]
                    alert("你编辑了..."+JSON.stringify(course))
                },

                handleDelete(index){
                    this.courseList.splice(index,1);
                    alert("你删除了...")
                },

                handleParent(){
                    //alert("tr点击了...");
                }
            }

        })
    </script>


</body>

</html>

02、概述

官网:https://v2.cn.vuejs.org/v2/guide/instance.html#%E5%AE%9E%E4%BE%8B%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%E9%92%A9%E5%AD%90

掌握它的生命周期是为了用它的生命周期的方法:一共8个,两两一组

这些方法不用我们触发,都是由vue自己触发的方法,知道这些方法的调用时机就可以了

创建时期:beforeCreate created

挂载时期:beforeMount mounted

更新时期:beforeUpdate updated

死亡时期:beforeDestory destoryed

每个 Vue 实例在被创建时都要经过一系列的初始化过程——例如,需要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。同时在这个过程中也会运行一些叫做生命周期钩子的函数,这给了用户在不同阶段添加自己的代码的机会。

生命周期就是告诉:vue从初始化到编译,实例挂载,到模版替换,到数据渲染是分阶段。而vue在这些阶段里面提供一个暴露钩子方法,让你可以在这些阶段添加一些改变数据方式,它会把你的改变的数据方法,导入到整个生命周期弄。进行重新编译和替换。

03、方法和时期的作用

你可以在这些方法中,去变更data的数据,vuejs会把你修改的数据进行渲染。

核心代码

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>生命周期</title>
    <script src="js/vue.min.js"></script>
</head>
<body>
<div id="app">
    {{message}}
    <button @click="changeupdate">更新数据</button>
</div>

<script>
    var vm = new Vue({
        el : "#app",
        data : {
            message : 'hello world',
            users:[]
        },
        methods:{
            changeupdate:function(){
                this.message = "4";
            }
        },
        beforeCreate : function() {
            console.log(this);
            showData('创建vue实例前', this);
        },

        created : function() {
            // 在这个阶段可以修改
            this.message = "1.";
            showData('创建vue实例后', this);
        },

        // 替换和编译阶段
        beforeMount : function() {
            this.message="2";
            showData('挂载到dom前', this);
        },

        mounted : function() {
            // 这里有一个问题?
            this.message = "3";
            showData('挂载到dom后', this);
        },


        beforeUpdate : function() {
            showData('数据变化更新前', this);
        },

        updated : function() {
            showData('数据变化更新后', this);
        },

        beforeDestroy : function() {
            showData('vue实例销毁前', this);
        },

        destroyed : function() {
            showData('vue实例销毁后', this);
        }
    });
    
    function realDom() {
        console.log('真实dom结构:' + document.getElementById('app').innerHTML);
    }
    
    function showData(process, obj) {
        console.log(process);
        console.log('data 数据:' + obj.message)
        console.log('挂载的对象:')
        console.log(obj.$el)
        realDom();
        console.log('------------------')
        console.log('------------------')
    }
    // 忘记注释
    vm.message = "good...";
    vm.$destroy();
</script>
</body>
</html>

小结
vuejs的生命周期钩子有几个?分别是?

04、为什么要学习生命周期

1:是因为开放的过程,有一些逻辑的数据初始化需要在页面加载完毕的时候就去执行。那么必须要知道那个地方执行即可:

created
mounted
1:一般在开放中我们都会使用这个两个方法去初始化和改变数据,然后给后续进行渲染和替换。不是beforeMounte不行,是因为mounted更适合。
2:如果未来在vue中存在js的dom操作。你就必须在mounted中进行定义和处理

09、Vuejs计算属性:computed

01、概述

在一些业务的开发中,在模板中使用表达式非常的方便,但是如果在模板中表达式的逻辑过于复杂,模板就会变得臃肿不堪且难以维护。比如:

<div id="app">
    {{message.split('').reverse().join('')}}
</div>

<script src="js/vue.min.js"></script>
<script>
    var vue = new Vue({
        el: "#app",
        data: {
            message: "Hello,Vue 无难事"
        },
        methods: {

        }
    })
</script>

插值表达式Mustache语法中的表达式调用了3个方法来最终实现字符串的反转,逻辑过于复杂。如果在模板中还要多次引用此处的翻转字符串,就更加难以理解和处理。这时应该使用计算属性可以很好的解决这个问题。

02、计算属性的定义

如果在开发中逻辑过于复杂的时候,应该考虑计算属性,计算属性是以函数形式来进行表达,定义在computed选项中定义,如下:

<div id="app">
    <p>原始字符串是:{{message}}</p>
    <p>计算后反转字符串:{{reverseMessage}}</p>
</div>

<script src="js/vue.min.js"></script>
<script>
    var vue = new Vue({
        el: "#app",
        data: {
            message: "Hello,Vue 无难事"
        },
        computed:{
            reverseMessage(){
                return this.message.split("").reverse().join('')
            }
        },
        methods: {

        }
    })
</script>

03、computed计算属性能修改吗?

答案:是不能,因为计算属性内部只提供了getter方法,没有提供setter方法。因为计算属性是监听响应式数据的变化而产生的一个机制。也就是上面的message响应式属性发生变化,才会从新计算计算属性reverseMessage。你直接去修改reverseMessage是不会有响应式的能力的。

如果你应要修改,可以把计算属性的set方法暴露出来,但是不建议

<div id="app">
    <p>原始字符串是:{{message}}</p>
    <p>计算后反转字符串:{{reverseMessage}}</p>
</div>

<script src="js/vue.min.js"></script>
<script>
    var vue = new Vue({
        el: "#app",
        data: {
            message: "Hello,Vue 无难事"
        },
        computed:{
            reverseMessage:{
                get(){
                    return this.message.split("").reverse().join('')
                },
                set(newv){
                    this.message = newv
                }
            }
        },
        methods: {

        }
    })
</script>

也就是说:computed默认是只读的,用于监听响应式数据的变化,而重新计算。

04、计算属性的缓存问题

复杂的表达式可以放到方法中实现,然后绑定表达式中调用方法即可。如下:

<div id="app">
    <p>原始字符串是:{{message}}</p>
    <p>计算后反转字符串:{{reverseMessage}}</p>
    <p>方法方式后反转字符串:{{reverseMessage2()}}</p>
</div>

<script src="js/vue.min.js"></script>
<script>
    var vue = new Vue({
        el: "#app",
        data: {
            message: "Hello,Vue 无难事"
        },
        computed:{
            reverseMessage(){
                console.log("computed")
                return this.message.split("").reverse().join('')
            }
        },
        methods: {
            reverseMessage2(){
                console.log("methods")
                return this.message.split("").reverse().join('')
            }    
        }
    })
	
    // 这里可以很清楚的看到,不会去执行计算
    let msg = vue.reverseMessage
    // 这里会再次执行方法
    msg = vue.reverseMessage2();

</script>
  • computed说明定义的属性拥有缓存的能力,为什么要提供缓存,假设有一个性能开销很大的计算属性A,它需要遍历一个巨大的数组并做大量的计算,然后可能还有其他的计算属性依赖于A。如果没有缓存,讲不可避免地多次执行A的getter方法。
  • 如果你的数据量很小,也不希望提升这点性能,可以完全使用方法来替代计算属性。
  • computed底层其实还是围绕着响应式数据进行处理,它其实就是响应式数据的再加工的过程。未来如果响应式属性发送了变化,computed属性会重新计算。
  • computed默认是只读,如果你想要更改计算属性,自己暴露set方法即可

05、时钟案例

在插值表达式中使用js表达式是非常方便的,而且也经常被用到。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vuejs测试</title>
</head>
<body>
<div id="app">
    <h2>
        当前时间是:{{birth}}
    </h2>
</div>
<script src="node_modules/vue/dist/vue.js"></script>
<script>
    var app = new Vue({
        el:"#app",//el即element,要渲染的页面元素
        data: {
            birthday:1429032123201
        },
        computed: {
            // 1:计算属性 可以当做属性直接使用。不需要定义切记
            birth() {
                // 2:获取当前时间
                const date = new Date(this.birthday);
                // 3: 日期格式化日志,返回进行回显页面
                return dateFormat("yyyy-MM-dd HH:mm:ss",date);
            }
        },
        // 生命周期函数
        created() {
            // 4:每隔1秒执行一次时间获取
            setInterval(()=>{
                this.birthday = new Date().getTime();
            },1000);
        }
    });


    // 日期格式化函数
    function dateFormat(fmt, date) {
        let ret;
        const opt = {
            "y+": date.getFullYear().toString(),        // 年
            "m+": (date.getMonth() + 1).toString(),     // 月
            "d+": date.getDate().toString(),            // 日
            "H+": date.getHours().toString(),           // 时
            "M+": date.getMinutes().toString(),         // 分
            "s+": date.getSeconds().toString()          // 秒
            // 有其他格式化字符需求可以继续添加,必须转化成字符串
        };
        for (let k in opt) {
            ret = new RegExp("(" + k + ")").exec(fmt);
            if (ret) {
                fmt = fmt.replace(ret[1], (ret[1].length == 1) ? (opt[k]) : (opt[k].padStart(ret[1].length, "0")))
            };
        };
        return fmt;
    }
</script>
</body>
</html>

计算属性本质就是方法,但是一定要返回数据。然后页面渲染时,可以把这个方法当成一个变量来使用。

效果:

06、小结

  • 在开发中,如果你发现在插值表达式中需要进行计算。你可以考虑用计算属性来完成。

  • 你把计算属性相当于定义一个变量来接受一个函数的计算返回的值。如下理解

    function computed(){
    	return "xxxx"
    }
    var reverseMessage  = computed();
    

10、Vuejs监控属性:watch

01、概述

在vue中还提供了一个非常通用的方式来观察和相应实例上的数据变动:监听器。当有一些数据需要随着它自身数据变化而变动时。就可以使用监听器。怎么听起来好像和计算属性的作用差不多。从功能上来说是的。但是两者还是存在很大的差别。

  • 因为computed是一个多对一关系,而watch更多是一对一关系。
  • computed是监听响应式多个响应式属性数据的变化,watch是监听响应式属性自身的变化而得到另外一个结果。
  • watch更多是一种监听自身 的变化,然后得到一个结果,而computed注重的是计算能力。也就是说watch可以把你监听的属性进行整容和改头换面。只能一个个监听。而computed就是可以监听多个响应式属性,可以把它们一起改头换面。

02、使用监听器watch

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>计算属性computed</title>
</head>

<body>

    <div id="app">
        <p>千米:<input type="text" v-model="kilometers"></p>
        <p>米:<input type="text" v-model="meters"></p>
    </div>

    <script src="js/vue.min.js"></script>
    <script>
        var vue = new Vue({
            el: "#app",
            data: {
                kilometers:0,
                meters:0
            },
            watch:{
                kilometers(val){
                    this.meters = val*1000
                },
                meters(newval,oleval){
                    this.kilometers = newval / 1000
                }
            },
            methods: {
                
            }
        })
    </script>

</body>

</html>

03、监听器的妙用,数据加载中

如果在开发中,一个数组初始化是异步执行和处理的,如果耗时太长,我们可以增加动画效果的方式,进行处理。

<div id="app">
    <h1>监听器的妙用</h1>
<div>{{loadingresult}}</div>
</div>

<script src="js/vue.min.js"></script>
<script>
    var vue = new Vue({
        el: "#app",
        data: {
            loadingresult:"",
            resultNum:[]
        },
        watch:{
            resultNum:{
                immediate:true,
                handler(newval,oldval){    
                    this.loadingresult = "请稍等,数据加载中..."
                    if(newval!=null && newval.length > 0){
                        this.loadingresult = "";
                    }
                }
            }
        },
        created(){
            setTimeout(() => {
                this.resultNum.push(1)
            }, 3000);
        },
        methods: {

        }
    })
</script>

04、对象的深度监听和立即加载

监听对象默认情况下。一定要数据发生变化才会触发。如果想初始化的时候就立即触发一次。可以使用:immediate:true。如果监听对象属性的变化,就必须使用:deep:true,如下:

<div id="app">
    <h1>判断年龄</h1>
    <input type="text" v-model="person.age">
    <div>{{loadingresult}}</div>
</div>

<script src="js/vue.min.js"></script>
<script>
    var vue = new Vue({
        el: "#app",
        data: {
            loadingresult:"",
            person:{
                name:"feige",
                age:10
            }
        },
        watch:{
            // person:{
            //     deep:true,
            //     immediate:true,
            //     handler(val,oldval){
            //         if(val.age >= 10){
            //             this.loadingresult = "已成年"
            //         }else{
            //             this.loadingresult = "未成年"
            //         }
            //     }
            // }

            "person.age":function(val,oldval){
                if(val >= 10){
                    this.loadingresult = "已成年"
                }else{
                    this.loadingresult = "未成年"
                }
            }
        },
        created(){

        },
        methods: {

        }
    })
</script>

监控

watch可以让我们监控一个值的变化。从而做出相应的反应。

示例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vuejs测试</title>
</head>
<body>
<div id="app">
    <input v-model="message">
</div>
<script src="node_modules/vue/dist/vue.js"></script>
<script>
    var app = new Vue({
        el:"#app",//el即element,要渲染的页面元素
        data: {
            message:"hello vue"
        },
        watch:{
            message(newValue, oldValue){
                console.log("新值:" + newValue + ";旧值:" + oldValue);
            }
        }
    });
</script>

</body>
</html>

效果:

深度监控

如果监控的是一个对象,需要进行深度监控,才能监控到对象中属性的变化,例如:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vuejs测试</title>
</head>
<body>
<div id="app">
   {{message}}
   {{this.coptions}}
     <button @click="changeBg">点我改变背景颜色</button>
</div>
<script src="node_modules/vue/dist/vue.js"></script>
<script>
    var app = new Vue({
        el:"#app",//el即element,要渲染的页面元素
        data: {
            message:"hello vue",
            coptions:{background:111111,size:12}
        },
        watch:{

            message(newValue, oldValue){
                console.log("新值:" + newValue + ";旧值:" + oldValue);
            },

            coptions: {
                //开启深度监控,可以监控到对象属性值的变化
                deep: true,
                //监控的处理方法
                handler(obj){
                    console.log("name = " + obj.background + ", age=" + obj.size);
                    document.body.style.background = "#"+obj.background;
                }
            }
            
        },
        methods:{
            changeBg(){
                this.message = "hi vue";
                this.coptions.background++;
            }
        }

    });
</script>

</body>
</html>

变化:

  • 以前定义监控时,person是一个函数,现在改成了对象,并且要指定两个属性:
    • deep:代表深度监控,不仅监控person变化,也监控person中属性变化
    • handler:就是以前的监控处理函数

效果:

05、小结

watch顾名思义,用于监听数据变化,其中可以监听的数据来源有三部分:props、data、computed内的数据;watch提供两个参数(newValue,oldValue),第一个参数是新值,第二个参数保存旧值;

computed用于处理复杂的逻辑运算,主要和methods储存方法来进行区分;methods储存方法,,computed储存需要处理的数据值;methods每次都会调用,computed有缓存机制,只有改变时才执行,性能更佳;

  1. computed 属性的结果会被缓存,除非依赖的响应式属性变化才会重新计算。主要当作属性来使用;
  2. methods 方法表示一个具体的操作,主要书写业务逻辑;
  3. watch 一个对象,键是需要观察的表达式,值是对应回调函数。主要用来监听某些特定数据的变化,从而进行某些具体的业务逻辑操作;可以看作是 computed 和 methods 的结合体;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值