zoukankan      html  css  js  c++  java
  • Vue学习笔记-2

    前言

    本文非vue教程,仅为学习vue过程中的个人理解与笔记,有说的不正确的地方欢迎指正讨论

    1、computed计算属性函数中不能使用vm变量

    在计算属性的函数中,不能使用Vue构造函数返回的vm变量,因为此时vm还未返回,依然处于Vue内部构造函数过程中,遂只能使用this来代替vm。
    若要使用typescript,可使用以下方法来实现代码智能感知

    vm = vm || this;
    

    另:其他不能用vm变量,只能使用this变量的地方,都可以通过此方法来获得Typescript的智能感知和代码语法检查,比如mounted生命周期系列函数等。
    不过模板里的vm引用Typescript无能为力,只能等待ts支持vue的jsx语法了╮(╯_╰)╭

    2、计算属性中不能引用其他计算属性?

    官方教程中没有找到相关说明(应该是我没找到),从使用角度而言大致可以总结出以下结论:

    1. 计算属性必须引用(依赖)非计算属性或固定值。(见demo1)
    2. 计算属性若引用(依赖)其他计算属性,则被引用的计算属性必须引用非计算属性或固定值(见demo2)
    3. 计算属性可循环依赖,但最终依赖链上的最上游的计算属性,必须引用非计算属性或固定值。

    DEMO1:官方标准用法,计算属性引用非计算属性:

    var vm = new Vue({
        el: "#app",
        data: {
            dataVal: "xxcanghai"
        },
        computed: {
            computedVal1: function () {
                //标准用法,计算属性引用非计算属性
                return this.dataVal + "_1";//输出 xxcanghai_1
            }
        }
    });
    

    DEMO2:计算属性链式依赖其他计算属性,则依赖链头必须引用非计算属性或固定值

    var vm = new Vue({
        el: "#app",
        data: {
            dataVal: "xxcanghai"
        },
        computed: {
            computedVal1: function () {
                return this.dataVal + "_1";
            },
            computedVal2: function () {
                //合法,计算属性computedVal2引用computedVal1,computedVal1再引用dataVal
                return this.computedVal1 + "_2";//输出 xxcanghai_1_2
            }
        }
    });
    

    原因很容易理解,如果最终没有引用或依赖任何非计算属性,那么计算属性在计算时会陷入死循环

    3、vue2.0中若使用组件嵌套,则在父组件执行$forceUpdate()之前模板中$children为空数组

    触发这个问题有以下几个前提:

    1. vue版本为2.0版本,1.0无此问题。
    2. 使用组件嵌套,在父组件的模板中访问$children变量
    3. 在渲染完成后没有再将$children变量写入过父组件的data变量(或其他vm数据)
      就会触发此问题。
    <!--父组件HTML模板-->
    <div id="app">
       <div>{{$children.length}}</div> <!--此处显示0,应该为3-->
       <child></child>
       <child></child>
       <child></child>
    </div>
    
    //子组件代码
    Vue.component("child", {
        template: "<div>child</div>",
    });
    
    //父组件声明
    new Vue({
        el: "#app",
    });
    

    如下图:

    解决方案1:使用$forceUpdate()

    注册父组件的mounted方法,执行$forceUpdate()

    <div id="app">
       <div>{{$children.length}}</div>
       <child></child>
       <child></child>
       <child></child>
    </div>
    
    Vue.component("child", {
        template: "<div>child</div>",
    });
    
    new Vue({
        el: "#app",
        mounted: function () {
            this.$forceUpdate();//强制重新绘制
        }
    });
    

    $children正确了:

    解决方案2:使用vm的变量代替$children

    注册父组件的mounted方法,将$children赋值给自定义的vm的变量。
    同时模板中使用自定义的变量来代替默认的$children

    <div id="app">
       <div>{{child.length}}</div> <!--使用自定义的child对象-->
       <child></child>
       <child></child>
       <child></child>
    </div>
    
    Vue.component("child", {
        template: "<div>child</div>",
    });
    
    var vm = new Vue({
        el: "#app",
        data: {
            child: []
        },
        mounted: function () {
            this.child = this.$children;//手动将$children对象赋值给自定义child变量
        }
    });
    

    至于导致此问题的原因只能通过阅读vue2.0版本的源码才能了解了。

    4、若父组件的template或render函数中无引用slot元素,则$children恒等于空数组

    此问题关联上面第3个问题。
    触发此问题的前提:

    1. vue2.0版本
    2. 父组件和子组件都直接写在调用方模板中
    3. 在模板中访问$children变量
    4. 已经解决在上述问题3中强制刷新的问题

    复现代码:

    <div id="app">
    	<!--子组件直接写在调用方的模板中-->
       <parent>
           <child></child>
           <child></child>
           <child></child>
       </parent>
    </div>
    
    //父组件
    Vue.component("parent", {
        template: "<p>parent child:{{$children.length}} </p>",//模板中无slot元素
        mounted(){
            this.$forceUpdate();
        }
    });
    Vue.component("child", {
        template: "<div>child</div>"
    });
    
    var vm = new Vue({
        el: "#app"
    });
    

    解决方案1:父组件模板包含slot元素

    在父组件的模板中加入slot元素。或在render函数中引用了this.$slots.default变量

    Vue.component("parent", {
        template: "<p>parent child:{{$children.length}} <slot></slot></p>",
        mounted(){
            this.$forceUpdate();
        }
    });
    

    解决方案2:在父组件模板中编写子组件定义

    此解决方案要修改此问题的复现第2要素,即子组件定义从调用方改为写到父组件的模板中也可解决此问题。

    <div id="app">
       <parent>
       </parent>
    </div>
    
    Vue.component("parent", {
    	//直接在父组件中写明调用子组件标签
        template: "<p>parent child:{{$children.length}}
                       <child></child>
                       <child></child>
                  </p>",
        mounted(){
            this.$forceUpdate();
        }
    });
    Vue.component("child", {
        template: "<div>child</div>",
    });
    
    var vm = new Vue({
        el: "#app",
        data: {
            child: []
        }
    });
    

    此方法虽然可以解决问题,但是有时我们直接把子组件写在调用方会更方便更利于理解,比如Tab与TabPage组件。
    如下Tab组件代码,可能更符合一般人的使用思维:

    <div id="app">
       <tab>
           <tab-page>Page1</tab-page>
           <tab-page>Page2</tab-page>
           <tab-page>Page3</tab-page>
       </tab>
    </div>
    

    相关笔记

    Vue学习笔记-1(http://www.cnblogs.com/xxcanghai/p/5849038.html)

    Vue学习笔记-2(http://www.cnblogs.com/xxcanghai/p/6098663.html)

  • 相关阅读:
    MySQL 索引优化
    [转]多列索引
    abstract class和interface有什么区别? [转]
    PM knowledge
    委托应用场景[摘]
    Web 服务描述语言工具 (Wsdl.exe)[FROM msdn]
    C# 四个基本技巧[转]
    What are database states? [forward]
    学做程序经理[摘]
    SET IDENTITY_INSERT 学习心得[转]
  • 原文地址:https://www.cnblogs.com/xxcanghai/p/6098663.html
Copyright © 2011-2022 走看看