Vue基础

Thursday, August 29, 2019

Vue 基础

计算属性,侦听器,方法

方法在每次渲染时都会重新加载,而计算属性和侦听器都是在监听的属性发生变化时再开始执行,在计算属性和侦听器都可用的情况下,使用计算属性,因为代码量少。

计算属性中,默认的return是get方法方法,但也可以手动添加set方法

class和style的绑定,vue中使用v-bind绑定style和class时,不仅可以使用字符串,还可以使用数组和对象。

class若绑定的是对象,则判断对象键值的true/flase(如果值是用data数据表示,若没有设置具体布尔值,默认存在则为true),绑定为数组时,则绑定的data数据键值的属性值,可绑定多个。

style若绑定时对象,则类似css写法,键值(样式名),属性(数据),如果遇到类似font-size这种写法,需要用驼峰写法代替(fontSize),绑定数组则可以在数组中添加多个对象。

v-if后可以跟v-if-else(v-if-else=“show===‘b’”)和v-else(三者需要在连续行)。

vue为提高性能,会复用标签,如果想标签独立需要加入不同的key值,key不推荐使用index,应该使用id。

v-for列表渲染中,如果渲染的是数组则有(item,index),如果是对象则有(item,键值,数据)。

如果想要修改数组,有三种方法,1是使用变异方法(push,pull,shift,unshift,reserve,sort,splice),2是替换数组(因为数组属于对象的一种,是引用类型),使用set方法(Vue.set/vm.$set),Vue.set(vm.xxxlist,索引,添加/替换内容)。

修改对象则只有两种方法,一种是替换对象,一种是使用set方法,Vue.set(vm.xxxObject,键值,数据)。

对于某些标签(table,ul,ol,select等),里面包含的标签是有要求的,如table后是tbody然后是tr,此时如果想用组件替代tr,可以使用is,

子组件中,data必须是function,因为子组件可能被调用多次,每个子组件都应该有独立的data,而根实例只会被调用一次,所以可以是对象,function中return的属性实例的属性。

vue中想要操控dom元素,需要给元素加入ref属性进行注册,在普通DOM元素中加入ref=“注册名”,引用的就是元素,this.$refs.xxx.innerHTML可以获取内容。在子组件中加入ref=“注册名”,引用的将是子组件的实例,所以可以获取里面的属性,this.$refs.xxx.number。

vue中有单向数据流,即父组件可以向下传递数据,但子组件不能修改父组件的数据,所以子组件接收到父组件的数据后,可以在data中将其赋值给本组件定义的属性,然后使用自身的属性进行运算。

子组件中,可以通过事件触发向父组件传递值。

组件参数校验,在组件的props属性中,可以对传进的参数进行校验。

props:["content","message"]   // 只接收
props:{
	content:String,        // 希望content是String类型
	message:[String,Number]   // mes可以是S或者N类型
}
props:{
	content:[String,Number],  //同上
	message:{
		type:String,     // 希望类型是S
		require:false,     //该参数是否是必须的
		default:'default value'  //,如果未传入参数,使用该默认值
		validator:function(value){   //对传入字符串长度进行校验
			return (value.length > 5)
		}
	}
}

props特性指定义的属性,在组件中有对应的接收,反之则是非props特性,非props特性的属性值会显示在组件的dom上。

在组件中,直接绑定原生事件(如click)会无效,会被视为是自定义事件,需要子组件绑定事件向外触发,如果想直接使用原生事件,可以添加.native,即 @click.native="xxx"

非父子组件间传递值,使用bus/总线

<body>
    <div id="app">
        <test content="Apple"></test>
        <test content="Banana"></test>
    </div>
    <script>
        Vue.prototype.bus = new Vue()
        Vue.component("test", {
            props: ['content'],
            template: '<div @click="handleClick">{{selfContent}}</div>',
            data: function () {
                return {
                    selfContent: this.content
                }
            },
            methods: {
                handleClick: function () {
                    this.bus.$emit('change', this.selfContent)
                }
            },
            mounted: function () {
                let this_ = this;    // 该this作用域是当前组件实例
                this.bus.$on('change', function (mes) {  //此时的this是bus指向的Vue实例
                    this_.selfContent = mes;   
                })
            }
        })
        var vm = new Vue({
            el: "#app"
        })
    </script>
</body>

首先在Vue的原型上添加原型属性bus并且将它指向Vue的实例,在点击方法中,使用bus的vue实例中的$emit事件方法,触发事件并传递值,随后在mounted方法中,使用$on方法监听事件,事件触发后,执行函数。

(个人理解:因为emit和on都是在同一个实例中,所以值可以在该实例中传递,随后再将值赋到组件中)

插槽,在组件中想要插入dom元素必须使用插槽,否则元素会被忽略,插槽可以写入默认值,默认插槽(即组件中的dom元素没有slot属性)只有一个,可直接用使用,具名插槽(dom元素中有slot=“name"属性)可以有多个,在template中使用,template中只可以有一个根元素,所以需要使用一个外层div包裹。

作用域插槽

<body>
    <div id="root">
        <body-content>
            <template slot-scope="{scope}">
                <h1>{{scope.user.name}}</h1>
            </template>
        </body-content>
    </div>
    <script>
        Vue.component('body-content', {
            data: function () {
                return {
                    list: [1, 2, 4, 5],
                    user: {
                        name: 'Tom',
                        age: 18,
                        sex: 'Female'
                    }
                }
            },
            template: `<div>
                <slot :user=user></slot>
                </div>`
        })
        new Vue({
            el: "#root"
        })
    </script>

让插槽内容可以访问到组件中的数据,模板中的slot需要有包裹,在slot中传递的属性,将在template中的slot-scope中被接收。

在vue2.6中,slot-scope被废弃,使用v-slot:default=“xxx”取代,其中default指插槽名,如果只有默认插槽可以省略为v-slot(并且可以直接在组件名上使用),但如果有多个(具名插槽)以上则必须用完整的语法(在template标签使用)。

            <template v-slot:default="scope">
                <h1>{{scope.user.age}}</h1>
            </template>

动态组件,组件可以根据is提供的组件名进行动态转换。

<component is="组件名"></component>

v-once,将内容存放在内存中,多次复用可提高效率