• Vue官方文档笔记


    1、如何创建一个Vue实例对象?

    var vm = new Vue({
              el: "#app",  //标签id 或 标签类名
              data:{ //双向绑定的数据
                  message: "王大锤",
                  show: true,
                  arr: [
                      { name: "王大锤", age: 18 }, { name:"罗小虎", age: 19 }
                  ]
              }
          })

    当一个Vue实例(如上面的vm)被创建后,它将data对象里面的所有的属性加入到Vue的响应式系统中。当这些属性的值发生改变时,视图会产生“响应”, 即视图展示最新的数据。

    如何双向式绑定数据?用v-model来绑定数据,如:

    <input v-model="message" />

    2、if  else  如何实现?用v-if、v-else、v-else-if,如:

    <div v-if="show">show为true展示</div>
    <div v-else>show为false展示</div>

    3、for循环如何使用?

    • 不带索引,格式:v-for = "item  in  arr",如:
      <div v-for="item in arr">{{item.name}}---{{item.age}}</div>
    • 带索引,格式:v-for = "(item, index)  in  arr",如:
      <div v-for="(item, index) in arr">{{index}}--{{item.name}}</div>
    • for循环除了能对数组进行遍历,还能对对象进行遍历,遍历对象的属性,格式:v-for = "value  in  object"  /  v-for = "(value, name)  in  object"   /   v-for = "(value, name, index)  in  object"

    4、Vue实例创建后,data对象里面的所有属性都会加入到响应式系统中,当这些属性的值发生改变时,视图将会产生“响应”,如果不想被响应式系统追踪变化,如何操作?

      使用Object.freeze()方法可以处理不想被追踪的数据。

    5、如何知道当前Vue实例对象作用在哪个标签上?

      Vue实例.el 就是目标标签,如vm.el == document.getElementById("#app")。在实例里面,this.$el指向的也是目标标签。

    6、如果Vue实例中的data里面的属性值变化我们想及时知道,如何做?

      在watch方法里面增加对属性的监听,这样当属性的值进行变化时,watch里面回及时知道。比如想监听data里面message属性的值变化。

    //第一种方式
    vm.$watch('message', function(newValue, oldValue){
        //这个回调函数会在 ’vm.message‘ 改变后调用
    })
    //第二种方式,在Vue实例里面写
          new Vue({
              el: "#app",
              data: {
                  message: "hello",
                  //...
              },
              watch: {
                  message: function(newValue, oldValue){
                    //这个回调函数会在‘message'改变后调用
                  }
              }
          })

    7、为什么不能在Vue实例的选项属性或回调中使用箭头函数?
      比如类似于 created: ()=>{ console.log(this.message) },  或vm.$watch('a', newValue => this.myMethod())。

      因为箭头函数中并没有this, 如果你使用了箭头函数,然后箭头函数中又使用了this。为了找到这个this,当在当前箭头函数中找不到这个this时,系统会一直向上级词法作用域去查找,直至找到为止,所以会经常导致出现Uncaught  TypeError: Cannot  read  property  of  undefined  或  Uncaught  TypeErrorr:  this.myMethod  is  not  a  function  之类的错误。

    8、一个Vue实例,从创建到销毁,经历了哪些过程?也是说它的生命周期是怎样的?

      主要有8个步骤

      8.1  beforeCreate:  创建Vue实例,初始化实例的事件、injections(注射:一般是检查是否有父级信号注入,在这里可以接收对父级组件或父级属性的引用,与父级提供的provide属性相配合)、reactivity(反应性:初始化监听属性变化的方法,如watch)。

      8.2  created: 在实例进入created后,会判断它是否包含“el"option(选项)。如果没有的话,它会调用vm.$mount(el)这个方法,然后执行下一步;如果有的话,直接执行下一步。紧接着会判断是否含有”template"这个选项,如果有的话,它会把template解析成一个render函数。

      8.3  beforeMount:  在beforeMount阶段中,完成render(渲染),  vm.$el创建完成,并将渲染出来的内容挂载到DOM节点上。

      8.4  mounted:  在mounted阶段,进行数据请求 --> data数据更新  -->  然后视图重新渲染  -->  再数据变化  -->  再重新渲染等等循环往复操作。这个对数据进行变化的过程,其实还包含了beforeUpdate和updated两个周期函数。

      8.5  beforeDestroy:  当Vue实例需要被销毁时,执行beforeDestroy函数,再这里拆卸属性侦听器(watch)、子组件、事件监听器(method)等等。

      8.6  destroyed:  最后一步,销毁Vue实例,完成了它丰功伟绩的一生!

    这是官方给出的一张生命周期图:

    9、v-once是什么指令,有什么用?

      一次性插值,再html标签中添加v-once属性,表示标签里绑定的文本插值只会展示第一次加载的数据。后面如果那个数据更改了,这个标签里面的内容不会再进行更新。

    10、如果相比文本插值转成html标签(把绑定的数据转成html标签),如何操作?

      使用v-html属性,如:<div  v-html="customHtml"></div>

      注意动态渲染的任意HTML可能会非常危险,因为它很容易导致XSS攻击。请只对可信内容使用HTML插值,绝不要对用户提供的内容使用插值。

      

    11、对于在html标签中的插值使用双括号{{message}}来绑定数据,如果想把数据绑定在HTML标签中的属性上,如类名(.)、样式(style)、自定义属性等如何操作?

      一般格式为 v-bind:属性名 = "变量名",如:

    <div v-bind:class="myClass" v-bind:style="myStyle" v-bind:key="myKey"></div>

      绑定事件的格式为  v-on:事件类型 = "事件名",如:

    <input  v-on:click="showMsg"   v-on:focus="getFocus"   v-on:blur="getBlur" />

    12、对于表单标签的一些存在即为true的属性,如何让它们默认为false(比如复选框checkbox的checked属性,所有表单标签的disabled属性) ?

      比如: 

    <input type="checkbox" checked/> 
    <input type="checkbox" checked="true" /> 
    <input type="checkbox" checked="false"/>

      这三种写法的效果是一样的,即这些复选框一渲染出来就是默认选中状态,类似的disabled属性也是这个表现。

      那么如何让它们默认为false呢?用v-bind, 比如:

    <input type="checkbox" v-bind:checked="false"/> 
    <input v-bind:disabled="false"/>

    13、Vue模板语法除了绑定变量,还能绑定表达式,如:

    <div>{{number + 1}} , {{ok ? '展示':'隐藏'}} ,{{message.split('').reverse().join('')}}</div>

    14、v-bind和v-on的缩写方式:

      v-bind:  可以缩写成 :  

    <div v-bind:href="url" v-bind:class="myClass"></div>

    可以缩写成

    <div :href="url" :class="myClass"></div>

      v-on: 可以缩写成

    <input  v-on:focus="getFocus" v-on:click="clickMe"/>

    可以缩写成

    <input @focus="getFocus" @click="clickMe"/>

    15、模板内的表达式可以进行简单运算,如果在模板内进行复杂逻辑有什么后果?有什么替代方案?

      在模板中放入太多的逻辑会让模板过重且难以维护。因此,对于任何复杂逻辑,应该使用计算属性。如:

    <div id="example">
      <p>Original message: "{{ message }}"</p>
      <p>Computed reversed message: "{{ reversedMessage }}"</p>
    </div>
    var vm = new Vue({
      el: '#example',
      data: {
        message: 'Hello'
      },
      computed: {
        // 计算属性的 getter
        reversedMessage: function () {
          // `this` 指向 vm 实例
          return this.message.split('').reverse().join('')
        }
      }
    })

      我们可以像绑定普通属性一样在模板中绑定计算属性,普通属性和计算属性已经建立了依赖关系。当普通属性变化时,计算属性也会跟着更新。

      当然我们能够看出,使用计算属性实现的效果,使用方法也能达到同样的效果,比如:

    <p>Reversed message: "{{ reversedMessage() }}"</p>
    var vm = new Vue({
      el: '#example',
      data: {
        message: 'Hello'
      },
      methods: {
          reversedMessage: function () {
            return this.message.split('').reverse().join('')
          }
        }
    })    

      那么问题来了,既然使用计算属性和方法的效果是一样的,那么用哪个更好性能更高?

      这个要具体问题具体分析,看用在哪些场景下。计算属性是基于它们的响应式依赖进行缓存的,只有相关响应式依赖发生改变时他们才会重新求值。这就意味着只要message还没发生改变,多次访问reversedMessage计算属性会立即返回之前的计算结果,而不必再次执行函数。相比之下,每当触发重新渲染时,调用方法将总会再次执行函数。

      因此,根据实际情况是否需要缓存,来判断是使用计算属性,还是使用方法,让性能更高。

      另外,计算属性vs侦听属性的区别比较,在某种场景下:当有些数据需要随着其他数据的变动而变动时,通常更好的做法是使用计算属性,而不是命令式的watch回调。如:

      

    <div id="demo">{{ fullName }}</div>
    var vm = new Vue({
      el: '#demo',
      data: {
        firstName: 'Foo',
        lastName: 'Bar',
        fullName: 'Foo Bar'
      },
      watch: {
        firstName: function (val) {
          this.fullName = val + ' ' + this.lastName
        },
        lastName: function (val) {
          this.fullName = this.firstName + ' ' + val
        }
      }
    })

      上面的代码式命令式重复的。且看使用计算属性如何实现这个效果:

    var vm = new Vue({
      el: '#demo',
      data: {
        firstName: 'Foo',
        lastName: 'Bar'
      },
      computed: {
        fullName: function () {
          return this.firstName + ' ' + this.lastName
        }
      }
    })

      可以看出,在这种场景下,使用计算属性比侦听属性要好的多。

    16、给标签绑定类名和内联样式,有几种写法?

      主要有两种:对象语法和数组语法,看下面的例子:

    <div :class="{classOne: classObj.isOK, 'classTwo': classObj.isNO}">class的对象语法</div>
    <div :class="{'classOne': classObj.isNo, 'classTwo': classObj.isOK}">class的对象语法</div>
    <div class="classZero" :class="classObj2">class的对象语法</div>
    <div :class="classObj3">class的数组语法</div>
    <div :class="[classObj3[0], classObj3[1]]">class的数组语法</div>
    <div :style="{fontSize: styleObj.fontSize, border: styleObj['border-bottom']}">style的对象语法</div>
    <div :style="styleObj">style的对象语法</div>
    <div :style="[styleObj, styleObj2]">style的数组语法</div>
    data:{
        classObj: { isOK: true, isNO: false }, //class对象语法
        classObj2: { classOne: true, classTwo: true }, //class的对象语法2
        classObj3: ['classOne', 'classTwo'],   //class的数组语法
        styleObj: { fontSize: '50px', 'border-bottom': '8px dashed purple', color: 'red' }, //内联样式的对象语法
        styleObj2: { borderLeft: '3px solid red', 'border-right':'5px solid green' }, //内联样式的对象语法
    },

    最后这8个div渲染为:

    <div class="classOne">class的对象语法</div>
    <div class="classTwo">class的对象语法</div>
    <div class="classZero classOne classTwo">class的对象语法</div>
    <div class="classOne classTwo">class的数组语法</div>
    <div class="classOne classTwo">class的数组语法</div>
    <div style="font-size: 50px; border: 8px dashed purple; ">style的对象语法</div>
    <div style="font-size: 50px; border-bottom: 8px dashed purple; color: red">style的对象语法</div>
    <div style="font-size: 50px; border-bottom: 8px dashed purple; color: red; border-left: 3px solid red; border-right: 5px solid green;">style的数组语法</div>

    17、数组有很多方法,哪些方法能够被Vue侦听,哪些方法不能被侦听?

      数组的push、pop、shift、unshift、sort、rever、splice等方法的调用会改变原数组,因此能够被Vue侦听;

      而filter、concat、slice等方法调用不会被改变原数组,而总是返回一个新数组,因此这几个方法的调用不会被Vue侦听。所以对于filter、concat、slice如果也想被侦听,可以用新数组替换旧数组。

      另外对于数组的通过索引修改某一项的值,或者修改数组的长度,也不会被Vue侦听,比如:

    var vm = new Vue({
      data: {
        items: ['a', 'b', 'c']
      }
    })
    vm.items[1] = 'x' // 不是响应性的, 不会被Vue侦听
    vm.items.length = 2 // 不是响应性的,不会被侦听

      如果想被Vue侦听,则可以使用vm.$set,或Vue.set(vm.$set实例方法是全局方法Vue.set的一个别名),如下:

    // Vue.set
    Vue.set(vm.items, indexOfItem, newValue)
    vm.$set(vm.items, indexOfItem, newValue)
    // Array.prototype.splice
    vm.items.splice(indexOfItem, 1, newValue)
    
    //修改数组索引长度的方法
    vm.items.splice(newLength)

      另外对于已经创建的实例,Vue不允许动态添加根级别的响应式属性。但是可以使用Vue.set(object,  propertyName,  value)方法向嵌套对象添加响应式属性。

    18、调用事件时,如何传递原始DOM的事件对象event ?

      如果是非内联方法,方法中默认第一个参数就是event;对于内联事件方法,可以传$event表示原始DOM的事件对象,如:

    <input @focus="getFocus" @click="clickMe('你点我了', $event)"/>
    method: {
        getFocus: function(event){
            console.log(event);
        },
        clickMe: function(msg, event){
            console.log(msg, ',', event);
        }
    }

    19、事件修饰符合按键修饰符

      1、在Vue中如何调用preventDefault()和stopPropagation()等事件方法?

      尽管我们可以在方法中轻松实现这些,但更好的方式是:方法只是纯粹的数据逻辑,而不是去处理DOM事件细节。因此,Vue为v-on提供了事件修饰符。

    <!-- 阻止单击事件继续传播 -->
    <a v-on:click.stop="doThis"></a>
    
    <!-- 提交事件不再重载页面 -->
    <form v-on:submit.prevent="onSubmit"></form>
    
    <!-- 修饰符可以串联 -->
    <a v-on:click.stop.prevent="doThat"></a>
    
    <!-- 只有修饰符 -->
    <form v-on:submit.prevent></form>
    
    <!-- 添加事件监听器时使用事件捕获模式 -->
    <!-- 即内部元素触发的事件先在此处理,然后才交由内部元素进行处理 -->
    <div v-on:click.capture="doThis">...</div>
    
    <!-- 只当在 event.target 是当前元素自身时触发处理函数 -->
    <!-- 即事件不是从内部元素触发的 -->
    <div v-on:click.self="doThat">...</div>

      注意:使用修饰符时,顺序很重要:相应的代码会以同样的顺序产生。比如v-on:click.prevent.self会阻止所有的点击,而v-on:click.self.prevent只会阻止对元素自身的点击。

      2、按键修饰符

      如何对键盘某别特别按键进行监听,如著名的event.keyCode= 13表示对键盘enter按键的监听。

      Vue对常用的按键设置了别名,如:enter、tab、delete(捕获“删除”和“退格”键)、esc、space、up、down、left、right等,用法:  

    <!-- 只有在 `key` 是 `Enter` 时调用 `vm.submit()` -->
    <input v-on:keyup.enter="submit">

     你还可以通过全局config.keyCodes对象自定义按键修饰符别名:

    // 可以使用 `v-on:keyup.f1`
    Vue.config.keyCodes.f1 = 112

    20、组件,如何创建一个组件?组件复用要注意哪些地方?父级如何传递数据给子组件?子组件如何传递数据给父级?

         1、组件的创建,先看一个示例

    // 定义一个名为 button-counter 的新组件
    Vue.component('button-counter', {
      data: function () {
        return {
          count: 0
        }
      },
      template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>'
    })
    组件是可复用的Vue实例,且带有一个名字,上面这个列子中是<button-counter>。我们可以在一个通过new Value创建的Vue跟实例二中,把这个组件作为自定义元素来使用: 
    <div id="app">
      <button-counter></button-counter>
    </div>
    new Vue({ el: '#app' })

      因为组件也是Vue实例,所以它们和new Vue接收相同的选项,例如data、computed、watch、methods以及其他生命周期钩子等。仅有的例外是像el根实例独自拥有的属性。

      2、组件的复用注意点

        一个组件的data属性必须是一个函数,这个和根实例的data是一个对象稍有不同。这样做的原因是为了当组件在复用时,可以让每个组件实例的数据互不影响。

      3、父级如何向子组件传递数据?

        父级通过v-bind:key传递子组件需要的数据,子组件在props属性里面接收父级传递过来的数据。

      4、子组件修改数据后,如何传回给父级(或者说通知父级修改数据)

        父级和子组件约定好在父级调用子组件时注册一个事件v-on:方法名,子组件修改数据后,通过$emit('方法名', { //... })传递新数据给父级。

      3、4完整示例:

    <div>
        <tan-one-com v-bind:super-obj="myInfo"
                     v-on:change-name="updateName" v-on:change-age="updateAge"></tan-one-com>
        <tan-one-com v-bind:super-obj="myInfo"
                     v-on:change-name="updateName" v-on:change-age="updateAge"></tan-one-com>
    </div>
    //注册全局组件, 注册之后,每个Vue实例都可以使用
    Vue.component('tan-one-com',{
        //父级bind用驼峰,子组件用全小写;
        //父级bind用全小写,子组件用全小写;
        //父级bind用中杠线连接,子组件可用驼峰式
        props: ['superObj'],  //接收来自父级传递过来的数据
        data: function(){  //自定义属性,必须用函数。这是为了保证该组件在复用时,各组件实例数据互不影响
            return {
                count: 1
            };
        },
        methods: {
            inputName: function(event){
                console.log(event.target.value);
                //通知父级,传递最新值给父级
                this.$emit('change-name', { value: event.target.value });
            },
            inputAge: function(age){
                //传递最新值给父级
                this.$emit('change-age', { value: age });
            }
        },
        template: '<div>' +
                    '<div><button v-on:click="count+=1">点我加一:{{count}}</button></div>' +
                    '<div><input type="text" placeholder="请输入名字" v-model="superObj.name" v-on:input="inputName"/></div>' +
                    '<div><input type="text" placeholder="请输入年龄" v-model="superObj.age" v-on:input="inputAge($event.target.value)"/></div>' +
                  '</div>'
    })
    
    var vm = new Vue({
        el: "#app",
        data:{
            myInfo: { name: '', age: 18 },
        },
        methods: {
            updateName: function(event){
                this.myInfo.name = event.value;
            },
            updateAge: function(event){
                this.myInfo.age = event.value;
                console.log("event: ", event);
            }
        }
    });
    21、如何让父级在子组件中插入一些自定义标签?
      子组件开放一个接口,名为slot标签,然后如果父级想在子组件中插入自定义标签 ,最后将会插入到slot标签中。 
    <div>
        <tan-two-com>
            <h3>男儿何不带吴钩,收取关山五十州;</h3>
            <h1>请君暂上凌烟阁,若个书生万户侯。</h1>
        </tan-two-com>
    </div>
    //注册全局组件,父级如何在子组件中插入自定义标签
            Vue.component('tan-two-com', {
                template: '<div style="border: 5px dashed green;">' +
                            '<p>我是子组件,给父级开放一个入口,方便插入父级自定义标签,用slot标签来接收父级自定义标签</p>'+
                            '<slot></slot>'+
                            '<div>..........end.......</div>'+
                '</div>'
            })

    22、定义组件名的方式主要有两种,官方建议使用短横线分隔命名法(子组件通知父级的事件名也建议用kebab-case法命名)

      1、kebab-case:短横线分隔命名法。用短横线给组件命名时,在引用时也必须使用kebab-case, 例如
    Vue.component('my-component-name', { /* ... */ })
    <div><my-component-name></my-component-name></div>
      2、PascalCase: 首字母大写命名法。使用首字母大写给组件命名时,在引用时可以两种命名法都可以使用,也就是说<my-component-name>和<MyComponentName>都是可以接受的。注意:直接在DOM(即非字符串的模板)中使用时只有kebab-case是有效的

     
    官方推荐的一些命名规则:
    • 组件名命名用kebab-case命名
    • 父子级单向数据流:父级引用子组件时用kebab-case(短横线分隔法),子组件prop用驼峰式命名接收
    • 子组件通知父级事件命名用kebab-case,即父级引用子组件时是v-on:xxx-xxx,子组件通知父级时是$emit('xxx-xxx', )
     

    测试示例:https://github.com/xiaotanit/Tan_HtmlDemo/tree/master/VueDemo

  • 相关阅读:
    迭代器
    【转】javascript中this的四种用法
    【转】CSS(10)盒子模型
    【转】深入理解JVM—JVM内存模型
    【转】深入JVM系列(一)之内存模型与内存分配
    【转】[译]深入理解JVM
    【转】C#中virtual和abstract的区别
    【转】面向对象设计的SOLID原则
    【转】Building a RESTful Web Service
    【转】设计模式:简单工厂、工厂方法、抽象工厂之小结与区别
  • 原文地址:https://www.cnblogs.com/tandaxia/p/11613346.html
Copyright © 2020-2023  润新知