vue——计算属性、侦听属性、自定义指令、生命周期函数

一、计算属性 computed

  • 把computed中的方法当做属性使用,返回一个数据供使用
  • 会主动获取数据源data中的数据  不需要传参 只是一种程序处理
  • 计算属性就是处理数据源中的数据 然后用于渲染 同时监听计算属性中用到的数据源 然后把计算的结果缓存
<div id="eg1">
       <h1>methods------{{birth}},{{age1(birth)}}</h1>
        <h1>computed-----{{birth}},{{age}}</h1>
        <button @click="change">点击</button>
        <p>{{shuxing}}</p>
    </div>
    <script> 
        new Vue({
            el: "#eg1",
            data: {
                birth: "2001-04-16"
            },
            methods: {
                age1(str) {
                    return new Date().getFullYear() - new Date(str).getFullYear()
                },
                change() {
                    this.shuxing = 200
                }
            },
            computed: {
                //第一种写法:语法糖
                age() {
                    return new Date().getFullYear() - new Date(this.birth).getFullYear()
                },

                //第二种写法  把shuxing当属性看
                shuxing: {
                    //获取 取值
                    get() {
                        console.log("computed执行了")
                        return new Date().getFullYear() - new Date(this.birth).getFullYear() + "岁"
                    },
                    //设置 存值
                    set(val) {
                        console.log(val)
                        this.birth = `${2022-v}-02-03`
                    }
                }
            },
        })
    </script>

 结果显示:

计算属性和方法的区别:(面试题)

  • 计算属性会把使用到的data中的属性缓存起来,防止页面发生大量重复计算,提升运行效率。仅当计算属性中使用到的data中那部分数据变了才会重新调用计算属性刷新页面,否则直接使用缓存中的数据。
  • methods方法没有计算结果缓存起来,data任何数据发生改变,模板会重新取值渲染页面 ,方法都会被重新调用一遍
  • 方法常常是作用的事件使用,计算属性常常是动态计算结果时使用

补充:关于计算属性 函数什么情况下调用(面试题)

  • 计算属性使用时当做属性使用 
  • 计算属性设计时当做函数设计(就像es6中的属性) 
  • 当计算属性的函数中使用到的data中的数据发生变化时,计算属性就会重新执行并刷新UI 

           1.如果是修改了data中监听的某个的属性值 计算属性就会运行 
           2.如果是修改了data中监听的某个属性值内部的数据,计算属性就不会重新运行 
        比如:计算属性使用的是data中的一个数组,某个交互把数组内部的某个下标的值改了,但是这个数 组没有改变,就不会触发计算属性 
           解决办法1:把修改后的数组重新赋值给data,让引用发生变化,来触发计算属性 
           解决办法2:赋值 JSON.parse(JSON.stringfy(data)) 

 二、属性侦听器 watch

  • watch:{x(){}}中的方法名必须跟要监听的data中的属性名一样,才代表监听指定属性
  • 当侦听器监听的属性发生变化时,就会调用watch中对应的方法
  • 侦听器属性比计算属性计算效率消耗大
 <div id="eg1">
        <p>{{n}}</p>
        <button @click="change1">修改n</button>
        <button @click="change2">修改obj</button>
        <p>{{obj.age}}</p>
    </div>
    <script>
        new Vue({
            el: "#eg1",
            data: {
                n: 100,
                obj:{age:20}
            },
            methods: {
                change1() {
                    this.n = 90
                },
                change2() {
                    //修改了引用数据内部的属性值,页面会重新渲染,但是侦听器属性不会触发 因为引用没有发生变化
                    this.obj.age = "21"
                    //只有修改了引用数据的引用 才会触发侦听器属性
                    this.obj={age:22}
                    //若想只修改引用数据的属性值也触发侦听器,必须深度监听
                }
            },
            watch: {
                n() {
                    console.log(1111)
                },
                // obj(){
                //     console.log("obj改变了")
                // },
                //深度监听 引用数据内部的属性值
                obj:{
                    deep:true,
                    handler:()=>{
                        console.log("obj改变了")
                    }
                }
            }
        })
    </script>

结果显示:

 计算属性、属性侦听器、方法、过滤器有什么区别?(面试题)

计算属性:会把计算的结果缓存起来,并监听计算过的数据源。如果监听的数据源发生改变就会重新计算(监听的属性没有发生变化 模板重新渲染 但直接取缓存中的计算结果)

方法:一般是提供给模板事件和其他方法(如钩子函数)使用,如果在模板中使用了方法,而且不是事件,只要模板中的渲染的任意数据源改变了,它都会重新调用

过滤器:用于数据渲染器的数据处理,除了用法与方法不一样 其他都一样。但是它没有被this劫持。

属性侦听器:只有侦听的属性发生变化时才会触发(deep:true 深度侦听,但消耗内存)

将以上函数分类的原因:为了业务更明显 功能更好调试

被this对象劫持的:方法、计算属性

三、自定义指令 directives

  • 指令:标签中v-开头的一种自定义的标签的属性 在vue运行后就具有封装好的功能 使用时非常简洁

除了默认设置的核心指令( v-model 和 v-show 等),Vue 也允许注册自定义指令。

在Vue里,代码复用的主要形式和抽象是组件。

有的情况下,仍然需要对纯 DOM 元素进行底层操作,这时候就会用到自定义指令 。

钩子函数

一个指令定义对象可以提供如下几个钩子函数 (均为可选):

  • bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。

  • inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。

  • update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 (详细的钩子函数参数见下)。

  • componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。

  • unbind:只调用一次,指令与元素解绑时调用。

钩子函数参数

指令钩子函数会被传入以下参数:

  • el:指令所绑定的元素,可以用来直接操作 DOM。
  • binding:一个对象,包含以下 property:
    • name:指令名,不包括 v- 前缀。
    • value:指令的绑定值,例如:v-my-directive="1 + 1" 中,绑定值为 2
    • oldValue:指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
    • expression:字符串形式的指令表达式。例如 v-my-directive="1 + 1" 中,表达式为 "1 + 1"
    • arg:传给指令的参数,可选。例如 v-my-directive:foo 中,参数为 "foo"
    • modifiers:一个包含修饰符的对象。例如:v-my-directive.foo.bar 中,修饰符对象为 { foo: true, bar: true }
  • vnode:Vue 编译生成的虚拟节点。移步 VNode API 来了解更多详情。
  • oldVnode:上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。
<div id="eg1">
        <p v-html="msg"></p>
        <input type="text" v-model="count">
        <div v-red>字体变红</div>
        <div v-color="'pink'">字体变粉</div>
        <div v-color="mycolor">data中的变量</div>
        <input type="text" v-focus value="获取光标">
    </div>
    <script>
        new Vue({
            el: "#eg1",
            data: {
                msg: "<h1>案例1</h1>",
                count: 200,
                mycolor: "blue"
            },
            directives: {
                red: {
                    inserted(el) {
                        //el:绑定这个指令的节点对象:DOM操作
                        console.log(el)
                        el.style.color = "red"
                    }
                },
                color: {
                    //inserted:指令插入节点以后  钩子函数
                    inserted(el, option) {
                        console.log(el, option.value)
                        el.style.color = option.value

                    }
                },
                focus: {
                    inserted(el) {
                        el.focus()
                    }
                }
            }
        })
    </script>

 结果显示:

四、生命周期函数

生命周期函数(钩子函数):

  • 钩子:c语言中有一类系统回调的函数执行业务
  • 在某种条件成立时,系统会去调用vue中设定的函数 这些函数叫做生命周期函数
  • 当vm实例在整个运行的过程中,会在不同的时期去执行特定的函数 这些函数叫做生命周期函数

vue组件中8个:当前vm实例从创建到销毁的过程中会调用的函数:

  1. beforeCreate() 
  2. created() 
  3. beforeMount() 
  4. mounted()      //以上4个钩子都只执行一次
  5. beforeUpdate() 
  6. updated()      //以上2个第一次构建不会调用,以后每次data被更新了才会调用
  7. beforeDestroy()
  8. destroyed() 只执行一次
  •  beforeCreate() 

  • 此函数由系统调用
  • 函数在vm创建完成之前运行时,vm正在创建中:劫持data,methods  所以此时this对象中还不能访问到数据

 能否网络请求数据 设置到数据源中?

  • 可以做网络请求 因为函数在运行时XMLHttpRuquest是可以访问做AJAX请求
  • 不能设置到数据源中 因为此时this还在创建

在此函数中可以做:

  •  预加载:网页中同源加载的优化(同一个页面中的img script等 src属性请求资源)  将资源请求下来 存着 但不渲染
  • 提前配置
  • 只要不是用于页面渲染的都可以
  • created() 

  • 在vm对象创建完毕后挂载到DOM树前触发钩子(调用函数) 
  • 即此函数可以操作this对象 但不能操作DOM

能否网络请求数据 设置到数据源中?

  • 可以做网络请求 因为函数在运行时XMLHttpRuquest是可以访问做AJAX请求
  • 可以设置到数据源中 因为此时this已经创建完毕

在此函数中可以做:

  • 请求首屏数据
  • beforeMount() 

  • 挂载/渲染前的操作
  • vm对象创建完毕后挂载到DOM树前调用函数
  • 可以做网络请求 可以设置到数据源中 可以操作this对象 无法操作DOM
  • mounted()

  • vm已经挂载到页面上 DOM渲染已经完成
  • 请求首屏数据
  • 网络请求时 页面已经出来了 请求后数据驱动页面 局部刷新页面
  • beforeUpdate() 

(数据源已经更新 )在页面重新渲染前 触发的钩子

数据更新时调用,发生在虚拟 DOM 打补丁之前。

这里适合在更新之前访问现有的 DOM,比如手动移除已添加的事件监听器,该函数在服务器端渲染期间不被调用,因为只有初次渲染会在服务端进行

此函数中不能网络请求数据更新数据源 会导致死循环

  • updated() 

  • 页面已经重新渲染后 触发钩子
  • 此函数中不能网络请求数据更新数据源 会导致死循环
  • beforeDestroy()

  • vm实例对象销毁之前 触发的函数 此时this还存在
  • 可以做最后的操作 如 保存用户的行为配置文件
  • destroyed() 

  • vm对象销毁后触发的函数 无法操作this
  • 调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监 听器会被移除,所有的子实例也会被销毁
  • 清除当前组件中的计时器  把body的滚动条滚动到顶部

五、组件

  • 是可复用的 Vue 实例
  • 主要用于开发中 具有相同特征不同数据的模块 把它集成为一个组件 供重复利用

注册组件的注意事项:

  • 注册组件时,组件名不能与系统标签同名
  • 组件template模板中 只能有一个根元素  
  • 注册时用驼峰命名法,使用时用连字符 如<MyBox>  <==>  <my-box>
 <div id="eg1">
        <Box></Box>
        <Nav1></Nav1>
        <my-box></my-box>
 </div>
 <script type="module">
        //第三种:import 导入
        import MyBox from "./components/MyBox.js"
        //第一种:写在全局 components中引用变量名
        let cpt1={
                    template: `<div>
                                  <h3>我是全局声明的</h3>
                               </div>`
                }
        new Vue({
            el: "#eg1",
            data: {},
            methods: {},
            components: {
                //注册组件
                //第一种:写在全局
                Box:cpt1,
                //第二种:直接注册
                Nav1:{
                    template:`<div>
                                <h3>我是在components中直接注册的</h3>
                              </div>`,
                    data:function(){
                            return {msg:"msg"}
                              },
                    methods:{
                        fn(){console.log("组件的全部方法")}
                    }
                },
                //第三种:import 导入
                MyBox
            },
        })
    </script>

结果显示:

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

哈哈ha~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值