Vue初学-第三天

计算属性

  • 计算属性指的是通过一系列运算之后,最终得到一个属性值
  • 这个动态计算出来的属性值可以被模板结构或methods方法使用
  • 特点
    • 虽然计算属性在声明的时候被定义为方法,但是计算属性的本质是一个属性
    • 计算属性会缓存计算的结果,只有计算属性依赖的数据变化时,才会重新进行运算
  • 这时你发现,其实将其定义成方法一样能实现这个功能,那他们有什么不一样
    • 两种方式的最终结果确实是完全相同的。
    • 不同的是计算属性是基于它们的响应式依赖进行缓存的。只在相关响应式依赖发生改变时它们才会重新求值。
    • 这就意味着只要 message 还没有发生改变,多次访问 reversedMessage 计算属性会立即返回之前的计算结果,而不必再次执行函数。
    • 相比之下,每当触发重新渲染时,调用方法将总会再次执行函数。
<div id="app">
        <!-- 这里写了一个简易的加法计算,当firstNum或secondNum任意一个值变化时,fullNum计算属性都会重新计算一次,然后将值返回 -->
        <input type="text" v-model="firstNum"> + <input type="text" v-model="secondNum"> = {{ fullNum }}
    </div>
    <script src="./js/vue.js"></script>
    <script>
        new Vue({
            el: "#app",
            data: {
                firstNum: 0,
                secondNum: 0
            },
            computed: {
                // 计算属性
                fullNum() {
                    // 将firstNum和secondNum转为数字类型然后相加并返回
                    return parseInt(this.firstNum) + parseInt(this.secondNum)
                }
            },
        })
    </script>

watch侦听器

  • watch侦听器允许开发者监视数据的变化,从而针对数据的变化做特定的操作
  • 其有俩个参数变化前的新值newVal变化前的旧值oldVal
    <div id="app">
        <input type="text" v-model="username">
    </div>
    <script>
        new Vue({
            el: "#app",
            data: {
                username: "穿山甲"
            },
            watch: {
                // 每当username数据发生变化,侦听器都会立马执行一次
                username(newVal, oldVal) {
                    console.log("旧的用户名:" + oldVal);
                    console.log("新的用户名:" + newVal);
                }
            },
        })
    </script>

image.png

  • immediate选项
    • 默认情况下,组件在初次加载完毕后不会调用watch侦听器。
    • 如果想让watch侦听器立即被调用,则需要使 用immediate选项
    <script>
        new Vue({
            ...
            watch: {
                username: {
                    handler(newVal, oldVal) {
                        ...
                    },
                    immediate: true
                }
            }
        })
    </script>

image.png

  • deep选项
    • 如果watch侦听的是一个对象,如果对象中的属性值发生了变化,则无法被监听到。此时需要使用deep选 项
    • 如果只想侦听该对象的一个属性,可以在命名时用对象.属性名
    <div id="app">
        <input type="text" v-model="name.username">
    </div>
    <script>
        new Vue({
            el: "#app",
            data: {
                name: {
                    username: "穿山甲"
                }
            },
            watch: {
                name: {
                    handler(newVal) {
                        //因为这里监听的是name对象,所以newVal也是name对象
                        console.log("我的代号:" + newVal.username);
                    },
                    deep: true
                }
            }
        })
    </script>
    <script>
        new Vue({
            ...
            watch: {
                //在这里只侦听了name对象里的username属性(虽然只有这个属性。但你可以把他当做有很多属性)
                'name.username': {
                    handler(newVal) {
                        //在这里newVal就是name.username
                        console.log("我的代号:" + newVal);
                    },
                    deep: true
                }
            }
        })
    </script>

image.png

Vue组件

  • 组件化开发
    • 组件化开发指的是:根据封装的思想,把页面上可重用的UI结构封装为组件,从而方便项目的开发和维护
    • vue中组件的后缀名是.vue
    • 每个vue组件由三个部分组成:
      • emplate -> 组件的模板结构
      • script -> 组件的 JavaScript 行为
      • style -> 组件的样式
    • 每个组件中必须包含template模板结构,而script行为和style样式是可选的组成部分
    • 但是,我们先用简单的练手,直接在html进行组件化也可以
      • 注意,在组件化中,data必须是一个函数,这样才能保证组件之间互不影响
    <div id="app">
         <!-- 这里直接用注册组件用的名字就能直接用了,真方便呢 -->
        <button-counter></button-counter>
    </div>
    <script src="./js/vue.js"></script>
    <script>
        Vue.component('button-counter', {
            data: function() {
                return {
                    count: 0
                }
            },
            template: `<button v-on:click="count++">
             你点我{{ count }}次了,还不快住手!!!
             </button>`
        })
        new Vue({
            el: "#app"
        })
    </script>

image.png

  • 组件化的优点
    • 复用性强
    • 互不干扰
    • new Vue接收相同的选项

image.png

image.png

  • 通过Prop向子组件传递数据
    • 你可以在组件上中的prop中注册的一些自定义的attribute当一个值传递给一个prop attribute的时候,它就变成了那个组件实例的一个property
    • 一个组件默认可以拥有任意数量的prop,任何值都可以传递给任何prop,也就是说,并不局限于父传子,兄弟互传,爷孙互传之类的都行
    • 我们可以像访问 data 中的值一样,访问prop里传来的值
    <div id="app">
        <!-- 一个经典的父传子案列 -->
        <father>
        </father>
    </div>
    <script>
        Vue.component('father', {
            // 这里定义一个father组件
            template: `
            <div class="father">
                // 在father组件中嵌套一个son组件,并给它绑定了一个father组件的name属性
                <son :name="name"></son>
            </div>
            `,
            data() {
                return {
                    name: "鸡汤来咯~~~"
                }
            }
        })

        Vue.component('son', {
            // 这里定义了一个son组件
            template: `
            <div class="son">
                <h3>子组件</h3>
                // 这里就将会展示father属性传过来的name值
                <p>{{ name }}</p>
            </div>
            `,
            data() {
                return {

                }
            },
            // 用props接收了father组件传来的name属性
            props: {
                // 接收参数的name不能有值,否则会报错
                name: ""
            }
        })
        new Vue({
            el: "#app"
        })
    </script>

image.png

  • 单个根元素

    • 在组件化中,每个组件必须只有一个根元素
    template:`
    <p>我是重庆军统</p>
    <span>和带日本双料特工</span>
    <a>代号:穿山甲</a>
    `
    
    • 这么写vue会给你报一个错,提示你只能有一个根元素

      image.png

    • 用一个盒子包起来就没问题了

    template: `
        <div>
            <p>这喝汤多是一件美事</p>
            <span>喝!为什么不喝!</span>
            <a>和我玩阴的是吧</a>
        </div>
        `
    

    image.png

  • 监听子组件事件

    • 子组件可以通过调用内建的 $emit 方法并传入事件名称来触发父组件的事件
    <div id="app">
        <text-run-father></text-run-father>
    </div>
    <script>
        Vue.component('text-run-father', {
            data: function() {
                return {
                    texts: [{
                        id: 1,
                        content: "你是谁?"
                    }, {
                        id: 2,
                        content: "别动我!"
                    }, {
                        id: 3,
                        content: "我要走了!!!"
                    }],
                    // 自定义一个属性,待会要用
                    fontLeft: 1
                }
            },
            template: `
            <div class="text-run-father">
                <!-- 这里给这个包裹着子组件的盒子一个绑定fontLeft值的左边距样式 -->
                <div :style="{ marginLeft: fontLeft + 'px' }">
                    <!-- 给子组件循环绑定texts列表里的数据 -->
                    <!-- 给子组件绑定一个run点击事件,每点击一次,左边距+10px -->
                    <text-run
                    v-for="text in texts"
                    :key="text.id"
                    :text="text"
                    @run="fontLeft += 10">
                    </text-run>
                </div>
            </div>
            `
        });
    
    ![image.png](https://img-blog.csdnimg.cn/img_convert/58f9400e438392bfc0bb5c0144d2990f.png)
        Vue.component('text-run', {
            template: `
            <div class="text-run">
                <h3>{{ text.content }}</h3>
                <!-- 在子组件这里调用$emit方法,使其每点击一次都能触发绑定的run事件 -->
                <button @click="$emit('run')">别点我!</button>
            </div>
            `,
            props: [
                'text'
            ]
    
        });
    
        var vm = new Vue({
            el: "#app"
        })
    </script>
    

image.png

今天就先学到这里啦,第三天结束

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值