最重要:

1、data:

  1)不渲染视图、不双向绑定的数据不放进data,在created中this.XXX = 定义即可;

  2)data中的对象和数组的改变:

    a、改变对象:

data() {
    return {
        kk: {
            a: 1
        }
    }
},
methods: {
    change() {
        this.kk.b = 2;    //通过直接赋值改变对象,不是响应式
        this.$set(this.kk, 'b', 2);    //用$set方法改变,是响应式
    }
}

     b、改变数组:

data() {
    return {
        ooo: [0, 1]
    }
},
methods: {
    change() {
        this.ooo[2] = 2;    //通过数组下标改变数组,不是响应式
        this.ooo.push(2);    //用push、splice等方法改变,是响应式(vue重写了这几种方法)
    }
}

2、.vue文件中this指向的内容:

  1)$attrs:是props的合集,只有自定义的属性才能取到 (透传,由上往下传递)

    index.vue:

<hello :tt="1234" msg="123"></hello>

    hello.vue:

<template>
    <div>111</div>
</template>

<script>
    export default {
        mounted() {
            console.log(this.$attrs);    //{ ttt: '1234', msg: '123' }
        }
    }
</script>

  2)$createElement:相当于render函数的h函数

  3)$el:当前div的DOM

  4)$refs:ref绑原生标签---->DOM,ref绑组件---->组件实例

    index.vue:

<hello v-for="v in 10" :key="v" ref="ddd"></hello>



this.$refs.ddd --->[10]    //10个hello组件,循环时可直接批量修改


this.$refs.ddd.forEach(x => {
    x.msg = 'hello';
});

    hello.vue:

<template>
    <div>{{ msg }}</div>     //循环10个hello
</template>


data() {
    return {
        msg: '111'
    }
}

   5)$parent:父级元素的实例(一般不用,也不要用)

  6)$listeners:与$attrs相对应,都是透传,是从下往上传递。eg:

index.vue:

<div>
    {{ abc }}  //默认显示1,点击hel.vue的button,改为888
    <hello :abc="abc" @click="_change"></hello>
</div>

data() {
    return {
        abc: 1
    }
},
methods: {
    _change(val) {
      this.abc = val;  
    }
}


hello.vue:

<hel v-bind="$attrs" v-on="$listeners">
</hel>


hel.vue: 

<div>
    <span>{{ $attrs.abc }}</span>       //默认显示1,点击button后变为888
    <button @click="_click"></button>
</div>


created() {
    console.log(this.$attrs);    //{ abc: '1'}
    console.log(this.$listeners);    //{ click: f }  index.vue的click事件
},
methods: {
    _click() {
        this.$emit('click', 888);    //点击调用index.vue的click事件
    }
}

3、$nextTick:解决mounted时,DOM没有完全渲染完的时间差(16ms)

mounted() {
    this.$nextTick().then(() => {
        ...//代码片段
    });
}

 4、计算属性、方法、watch比较:

  1)计算属性(computed):对数据的计算和过滤等一些简单的操作,有缓存(依赖没变、结果没变),可按照使用场景优先使用

    使用场景:多个params绑定,修改单个用computed

coputed: {
    params: {
        page: this.page,
        pageSize: this.pageSize
    }
}    //一个改,整个计算

  2)methods:不缓存,每次都运行

  3)watch:数据改变后,要调接口和进一步的操作

    使用场景:a、可以监听路由跳转的参数

watch: {
    $route(val) {
        ...//代码片段
    }
}

      b、监听嵌套对象深层的某个值:

data() {
    return {
        kk: {
            a: {
                b: {
                    c: 1
                }
            }
        }
    }
},

watch: {
    'kk.a.b.c': funtion(val) {
        ...//代码片段
    }
}

 5、key:为了更高效的复用

  vDOM:用js对象表达DOM,配合diff算法生成DOM

  1)包在中间的子节点复用,值会改变。eg:<span>3</span> ------> 5

  2)包在属性中的子节点复用,不会改变。eg:<img src="1.jpg" /> ------>不会改变,因为已经渲染了。

6、注册组件:

   (1)动态注册组件:

(1)
import hello from './hello';

components: { hello }


(2)
this.components('hello');


(3) table.config.js: 
import hello from 'hello';

render(h) {
    return h('hello', { ... })
}

  (2)全局注册:

Vue.component('hello');

7、props:父组件传递给子组件的数值

  (1)传递变量时前面需要加":",否则一律按字符串处理

<hello msg="true"></hello>    ----->msg为字符串"true"


<hello :msg="true"></hello>    ----->msg为布尔型数值true

  (2)布尔型的数值传递true值,可直接省略写:

<hello msg></hello>    ----->msg为布尔型数值true

  (3)props的值不允许直接修改,在子组件中需要修改,则需要重新定义一个变量去修改。

  (4)对一个 prop 进行“双向绑定”:加.sync修饰符。即在子组件也可以修改父组件prop传递的值

index.vue:

<hello :msg.sync="123"></hello>



hello.vue:

this.$emit('update:msg', '222');  

 

 

 

 

 

 

 

 

 

 

较重要:

1、模块化:精简、复用(按需调用)、防止变量污染

2、AMD、CMD、commonJS、esModule(es6):

  1)AMD:define(modules, callback):依赖前置、异步定义

  2)CMD:define():依赖就近,即用即返

  3)commonJS:require()引入(图片src引入或判断引入),exports导出、运行时加载。例:

    index.js:

var bar = require('./bar.js');

function foo() {
    return bar.bar();
}

    bar.js:

exports.bar = function() {
    console.log('1111');
}

  4)ES Module:在script头部用import引入,export导出、编译时加载。例:

    index.js:

'use strict'
import bar, {foo} from './bar.js';

bar();    // 11

foo();    // 112 

    bar.js:

'use strict';
export default function bar () {
    console.log('11');
};
export function foo () {
    console.log('112');
}

3、vue.js包括编译和运行两部分:

  1)编译:将template代码片段转成AST(抽象语法树)---->优化AST(标记静态部分不再渲染)---->AST生成render函数。

  2)运行:render函数 ----> vDOM ----> DOM

  mark:由于webpack的vue-loader做了预编译,因此不需要vue.js做编译,因此用vue.runtime.js(仅运行版本的vue.js)。需要做的几处改变:

    1)main.js中new Vue({});中的template: '<App />', components: {App}需要改变成render: h => (App) 。

    2)this.$Message没法调用,将iview源码中注册组件的components改成render函数即可。

4、data、props、methods都可代理到实例上,通过this.XXX直接调用,不通过this.$data.XXX等。this.$data---->拿到所有data中定义的数据

5、_uid是每个组件唯一的标识

6、@hook:监听子组件生命周期加载完成:

<hello @hook:mounted="kk" @hook:created="qq"></hello>

kk() {    //监听子组件hello的生命周期mounted完成
  console.log('hello mounted done');  
}

qq() {    //监听子组件hello的生命周期created完成
  console.log('hello created done');  
}

7、{{}}等同于v-text,用于存放DOM中的变量值,一般用{{}},有可能会出现不解析的情况,用指令v-cloak(等编译完才显示)解决即可

  2)v-html可以解析html语句,可转义,但是可能会遭到XSS攻击,因此要慎用

8、动态值的优先级更高:

<input value="22" :value="77" />

----->  value: 77

 9、$event:需要添加自己的参数时的占位符

  1)正常情况下的子组件调用父组件的方法以及传参:

index.vue:
<hello @click="kii"></hello>


kii(data) {
  console.log(data);   //22
}




hello.vue:
<div @click="aaa">emit click</div>


click() {
  this.$emit('click', 22);  
}

  2)父组件需要在该组件中传递自己的参数时,需要$event来占位保留子组件传递的值:

index.vue:
<hello @click="kii($event, 33)"></hello>


kii(data, val) {    //$event只能识别第一位参数,因此子组件需要传递多个参数时,用对象包起来传递整个对象即可
  console.log(data, val);   //22  33
}




hello.vue:
<div @click="aaa">emit click</div>


click() {
  this.$emit('click', 22);  
}

 10、插槽:

  (1)插槽的用法:

    1)父组件插槽占位,引入不同的子组件:

index.vue:

<hello>
    <slot></slot>    
</hello>


hello.vue:

<div>
    <span>{{msg}}</span>
</div>


data() {
    return {
        msg: '111'
    }
}

    2)具名插槽:

index.vue:

<hello>
    <template v-slot:header>
        <p>This is header slot!!</p>
    </template>
    <template>
        <p>This is main slot!!</p>
    </template>
    <template v-slot:footer>
        <p>This is footer slot!!</p>
    </template>
</hello>


hello.vue:

<div>
    <header>
        <slot name="header"></slot>
    </header>
    <main>
        <slot></slot>
    </main>
    <footer>
        <slot name="footer"></slot>
    </footer>
</div>  

  (2)用子组件的数据:

index.vue:

<hello v-slot="uu">
    <span>{{uu.aa}}</span>
    <span>{{uu.bb}}</span>
</hello>


hello.vue:

<div>
    <slot :aa="msg" :bb="msg2"></slot>
</div>


data() {
    return {
        msg: '111',
        msg2: '222'
    }
}

 11、动态组件:

  (1)keep-alive:缓存。使用场景:1)不要求实时性;2)步骤条(保存当前操作)。

    1)include、exclude根据name值去匹配包括还是去掉该路由的缓存;max则表示最大缓存的组件实例数:

<!-- 逗号分隔字符串 -->
<keep-alive include="a,b">
  <component :is="view"></component>
</keep-alive>



<!-- 最大缓存组件实例数,超过则最久没访问的组件实例会被销毁 -->
<keep-alive :max="10">
  <component :is="view"></component>
</keep-alive>

    2)当组件在 <keep-alive> 内被切换,它的 activated (进)和 deactivated (出)这两个生命周期钩子函数将会被对应执行。使用场景:

      (A)、页面不刷新;

      (B)、同一个组件,不同的调用,导致不渲染,解决方法:

       a)监听路由变化:

watch: {
    $route(val) {
        //代码片段
    }
}

      b)beforeUpdateRoute

  (2)动态组件:使用场景:1)判断条件加载两个不同组件;2)加载动态表单

<!-- 自定义属性可任意加 -->
<component :is="data.length > 300 ? 'hello' : 'div'" :size="30">
</component>

  (3)异步组件:(性能优化)

    1)代码覆盖率:加载的文件都只为展示当前的页面,覆盖率越高,性能越好;

    2)跟首屏无关;    

    3)按需加载.

<!-- 需要加载hello组件时,会加载hello.js -->
const Hello = () => import (/* webChunkName: 'hello' */ '@/views/hello');   

  (4)混入(mixin):全局/局部注册,解决复用问题(很多页面都需要有这些)

    1)mixin中生命周期和组件的合并,其他的则会覆盖组件的;

    2)坏处:看不见定义及处理,因此要少用。

  (5)inject和provide:解决跨级暴露并接收

12、函数式组件:简单用于展示类的组件,无响应式,性能更好:

<template functional>
    <!-- 组件内容 -->
</template>

13、插件:在new Vue()之前通过全局方法 Vue.use() 使用插件。

14、过滤器:对数据的过滤。适用于v-bind和{{}}。主要场景是多个地方都用到的情况下,用过滤器,也可以全局注册:

<!-- 在双花括号中 -->
{{ message | capitalize }}

<!-- 在 `v-bind` 中 -->
<div v-bind:id="rawId | formatId"></div>
//在实例中定义过滤器
filters: {
    capitalize: function (value) {
        if (!value) return '';
        value = value.toString();
        return value.charAt(0).toUpperCase() + value.slice(1);
    }
}



//全局注册过滤器
Vue.filter('capitalize', function (value) {
    if (!value) return '';
    value = value.toString();
    return value.charAt(0).toUpperCase() + value.slice(1);
})

new Vue({
  // ...
})

15、自定义组件的v-model:

index.vue:

<div>
    {{abc}}    //点击hello组件的按钮后,该变量变为233333
    <hello v-model="abc"></hello>
</div>

data() {
    return {
        abc: 1
    }
}


hello.vue:
<button @click="changeA">Click!</button>

props: ['abc'],
model: {
    event: 'change',
    prop: 'abc'
},
methods: {
    chngeA() {
        this.$emit('change', 233333);
    }
}

16、生命周期钩子(常用):

  1)created:调接口,加载loading状态,定义不渲染视图不双向绑定的数据等;

  2)mounted:之后才能渲染DOM,注意DOM渲染时间差,用nextTick解决;

  3)destroyed:组件销毁时的操作;

  4)activated:在keep-alive时才有该生命周期,组件激活时调用,在服务器端渲染期间不被调用;

  5)deactivated:在keep-alive时才有该生命周期,组件停用时调用,在服务器端渲染期间不被调用。

17、API:

  1)Vue.extend(options):创建构造器,并创建实例,挂载在页面元素上

// 创建构造器
var Profile = Vue.extend({
  template: '<p>{{firstName}}</p>',
  data: function () {
    return {
      firstName: 'Walter',
    }
  }
})
// 创建 Profile 实例,并挂载到body元素上。
new Profile().$mount('body')

  2)Vue.compile:在 render 函数中编译模板字符串。只在独立构建时有效。

  3)<pre>:不编译,直接显示写入的代码片段。

 18、vm.$watch:添加动态监听,需要手动销毁:

<div>
    <button @click="change">Click!!</div>
    <hello :abc="abc"></hello>
</div>


data() {
    return {
        abc: 1
    }
},
methods: {
    change() {
        this.abc++;
    }
}


hello.vue:

<span>{{ abc }}</span>

props: ['abc'],
mounted() {
    //添加动态监听
    this.$watch('abc', function(val)) {
        console.log('val', val);   //每次点击都会走监听 
    });

    //添加回调内销毁的监听
    let unwatch = this.$watch('abc', function(val)) {
        console.log('val', val);   //只有第一次改变会走监听 
        unwatch();
    });
}

 

posted on 2019-07-18 20:40  minoz  阅读(339)  评论(0编辑  收藏  举报