VUE学习要点整理

一、理解VUE原理

用于构建用户界面的渐进式框架。通过Vue指令,实现JS和HTML的分离,JS代码仅仅是通过Module去控制View,而不是定义View。

中文官网:cn.vuejs.org/

1、Vue.js 框架的优势:

提高代码复用率
降低模块之间耦合度
提高开发速度
提高代码质量
组件化(web component)开发
 

2、VUE安装:

1、安装node.js 

nodejs.org/en/     git:  git-scm.com/download/wi…

2、安装bower

npm install bower -g (用 bower -v  查看是否安装成功)

3、bower install vue<#版本> (用bower info vue 查看版本)

 

3、VDOM原理

1、解决的问题:

Virtual DOM 用来解决DOM与Layout绘画压力问题。每一次DOM改变,Layout都会repaint,如果操作频繁,会造成渲染压力。
vue=>JSEngine=>DOM=>Layout

2、择时渲染:

VDOM 会择时渲染,1、setTimeout计时,或者引擎觉得合理的时机。

3、Diff算法:

VDOM在引擎源码中,是一个JS对象,其实是树状结构的JSON。所有节点都挂载在根节点上。每次diff的时候,有key就按照key比较,key必须是唯一的,可以用id+data作为key。没有key,就按照type比较。type不同的节点,直接拿掉,记录下来,下次重画。子节点里,比较出新增的,删除的,把这些都记录成diff,下次用diff重画节点。

面试题1:

用JS代码操作DOM写一个响应刷新

function changeDirectly(){
    var app = document.getElementById('app');
	var html = '';

	var htmlTmp = document.getElementById('tmp').innerHTML;

	html = htmlTmp.replace(/%word%/g, 'abc');
	console.log(html);

	app.innerHTML = html;
}
addEventListener('click', changeDirectly);
复制代码

实质就是在DOM中直接查找指定的标签,然后全局替换。

4、响应式原理

官网文章说的很透彻了。
cn.vuejs.org/v2/guide/re…

这里总结一下我的理解

1、JavaScript ES5 中 有个一个方法,Object.defineProperty,可以把传入vue的JS对象中的所有property转为getter/setter。(VUE不支持IE8以下是因为其不支持ES5)

2、每个vue组件实例都对应一个watcher实例,watcher把组件渲染过程中接触过的JS数据的property记录为依赖,当依赖的setter触发时,watcher被通知,然后重新渲染关联组件。

image.png
图片引自cn.vuejs.org/images/data…

3、涉及vue中data对象的property属性修改,如果要实现修改后property的响应,必须要从原型链的层级修改。具体方法,参考文章中详细介绍。

4、另外在异步更新DOM过程中,如果同一个事件循环过程中,同一个watcher被触发多次,那么只会被推入到队列中一次,在下一次tick中,只执行最后更新的那次,这种去重简化了不必要的DOM刷新。

5、每次tick,实际原理和setTimeOut类似,都会在下一轮刷新时执行。可以自定义调用Vue.nextTick(callback)执行下次刷新内容。

Vue.component('example', {
  template: '<span>{{ message }}</span>',
  data: function () {
    return {
      message: '未更新'
    }
  },
  methods: {
    updateMessage: function () {
      this.message = '已更新'
      console.log(this.$el.textContent) // => '未更新'
      this.$nextTick(function () {
        console.log(this.$el.textContent) // => '已更新'
      })
    }
  }
})
复制代码

二、从MV*模式理解响应式原理

1、MVC模式:

Module存放数据
View更新DOM
Controller调用Module给View渲染
M——>C——>V

2、MVP模式

Presenter: 更新Module,修改View
M<==>P<==>V

3、MVVM模式

MVVM模式是进阶的MVP模式,这个才是vue使用的,前两个是过度版本介绍。
ViewModel: 自动化调用的Presenter
Module 更新,View自动随着更新

Vue的MVVM实现:
当Vue实例创建后,形成双向绑定,关键技术点就是 DOM Listener, Data bindings
M<=>VM<=>V
View层,DOM Listener监听DOM的变化,
Module层,Data bindings 帮助更新View 和 DOM
这个过程就是VM
Data bindings 就是指 Module里面有get()/set(),实现对数据的修改,get/set调用watcher()刷新View,然后修改DOM。

三、VUE语法:指令、事件、过滤器、计算属性,侦听器

1、指令:

  • v-if:条件指令
  • v-else: 条件指令,和v-if配合使用
  • v-show:渲染指令 显示或隐藏元素
  • v-for:列表指令
  • v-model:用于将控件与module双向绑定
  • v-model.lazy 只有在回车onblur时改动
  • v-model.number 只能输入数据
  • v-model.trim 去除前后空格
  • input:与module双向绑定
  • v-bind:用来控制元素的属性值,简写方式 “:” (v-bind = 🙂
    • v-bind:src=”https://juejin.cn/post/expression”
    • v-bind:class=”expression”
    • v-bind:style=”expression”

2、事件:

v-on:<事件名>
.stop
.prevent
.13 或者 .enter
.left 或者 .right 或者 .middle
.once
.ctrl 或者 .shift 或者 .alt

3、过滤器

{{message | filter}} 用于格式化输出

4、计算属性:

把函数当成属性

5、侦听器:

防止watch滥用,改用 computed

四、组件

利用组件实现代码可复用。

1、组件生命周期:

四个阶段:Create/Mount/Update/Destroy

每一个阶段都有前后两个状态:

beforeCreate/created (创建)

beforeMount/mounted (挂载DOM)

beforeUpdate/updated (更新)

beforeDestroy/destroyed (销毁)

2、组件通信

1、父子通信

父组件向子组件传递字符串或者传递变量:以子组件属性 props的方式,透传字符串

Vue.component('child', {
    template: `
        <div>
            <p :id="p1">{{str}}</p>
        </div>
        `,
    props: ['p1', 'str'],
    methods: {

    },
    mounted: function(){
        console.log(this.p1, this.str);
    }
});

Vue.component('parent', {
    template: `
        <div>
            <child :p1="prtP1" :str="prtStr"></child>  // 传递变量
           // <child :p1="11111111" :str="222222222"></child>  // 传递字符串
        </div>
        `,
    data: function(){
        return {
            prtP1: 'p456',
            prtStr: 'abc' 
        }
    }
});
复制代码

2、子组件向父组件传递数据

  1. 在父组件中建立事件响应函数
  2. 在父组件模版中,绑定事件,事件调用事件响应函数
  3. 在子组件中,触发事件
// 子组件
Vue.component('child', {
    template: `
        <div>
            <input type="button" @click="sendData" value="点我发送信息">
        </div>
        `,
    methods: {
        sendData: function(){
            this.$emit('myEvent', 'Hello World! I am Vue!');
        }
    }
});

// 父组件
Vue.component('parent',{
    template: `
        <div>
            <child @myEvent="getData"></child>
            <hr />
            <h4>现在的msg:{{msg}}</h4>
        </div>
        `,
    methods: {
        getData: function(msg){
            console.log('收到了来自子组件的信息:' + msg);
            this.msg = msg;
        }
    },
    data: function(){
        return {
            msg: ''
        };
    }
});
复制代码

3、父组件访问子组件的数据:this.$ref

// 子组件
Vue.component('child', {
    template: `
        <div></div>
    `,
    data: function(){
        return {
            childStr: 'I am your son!'
        };
    },
    mounted: function(){
        console.log('子组件的mount:' + this.$parent.parentStr);
    }
});

// 父组件
Vue.component('parent', {
    template: `
        <div>
            <child ref="mySon"></child>
            <input type="button" value="获得子组件信息" @click="getData">
        </div>
        `,
    data: function(){
        return {
            parentStr: 'I am your father!'
        }
    },
    methods: {
        getData: function(){
            console.log('获得子组件信息:' + this.$refs.mySon.childStr);
        }
    }
});
复制代码

4、子组件访问父组件的数据: this.$parent

Vue.component('parent', {
    template: `
        <div>
            <ul v-show="isSwitchOn">
                <li v-for="item in array">{{item}}</li>
            </ul>
            <child ref="mySon" ></child>
        </div>
        `,
    data: function(){
        return {
            isSwitchOn: true,
            array: [5, 10, 25, 50]
        };
    }
});

// 子组件
Vue.component('child', {
    template: `
        <div>
            <input type="button" value="显示/不显示" @click="showOrNot" />
            <input type="button" value="添加" @click="addItem">
        </div>
        `,
    methods: {
        showOrNot: function(){
            this.$parent.isSwitchOn = !this.$parent.isSwitchOn;
        },
        addItem: function(){
            this.$parent.array.push(25);
        }
    }
});
复制代码

5、兄弟组件之间通信

  • 需要通过公共的Vue实例对象
  • 接收方绑定事件,发送方触发事件
// 1. 创建公共的Vue对象
var bridge = new Vue();
// 2. 创建两个子组件
Vue.component('child-1',{
    template: `
        <div>
            <h4>msg: {{msg}}</h4>
            <input type="button" value="1->2" @click="sendData" />
        </div>
        `,
    data: function(){
        return {
            msg: ''
        }
    },
    methods: {
        sendData: function(){
            bridge.$emit('OneToTwoEvent', 'Hello 2, I am 1');
        }
    },
    mounted: function(){
        var that = this;
        bridge.$on('TwoToOneEvent', function(msg){
            console.log('收到来自2的:' + msg);
            that.msg = msg;
        })
    }
});

Vue.component('child-2',{
    template: `
        <div>
            <h4>msg: {{msg}}</h4>
            <input type="button" value="2->1" @click="sendData" />
        </div>
        `,
    data: function(){
        return {
            msg: ''
        }
    },
    methods: {
        sendData: function(){
            bridge.$emit('TwoToOneEvent', 'Hello 1, I am 2');
        }
    },
    mounted: function(){
        // 1. mounted被调用时,只是定义了回调函数,但是并没有运行
        // 2. 当child-1来触发事件时,引擎来调用回到函数,此时初始化回调函数中的this指向
        //    注意:此时this并不只想child-2对象,所以,this.msg找不到的
        // 3. 用闭包。
        var that = this;
        bridge.$on('OneToTwoEvent', function(msg){
            console.log('收到来自1的:' + msg);
            that.msg = msg;
        })
    }
});
复制代码

五、路由

路由就是设定URL和返回页面或者视图的对应关系,每个URL对应一个页面或者视图。

六、vuex

类Flux的状态管理。解决的问题是:vue原始数据被多个实例间共享时,如果被修改,将导致多个实例发生改变,且无法追溯是谁修改的。这容易造成混乱和不安全。

  1. vuex可以简单为,将每次对vue原始数据的修改都作记录
  2. 进阶理解:引用Flux思想,将data包裹上state,形成一个Store。View需要修改,可以发送一个action给dispatcher,然后由dispatcher去通知Store,修改完,View再更新。

更深入的理解 juejin.cn/post/695247…

七、脚手架: Vue cli

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享