一、computed、watch、methods

1.vue实例中的计算属性选项

计算属性关键词: computed。

在一个计算属性里可以完成各种复杂的逻辑,包括运算、函数调用等,只要最终返回一个结果就可以。注意:computed定义的名称不能与data一样

<body>
<div id="example">
    <p>Original message: "{{ message }}"</p>
    <p>Computed reversed message: "{{ reversedMessage }}"</p>
</div>
</body>
<!--将vue引入到本地-->
<script src="js/vue.js"></script>
<script>
    var vm = new Vue({
        el: '#example',
        data: {
            message: 'Hello'
        },
        computed: {
        // 计算属性的 getter
            reversedMessage: function () {
        // `this` 指向 vm 实例
                return this.message.split('').reverse().join('')
            }
        }
    })
</script>

computed vs methods

我们可以使用 methods 来替代 computed,效果上两个都是一样的,但是 computed 是基于data的依赖缓存,只有相关依赖状态发生改变时会重新计算,页面重新渲染值不会变化。而使用 methods ,在重新渲染的时候,函数总会重新调用执行(即调用就执行)

<body>
<div id="example">
    <p>Original message: "{{ message }}"</p>
    <p>Computed reversed message: "{{ reversedMessage }}"</p>
    <p >Methods reversed message: "{{ reversedMessage2() }}"</p>
</div>
</body>
<!--将vue引入到本地-->
<script src="js/vue.js"></script>
<script>
    var vm = new Vue({
        el: '#example',
        data: {
            message: 'Hello'
        },
        computed: {
        // 计算属性的 getter
            reversedMessage: function () {
        // `this` 指向 vm 实例
                return this.message.split('').reverse().join('')
            }
        },
        //通过方法来惭怍属性
        methods:{
            reversedMessage2:function () {
                return this.message.split('').reverse().join('')
            }
        }
    })
</script>

2. watch

vue.js提供了一个方法$watch(也存在缓存机制,但是没computed简洁),用于观察Vue实例上的数据变动。更好的办法是使用计算属性而不是一个命令式的$watch回调。

说白了$watch这货就是观察一个值的变化,观察的这个值一变化的话,那么就执行function里面的语句。数据变化时执行异步或开销较大的操作

watch是在vue实例对象中观测数据的变化;$watch是通过实例对象调用观测数据。

<div id="example">
    firstName:<input type="text" name="li"  v-model="firstName">
             <br>
    lastName:<input type="text" name="fei"  v-model="lastName">
    <p>fullName: {{fullName}}</p>
</div>
</body>
<!--将vue引入到本地-->
<script src="js/vue.js"></script>
<script>
    var vm = new Vue({
        el: '#example',
        data: {
            firstName:'Foo',
            lastName:'Bar',
            fullName:''
        },
        computed: {
        // 计算属性的 getter
            reversedMessage: function () {
        // `this` 指向 vm 实例
                return this.message.split('').reverse().join('')
            }
        },
        //通过方法来惭怍属性
        methods:{
            reversedMessage2:function () {
                return this.message.split('').reverse().join('')
            }
        },
//        watch: {
//             firstName: function (val) {
//                 this.fullName = val + ' ' + this.lastName
//             },
//            lastName: function (val) {
//                this.fullName = this.firstName + ' ' + val
//            }
//        }
    });
    vm.$watch('lastName',function (val) {
        this.fullName = val+' '+this.lastName;
    });
    vm.$watch('firstName',function (val) {
        this.fullName = this.firstName+' '+val;
    })
</script>

1.1 computed

    1.是计算值
    2.具有缓存性,页面重新渲染值不会变化,计算属性会立即返回之前的计算结果,而不必再次执行函数(只有当依赖数据发生改变才会重新计算)
    3.不支持异步,当computed内有异步操作时无效,无法监听数据的变化

    4.不支持箭头函数

        理由是箭头函数绑定了父级作用域的上下文,所以 this 将不会按照期望指向 Vue 实例,我们这里需要挂载到vm上,使用箭头函数打印this,发现是undefined。
        箭头函数的this是定义时就固定的,不能改变或者重新绑定;而普通函数的this,是指向运行时所在的作用域,所以是可以改变或重新绑定。

2.2 watch

    1.是观察的动作

    2.无缓存性,页面重新渲染时值不变化也会执行(值改变则直接触发)

    3.支持异步

    4.监听数据必须是 data 中声明过或者父组件传递过来的props中的数据以及挂载到vm上的数据(computed)

    5.不支持箭头函数

        理由是箭头函数绑定了父级作用域的上下文,所以 this 将不会按照期望指向 Vue 实例,我们这里需要挂载到vm上。

2.3 methods

    1.是函数

    2.无缓存性,页面重新渲染会被重新调用

    3.支持异步

    4.不支持箭头函数

        理由是箭头函数绑定了父级作用域的上下文,所以 this 将不会按照期望指向 Vue 实例,我们这里需要挂载到vm上。

下面还另外总结了几点关于 computed 、watch 和 methods 的差异:

  1. computed 是计算一个新的属性,并将该属性挂载到 vm(Vue 实例)上,而 watch 是监听已存在且已挂载到 vm 上的数据,所以用 watch 同样可以监听 computed 计算属性的变化(其它还有 dataprops
  2. computed 本质是一个惰性求值的观察者,具有缓存性,只有当依赖变化后,第一次访问 computed 属性,才会计算新的值,其他直接使用这个计算得到的值,而 watch 则是当数据发生变化便会调用执行函数
  3. 计算属性是有缓存的,只要相关依赖没有改变,多次访问计算属性得到的值是之前缓存的计算结果,不会多次执行
  4. methods 则是调用才更新
  5. 从使用场景上说,computed 适用一个数据被多个数据影响,而 watch 适用一个数据影响多个数据

二、vue 组件

2.Vue.js 组件

组件(Component)是 Vue.js 最强大的功能之一。

组件可以扩展 HTML 元素,封装可重用的代码。

组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树

注册一个全局组件语法格式如下:

Vue.component(tagName, options)

tagName 为组件名(标签名),options 为配置选项。注册后,我们可以使用以下方式来调用组件:

<tagName></tagName>
<div id="example">
    <!--使用我们自定义的组件-->
    <goheader></goheader>
</div>
</body>
<!--将vue引入到本地-->
<script src="js/vue.js"></script>
<script>
//    注册一个全局组件
    Vue.component('goheader',{
        template:'<h2>自定义全局组件!</h2>'
    });
    var vm = new Vue({
        el: '#example',
        data: {
//            这里不能将全局组件中的数组定义在data中
//           meg:"自定义全局组件!"
        }
    })
</script>

局部组件

我们也可以在实例选项中注册局部组件,这样组件只能在这个实例中使用:

<div id="example">
    <!--使用我们自定义的组件-->
    <go-child></go-child>
</div>
</body>
<!--将vue引入到本地-->
<script src="js/vue.js"></script>
<script>
//    注册一个局部模板
    var divChild = {
        template:'<h2>自定义局部组件!</h2>'
    };
    var vm = new Vue({
        el: '#example',
        //注册组件的选型
        components:{
            //<go-child>只在父模板中使用
            'goChild':divChild
        }
    })
</script>

动态组件:(:is="组件名")

不改变路由的情况下切换不同的页面/组件

// 子组件占位符
<component :is="viewCom"></component>

vue-动态组件(:is=“组件名“)_muzidigbig的博客-CSDN博客_vue动态组件名

组件使用细节

1.组件is的用法

<ul><ol><table><select> 这样的元素里允许包含的元素有限制,而另一些像这样的元素只能出现在某些特定元素的内部。在自定义组件中使用这些受限制的元素时会导致一些问题,例如:

// 会展示不出我们的子组件my-row
<table>
  <my-row>...</my-row>
</table>

自定义组件 <my-row> 会被当作无效的内容,因此会导致错误的渲染结果。变通的方案是使用特殊的 is 特性:

<table>
  <tr is="my-row"></tr>
</table>

应当注意,如果使用来自以下来源之一的字符串模板,则没有这些限制:

  • <script type="text/x-template">
  • JavaScript 内联模板字符串
  • .vue 组件

因此,请尽可能使用字符串模板。

这就用到了本文的中心“is”,当我们使用<tr is="my-tr" v-for="(man,key) in mans" :man="man" :key="key"></tr>引入插件,而不是<my-tr></my-tr>时,一切就正常了。

2.cli中组件,data必须是函数,并且返回一个对象,在对象内部保存数据

vue组件中data必须是一个函数的原因_muzidigbig的博客-CSDN博客

理解这点之后,再理解js的原型链:  

var MyComponent = function() {}
MyComponent.prototype.data = { a: 1, b: 2,}
  // 上面是一个虚拟的组件构造器,真实的组件构造器方法很多  
var component1 = new MyComponent()
var component2 = new MyComponent()
// 上面实例化出来两个组件实例,也就是通过 MyComponent  调用,创建的两个实例
component1.data.a === component2.data.a // true
component1.data.b = 5
component2.data.b // 5 

  可以看到上面代码中最后三句,这就比较坑爹了,如果两个实例同时引用一个对象,那么当你修改其中一个属性的时候,另外一个实例也会跟着改。这怎么可以,两个实例应该有自己各自的域才对。所以,需要通过下面方法来进行处理:  

var MyComponent = function() {
    this.data = this.data()
}
MyComponent.prototype.data = function() { return { a: 1, b: 2, }  }  

这样每一个实例的data属性都是独立的,不会相互影响了。
3.组件,ref获取dom/子组件实例对象

ref被用来给元素或子组件注册引用信息。引用信息将会注册在父组件的 $refs对象上。如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向该子组件实例

通俗的讲,ref特性就是为元素或子组件赋予一个ID引用,通过this.$refs.refName来访问dom元素或子组件的实例对象

<p ref="p">Hello</p>
<children ref="children"></children>
this.$refs.p; // dom
this.$refs.children // 子组件实例

this.$refs介绍

this.$refs 是一个对象,持有当前组件中注册过 ref 特性的所有 DOM 元素和子组件实例对象

注意: $refs只有在组件渲染完成后才填充,在初始渲染的时候不能访问它们,并且它是非响应式的,因此不能用它在模板中做数据绑定。

若有不足请多多指教!希望给您带来帮助!

Logo

前往低代码交流专区

更多推荐