# Vue.js 开发去哪儿网App

(版本:2.5->2.6->3.0)

# 前言

  • 学习方法

    1. 视频教程带你入门:
      初学者如果没有MVVM模式的基础学习Vue,可能初期切换思路有比较大的难度,这个时候可以借助视频教程辅助入门,而如果你对React或者Angular有过工作经验或者足够多的了解,那么可以省略这一步了,直接读官方文档会是更好的选择。
    2. 细读文档:
      Vue的官方文档上基本包含了Vue的所有知识点,文档看透,Vue也就掌握的很好了。
    3. 高级知识点深究:
      Vue中的一些难点,比如说服务器端渲染(SSR),预渲染,高级异步组件,递归组件,Vuex,vue-router,weex这样的内容,这个阶段需要把这些知识一一攻克。
    4. 源码阶段:
      到了这个阶段的同学,基本上可以游刃有余的使用Vue进行项目开发了,接下来就是深挖Vue的实现原理了,你可以通读Vue,Vuex,vue-router这些库的源码,做到从底层理解Vue的设计思路。
    5. 横向学习:
      当你从底层驾驭了Vue,是时候开始扩展你的知识广度了,你可以尝试学习React,Angular等其他框架,横向打通这些框架之间的关联:我们经常说某些框架好,某些框架不好,但是实际上如果你深入学习每个框架,它们都有自己优秀的设计理念和适用场景,只有你对每一个框架有了深入的理解后,才能够横向对比理解框架各自最大的优势。到时候,我相信大家也就不会随便喷其他框架了,Vue也可以用的炉火纯青了。
  • 课程结构

    基础内容 ➡️ 基础语法 ➡️ MVVM模式 ➡️ 组件化
    生命周期 ➡️ 动画特效
    实战项目 ➡️ 环境搭建 ➡️ 使用Git ➡️ 数据模拟 ➡️ 本地开发
    联调 ➡️ 真机测试 ➡️ 上线

  • 课程知识结构

    Axios、Vuex、Stylus、插件
    Vue Router、异步组件、递归组件、公用组件

# 基础复习

var app = new Vue({
    el:’#app’,
    data:{
        msg: ‘ hello’
    }
})
1
2
3
4
5
6

实例外引用该vue实例里的数据,这样用:
app.$data.msg
msg是变量名。注意要加$data

绑定属性,传入数据,不用加花括号!如::value="todo"

# v-model原理

引申:v-model原理
(🍎 这篇文章还讲了 “自定义组件怎么实现v-model”)

<input v-model="todo" />
//  等同于
<input :value="todo" @input="todo = $event.target.value" />
1
2
3

解释:
$event 指代当前触发的事件对象。
$event.target 指代当前触发的事件对象的dom
$event.target.value 就是当前 dom 的 value值

@input方法中,value => todo
:value中,todo => value
如此,形成了一个闭环,也就是所说的数据的双向绑定。

说明:
这个语法糖必须是固定的,什么意思?
也就是说,满足语法糖规则:属性必须为 value,方法名必须为 input,缺一不可。

# jQuery实现todolist的面向对象写法

function Page(){ }  
$.extend(Page.prototype,{
	init:function(){
        this.bindEvents()
    },
    bindEvents:function(){
        var btn = $("#btn");
        btn.on('click',$.proxy(this.handleBtnClick,this));
    },
    handleBtnClick:function(){
	    alert('123')      
    }
})
var page = new Page();
page.init();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# jQuery实现todolist的面向对象写法 FAQ (听课 2-4 课后问答)

  1. this.bindEvents()this.handleBtnClick, 同样是方法,this.handleBtnClick加上括号为什么会出错?

    • 前面那个有括号,是执行方法的动作;
      后面那个没有括号,它是作为一个方法的参数,是个方法本身,不是执行动作。
  2. btn.on("click", $.proxy(this.handleBtnClick, this)) 写法,是不是类似于以前 面向过程 写法中 把this赋值给一个变量,把this储存起来?

    • 是的,它和es6里面的bind(this)是一个东西
  3. 三个this是不是都是指向的构造函数的实例?对这三个this都有点蒙。

    • 都指向vue实例,vue底层帮你做了绑定
  4. 之所以在构造函数的原型里面分三步写出点击事件,没有像dom一样直接获取元素绑定事件,是不是为了方便以后的分节引用?

    • 为了方便清空引用
  5. 我现在具备js基础知识,但是jquery基本是不怎么会的,想请教一下老师这种情况,边看老师讲的Vue边看jquery文档感觉效率很低,就比如proxy这个用法$.proxy(this.handleBtnClick,this)看了文档不太能理解,有么有什么好的学习方法?

    • 没有好办法,硬着头皮学
  6. $.extend(){}这是什么方法?

    • jQuery.extend()方法,$是jQuery的简写。
    • 用于将一个或多个对象的内容合并到目标对象,跟vue没有什么关系,这里只是用jquery的方法演示下功能的实现和vue做一个对比。
    • JQuery的extend扩展方法 (很具体,讲了原理,还讲了应用。)
  7. $.extend(Page.prototype,{})Page.prototype = {}有什么不同

    • 建议你打开jquery的代码,搜索extend关键字,去尝试看下这个方法的实现源码,很简单的,看过九洞,其实两者差别不大,前者是向prototype上增加内容,后者是直接覆盖prototype
    • 一个是jquery方法extend向page原型上添加,一个是js原生方法page.prototype
  8. 构造函数是什么,怎么用?

    • JS 中构造函数和普通函数的区别
    • 严格说来,构造函数归属于javascript中的知识部分,你首先需要了解js的构造函数,原型对象,及简单的面向对象的知识,jquery 在老师的编码中,实际只是起到了一个工具的作用,一个是$.extend()合并对象,另一个$.proxy()绑定this指向。
    • 我认为理解$.extend $.proxy obj.on这三个jquery API就OK。
    • 老师使用$.extend给类Page的原型扩展方法,以便实例对象访问。使用on给btn注册事件。使用$.proxy规定执行handleBtnClick函数内部的this指向。
  9. $.proxy是什么?

    • jQuery $.proxy() 方法
    • $.proxy用法(解决this转移问题) 描述:接受一个函数,然后返回一个新函数,并且这个新函数始终保持了特定的上下文语境。
      实例:
      强制执行 objPerson 内的 "test" 函数的上下文。
      做一下就大致明白,这里不用$.proxy的话,this.name 和 this.age 都取不到值。
    <!DOCTYPE html>
    <html>
    	<head>
    		<meta charset="utf-8"> 
    		<title>菜鸟教程(runoob.com)</title> 
    		<script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js">
    		</script>
    		<script>
    		$(document).ready(function(){
    		  var objPerson = {
    		    name: "John Doe",
    		    age: 32,
    		    test: function(){
    		      $("p").after("Name: " + this.name + "<br> Age: " + this.age);
    		    }
    		  };
    		  $("button").click($.proxy(objPerson,"test"));
    		});
    		</script>
    	</head>
    	<body>
    		<button>执行 test 函数</button>
    		<p></p>
    	</body>
    </html>
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25

# 附加:Javascript简写条件语句

  1. 简写变量声明
    在定义函数的时候,你可能需要先声明多个变量,例如:
let x;
let y;
let z = 3;
1
2
3

这时,你可以使用简写的方式节省很多时间和空间,即同时声明多个变量:

let x, y, z=3;
1
  1. 简写 if 执行条件 这可能微不足道,但值得一提。在你做if条件检查的时候,其赋值操作可以省略,例如:
if (likeJavaScript === true)
1

可以简写为:

if (likeJavaScript)
1

只有当likeJavaScript是真值的时候,以上两个语句才可以替换。如果判断假值,例如:

let a;
if ( a !== true ) {
 // do something...
}
1
2
3
4

可以简写为:

let a;
if ( !a ) {
 // do something...
}
1
2
3
4
  1. 三元运算符
const x = 20;
let answer;
if (x > 10) {
 answer = 'is greater';
} else {
 answer = 'is lesser';
}
1
2
3
4
5
6
7

可以写成:

const answer = x > 10 ? 'is greater' : 'is lesser';
1

(迷惑:const x = 20 跑哪去了?)
也可以嵌套if语句:

const big = x > 10 ? " greater 10" : x
1
  1. 简写短路求值
    当给一个变量分配另一个值的时候,你可能想确定初值不是null,undefined或空值。这时,你可以写一个多重条件的if语句:
if (variable1 !== null || variable1 !== undefined || variable1 !== '') {
  let variable2 = variable1;
}
1
2
3

或者可以使用短路求值的方法:

const variable2 = variable1  || 'new';
1
  1. 简写 JavaScript 循环方法
    当你想使用纯 javascript 而不依赖外库(例如jQuery)的时候,这是非常有用的。
for (let i = 0; i < allImgs.length; i++)
1

可以简写为:

for (let index in allImgs)
1

也可以使用Array.forEach:

function logArrayElements(element, index, array) {
 console.log("a[" + index + "] = " + element);
}
[2, 5, 9].forEach(logArrayElements);
// logs:
// a[0] = 2
// a[1] = 5
// a[2] = 9
1
2
3
4
5
6
7
8

# 视图模式

Model-View-Controller(模型-视图-控制器):
用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑.它强制性地使应用程序的输入、处理和输出分开。
最典型的MVC就是JSP +servlet+javabean的模式。

MVVM,m-v-vm
专注于m,vue来实现vm,节约至少30%代码量
vue中VM的实现:虚拟dom,definproperty,可以在课程全部学完之后再去了解。

# 前端组件化

每一个组件就是页面上的一个区域。
我的理解:拼乐高。
(听课 2-5)

# 听课 2-6 使用组件改造todolist

vue.component是创建全局组件的方法,注意是全局组件
如果组件注册的时候这样命名:'TodoItem',引用的时候就可以这样引用:

<todo-item></todo-item>
1

v-bind 向组件传入一个绑定值,如:

<todo-item v-bind:content="item" v-for="item in list"></todo-item>
1

把item的内容传给content,
然后子组件就要接收content的内容,用props,然后就可以在子组件的template中引用content了。如:

vue.component('TodoItem',{
	props:['content'],
	template: "<li>{{content}}</li>"
})
1
2
3
4

局部组件的使用:

可以在实例外面定义,然后在实例里注册,才能使用(目前来看是跟全局组件一样使用)。如:

var TodoItem = {
	props:['content'],
	template: "<li>{{content}}</li>"
}

var app = new Vue({
	...
	components:{
		TodoItem: TodoItem
	},
	...
})
1
2
3
4
5
6
7
8
9
10
11
12

# 听课 2-7 简单的组件间传值

学了用 v-bind 和 props 从父组件向子组件传值,那如何从子组件向父组件传值呢?
$emit (啊,学过了,老忘 😢),可以传递事件和数据(值)

var TodoItem = {
	props:['content'],
	template: "<li @click="deleteItem">{{content}}</li>",
	methods: {
		deleteItem: function () {
			$emit("delete")
		}
	}
}
1
2
3
4
5
6
7
8
9

子组件想传递给父组件触发的事件,父组件要监听才能触发。
如下,监听deleteItem,监听到时触发父组件里面的delete事件:

<todo-item @delete="deleteItem" v-bind:content="item" v-for="item in list"></todo-item>
1

这个时候,案例里面想要 在点击某个事项时,可以删掉这个事项,此时如何实现? 思路: 点击在父组件上,触发

v-bind: 简写成 :

# 到vue官网仔细通读“介绍”章节文档

(听课 2-8 章节作业)

答疑:
https://coding.imooc.com/learn/list/203.html
https://coding.imooc.com/learn/questiondetail/61185.html
https://coding.imooc.com/learn/questiondetail/55421.html
https://coding.imooc.com/learn/questiondetail/50428.html
https://coding.imooc.com/learn/questiondetail/123153.html
https://coding.imooc.com/learn/questiondetail/132470.html
https://coding.imooc.com/learn/questiondetail/136091.html
https://coding.imooc.com/learn/questiondetail/127956.html