用了这么久的vue了,可是一直没有时间写个系列文章,如今抽必定时间总结下vue的知识点。vue
首先,Vue 不支持 IE8
及如下版本,由于 Vue 使用了 IE8 没法模拟的 ECMAScript 5 特性。但它支持全部兼容 ECMAScript 5 的浏览器。
下面总结的内容是在2.x的版本。node
<script>
引入直接下载并用 <script>
标签引入,Vue 会被注册为一个全局变量。webpack
在开发环境下不要使用压缩版本,否则你就失去了全部常见错误相关的警告!
推荐:https://cdn.jsdelivr.net/npm/vue,会保持和 npm 发布的最新的版本一致。能够在 https://cdn.jsdelivr.net/npm/vue/ 浏览 npm
包资源。
也能够从 unpkg
和 cdnjs
获取 (cdnjs 的版本更新可能略滞后)。git
在用 Vue
构建大型应用时推荐使用 NPM
安装。NPM 能很好地和诸如 webpack 或 Browserify 模块打包器配合使用。同时 Vue 也提供配套工具来开发单文件组件。github
# 最新稳定版 $ npm install vue
快速搭建大型单页应用,只需几分钟便可建立并启动一个带热重载、保存时静态检查以及可用于生产环境的构建配置的项目:web
# 全局安装 vue-cli $ npm install --global vue-cli # 建立一个基于 webpack 模板的新项目 $ vue init webpack my-project # 安装依赖,走你 $ cd my-project $ npm install $ npm run dev
GitHub 仓库的 /dist
文件夹只有在新版本发布时才会提交。若是想要使用 GitHub 上 Vue 最新的源码,你须要本身构建!vue-cli
git clone https://github.com/vuejs/vue.git node_modules/vue cd node_modules/vue npm install npm run build
<div id="app"> {{ message }} </div>
var app = new Vue({ el: '#app', data: { message: 'Hello Vue!' } })
如今数据和 DOM 已经被创建了关联,全部东西都是响应式的。咱们要怎么确认呢?打开你的浏览器的 JavaScript 控制台 (就在这个页面打开),并修改 app.message 的值npm
给某一个DOM元素绑定属性,以下数组
<div id="app"> <span v-bind:title="message"> 鼠标悬停几秒钟查看此处动态绑定的提示信息! </span> </div>
JS代码:浏览器
var app = new Vue({ el: '#app', data: { message: '页面加载于 ' + new Date().toLocaleString() } })
其中上面用到的v-bind
特性被称为指令
。
控制切换一个元素是否显示也至关简单:
<div id="app"> <p v-if="seen">如今你看到我了</p> </div>
var app = new Vue({ el: '#app', data: { seen: true } })
v-for
指令能够绑定数组的数据来渲染一个项目列表:
<div id="app"> <ol> <li v-for="todo in todos"> {{ todo.text }} </li> </ol> </div>
var app = new Vue({ el: '#app', data: { todos: [ { text: '学习 JavaScript' }, { text: '学习 Vue' }, { text: '整个牛项目' } ] } })
在控制台里,输入 app.todos.push({ text: '新项目' })
,你会发现列表最后添加了一个新项目。
Vue 提供了 v-model
指令,它能轻松实现表单输入和应用状态之间的双向绑定。
<div id="app"> <p>{{ message }}</p> <input v-model="message"> </div>
var app = new Vue({ el: '#app', data: { message: 'Hello Vue!' } })
重要:须要明白全部的 Vue 组件都是 Vue 实例,而且接受相同的选项对象 (一些根实例特有的选项除外)。
组件系统是 Vue 的另外一个重要概念,由于它是一种抽象,容许咱们使用小型、独立和一般可复用的组件构建大型应用。仔细想一想,几乎任意类型的应用界面均可以抽象为一个组件树:
在 Vue 里,一个组件本质上是一个拥有预约义选项的一个 Vue 实例。在 Vue 中注册组件很简单:
// 定义名为 todo-item 的新组件 Vue.component('todo-item', { template: '<li>这是个待办项</li>' })
如今你能够用它构建另外一个组件模板:
<ol> <!-- 建立一个 todo-item 组件的实例 --> <todo-item></todo-item> </ol>
可是这样会为每一个待办项渲染一样的文本,这看起来并不炫酷。咱们应该能从父做用域将数据传到子组件才对。让咱们来修改一下组件的定义,使之可以接受一个 prop
:
Vue.component('todo-item', { // todo-item 组件如今接受一个 // "prop",相似于一个自定义特性。 // 这个 prop 名为 todo。 props: ['todo'], template: '<li>{{ todo.text }}</li>' })
如今,咱们可使用 v-bind 指令将待办项传到循环输出的每一个组件中:
<div id="app"> <ol> <!-- 如今咱们为每一个 todo-item 提供 todo 对象 todo 对象是变量,即其内容能够是动态的。 咱们也须要为每一个组件提供一个“key”,稍后再 做详细解释。 --> <todo-item v-for="item in groceryList" v-bind:todo="item" v-bind:key="item.id"> </todo-item> </ol> </div>
Vue.component('todo-item', { // todo-item 组件如今接受一个 // "prop",相似于一个自定义特性。 // 这个 prop 名为 todo。 props: ['todo'], template: '<li>{{ todo.text }}</li>' }) var app = new Vue({ el: '#app', data: { groceryList: [ { id: 0, text: '蔬菜' }, { id: 1, text: '奶酪' }, { id: 2, text: '随便其它什么人吃的东西' } ] } })
这个例子子单元
经过 prop
接口与父单元进行了良好的解耦。咱们如今能够进一步改进 <todo-item>
组件,提供更为复杂的模板和逻辑,而不会影响到父单元。
在一个大型应用中,有必要将整个应用程序划分为组件,以使开发更易管理
<div id="app"> <app-nav></app-nav> <app-view> <app-sidebar></app-sidebar> <app-content></app-content> </app-view> </div>
你可能已经注意到 Vue 组件很是相似于自定义元素——它是 Web 组件规范的一部分,这是由于 Vue 的组件语法部分参考了该规范。例如 Vue 组件实现了 Slot API 与 is 特性。可是,仍是有几个关键差异:
当一个 Vue 实例被建立时,它向 Vue 的响应式系统中加入了其 data 对象中能找到的全部的属性。当这些属性的值发生改变时,视图将会产生“响应”,即匹配更新为新的值。
// 咱们的数据对象 var data = { a: 1 } // 该对象被加入到一个 Vue 实例中 var vm = new Vue({ data: data }) // 它们引用相同的对象! vm.a === data.a // => true // 设置属性也会影响到原始数据 vm.a = 2 data.a // => 2 // ……反之亦然 data.a = 3 vm.a // => 3
重要:当这些数据改变时,视图会进行重渲染。值得注意的是只有当实例被建立时data
中存在的属性才是响应式的。也就是说若是你添加一个新的属性,好比:vm.b = 'hi'
那么对 b
的改动将不会触发任何视图的更新。若是你知道你会在晚些时候须要一个属性,可是一开始它为空或不存在,那么你仅须要设置一些初始值。好比:
data: { newTodoText: '', visitCount: 0, hideCompletedTodos: false, todos: [], error: null }
咱们也可使用ES6标准中提供的一个方法Object.freeze()
,其方法做用就是冻结对象,对对象中的属性进行修改无效。也便是会阻止修改现有的属性,也意味着响应系统没法再追踪变化
。
var obj = { foo: 'bar' } Object.freeze(obj) new Vue({ el: '#app', data () { return { obj } } })
<div id="app"> <p>{{ obj.foo }}</p> <!-- 这里的 `obj.foo` 不会更新! --> <button @click="obj.foo = 'baz'">Change it</button> </div>
除了数据属性,Vue 实例还暴露了一些有用的实例属性与方法。它们都有前缀 $,以便与用户定义的属性区分开来。例如:
var data = { a: 1 } var vm = new Vue({ el: '#example', data: data }) vm.$data === data // => true vm.$el === document.getElementById('example') // => true // $watch 是一个实例方法 vm.$watch('a', function (newValue, oldValue) { // 这个回调将在 `vm.a` 改变后调用 })
每一个 Vue 实例在被建立时都要通过一系列的初始化过程——例如,须要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。同时在这个过程当中也会运行一些叫作生命周期钩子的函数,这给了用户在不一样阶段添加本身的代码的机会。
好比 created
钩子能够用来在一个实例被建立以后执行代码:
new Vue({ data: { a: 1 }, created: function () { // `this` 指向 vm 实例 console.log('a is: ' + this.a) } }) // => "a is: 1"
也有一些其它的钩子,在实例生命周期的不一样阶段被调用,如 mounted
、updated
和 destroyed
。生命周期钩子的 this
上下文指向调用它的 Vue
实例。
不要在选项属性或回调上使用箭头函数,好比created: () => console.log(this.a)
或vm.$watch('a', newValue => this.myMethod())
。由于箭头函数是和父级上下文绑定在一块儿的,this
不会是如你所预期的Vue
实例,常常致使Uncaught TypeError: Cannot read property of undefined
或Uncaught TypeError: this.myMethod is not a function
之类的错误。
下图展现了实例的生命周期。你不须要立马弄明白全部的东西,不过随着你的不断学习和使用,它的参考价值会愈来愈高。
注:特别有用