Vue在国内的应用还是挺多的,也许比React多,公司的项目,小程序,很多的Vue的使用。
学习计划:
- 先学官方文档,从基础开始,初步感受,有了vue这些框架,前端开发本身应该很简单啊
- 学习demo,包含官方的demo,其他开源的demo,公司的项目,了解Vue的应用
- 看一看Vue技术内幕
- 将Vue应用到小程序的开发
- 前端技术,感觉不是1-2个月可以学好的,先花时间学一学,后续再慢慢补充,如果没机会实战,那也许只能是了解熟悉,而不能掌握,这也是没办法的事情,任何一项技术都是如此
FAQ
dist: 全称是distribution
打包后,chunk-vendors.js文件超大,几百k
Babel 入门教程: Babel是一个广泛使用的转码器,可以将ES6代码转为ES5代码,从而在现有环境执行。
Flow 是 facebook 出品的 JavaScript 静态类型检查工具。Vue.js 的源码利用了 Flow 做了静态类型检查,所以了解 Flow 有助于我们阅读源码。认识 Flow
Flow是工具,TypeScript是语言。 Flow - JS静态类型检查工具
ESLint TSLint: 代码检查工具,就像OCLint一样,对代码进行自动review,与flow是不同的东西,flow是编译时做静态类型检查,而lint是做代码规范,代码结构等简单,比如判断代码是否有太多层的if
css pre-processor
test
vue-cli 创建项目功能配置
功能(在项目创建后,仍然可以通过安装插件来增加功能)
babel: Babel是一个广泛使用的转码器,可以将ES6代码转为ES5代码,从而在现有环境执行 TypeScript: 支持使用 TypeScript 书写源码 Progressive Web App (PWA) Support: PWA 支持 Router: 支持 vue-router Vuex: 支持 vuex CSS Pre-processors: 支持 CSS 预处理器 Linter / Formatter: 支持代码风格检查和格式化 Unit Testing: 支持单元测试 E2E Testing: 支持 E2E 测试 使用配置文件: 将插件的配置保存在各自的配置文件中
vue-router
vue-router两种模式:hash 模式、history 模式
Progressive Web App (PWA) Support
就是可以将web应用添加到主屏幕的技术
基础
Vue实例
- 真双向绑定,UI输入直接改变model
<div id="app-6">
<p></p>
<input v-model="message">
</div>
var app6 = new Vue({
el: '#app-6',
data: {
message: 'Hello Vue!'
}
})
- 组件化应用构建
demo如下
<div id="app-7">
<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', {
props: ['todo'],
template: '<li></li>'
})
var app7 = new Vue({
el: '#app-7',
data: {
groceryList: [
{ id: 0, text: '蔬菜' },
{ id: 1, text: '奶酪' },
{ id: 2, text: '随便其它什么人吃的东西' }
]
}
})
有几个注意点:
- 组件
todo-item
直接在 html 中当标签使用 bind
的意思是:将标签的 todo 属性,与 Vue 实例的 item 属性保持一致,这里的 item,是遍历 Vue 实例的 groceryList 得到的- 在一个大型应用中,有必要将整个应用程序划分为组件,以使开发更易管理。在后续教程中我们将详述组件,不过这里有一个 (假想的) 例子,以展示使用了组件的应用模板是什么样的(都是组件化,更简洁直观语义化,避免一堆html标签):
<div id="app">
<app-nav></app-nav>
<app-view>
<app-sidebar></app-sidebar>
<app-content></app-content>
</app-view>
</div>
- 与自定义元素的关系:原来原生
Web 组件规范
已经有自定义原素了,是html更简洁直观语义化,避免一堆html标签,具体不清楚,先不管了,Vue的组件说它比原生强大
Vue实例
- Vue 实例暴露的属性和方法,需要前缀
$
var data = { a: 1 }
var vm = new Vue({
el: '#example',
data: data
})
// 获得这个实例上的属性
// 返回源数据中对应的字段
vm.a == data.a // => true
// 设置属性也会影响到原始数据
vm.a = 2
data.a // => 2
// ……反之亦然
data.a = 3
vm.a // => 3
vm.$data === data // => true
vm.$el === document.getElementById('example') // => true
// $watch 是一个实例方法
vm.$watch('a', function (newValue, oldValue) {
// 这个回调将在 `vm.a` 改变后调用
})
- 实例生命周期
模板语法
-
Vue.js 使用了基于 HTML 的模板语法,允许开发者声明式地将 DOM 绑定至底层 Vue 实例的数据。HTML 的模板语法,什么意思?
-
如果你熟悉虚拟 DOM 并且偏爱 JavaScript 的原始力量,你也可以不用模板,直接写渲染 (render) 函数,使用可选的 JSX 语法。难道React用的不是 HTML 的模板语法?
- “Mustache”语法 (双大括号)
<span>Message: </span>
- 双大括号会将数据解释为普通文本,而非 HTML 代码。为了输出真正的 HTML,你需要使用 v-html 指令: ```html
Using mustaches:
Using v-html directive:
5. Mustache 语法不能作用在 HTML 特性上,遇到这种情况应该使用 v-bind 指令:
```html
<div v-bind:id="dynamicId"></div>
- 指令 (Directives) 是带有 v- 前缀的特殊特性。一些指令能够接收一个“参数”,在指令名称之后以冒号表示。例如,v-bind 指令可以用于响应式地更新 HTML 特性:
<a v-bind:href="url">...</a> <a v-on:click="doSomething">...</a>
- 指令修饰符 (Modifiers) 是以半角句号 . 指明的特殊后缀,用于指出一个指令应该以特殊方式绑定。例如,.prevent 修饰符告诉 v-on 指令对于触发的事件调用 event.preventDefault(): ```html
8. 在构建由 Vue.js 管理所有模板的单页面应用程序 (SPA - single page application) 时,v- 前缀也变得没那么重要了。因此,Vue.js 为 v-bind 和 v-on 这两个最常用的指令,提供了特定简写:(SPA的概念不是特别清楚)
```html
<!-- 完整语法 -->
<a v-bind:href="url">...</a>
<!-- 缩写 -->
<a :href="url">...</a>
<!-- 完整语法 -->
<a v-on:click="doSomething">...</a>
<!-- 缩写 -->
<a @click="doSomething">...</a>
计算属性和侦听器
- demo
<div id="example">
<p>Original message: ""</p>
<p>Computed reversed message: ""</p>
</div>
var vm = new Vue({
el: '#example',
data: {
message: 'Hello'
},
computed: {
// 计算属性的 getter
reversedMessage: function () {
// `this` 指向 vm 实例
return this.message.split('').reverse().join('')
}
}
})
-
计算属性和方法:计算属性有缓存,方法没有
-
侦听属性
<div id="demo"></div>
var vm = new Vue({
el: '#demo',
data: {
firstName: 'Foo',
lastName: 'Bar',
fullName: 'Foo Bar'
},
watch: {
firstName: function (val) {
this.fullName = val + ' ' + this.lastName
},
lastName: function (val) {
this.fullName = this.firstName + ' ' + val
}
}
})
// 上面代码是命令式且重复的。将它与计算属性的版本进行比较:
var vm = new Vue({
el: '#demo',
data: {
firstName: 'Foo',
lastName: 'Bar'
},
computed: {
fullName: function () {
return this.firstName + ' ' + this.lastName
}
}
})
- 计算属性默认只有 getter ,不过在需要时你也可以提供一个 setter :
// ...
computed: {
fullName: {
// getter
get: function () {
return this.firstName + ' ' + this.lastName
},
// setter
set: function (newValue) {
var names = newValue.split(' ')
this.firstName = names[0]
this.lastName = names[names.length - 1]
}
}
}
// ...
- 侦听器:一个很好的demo,对于初步了解vue的实战
<div id="watch-example">
<p>
Ask a yes/no question:
<input v-model="question">
</p>
<p></p>
</div>
<!-- 因为 AJAX 库和通用工具的生态已经相当丰富,Vue 核心代码没有重复 -->
<!-- 提供这些功能以保持精简。这也可以让你自由选择自己更熟悉的工具。 -->
<script src="https://cdn.jsdelivr.net/npm/axios@0.12.0/dist/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/lodash@4.13.1/lodash.min.js"></script>
<script>
var watchExampleVM = new Vue({
el: '#watch-example',
data: {
question: '',
answer: 'I cannot give you an answer until you ask a question!'
},
watch: {
// 如果 `question` 发生改变,这个函数就会运行
question: function (newQuestion, oldQuestion) {
this.answer = 'Waiting for you to stop typing...'
this.debouncedGetAnswer()
}
},
created: function () {
// `_.debounce` 是一个通过 Lodash 限制操作频率的函数。
// 在这个例子中,我们希望限制访问 yesno.wtf/api 的频率
// AJAX 请求直到用户输入完毕才会发出。想要了解更多关于
// `_.debounce` 函数 (及其近亲 `_.throttle`) 的知识,
// 请参考:https://lodash.com/docs#debounce
this.debouncedGetAnswer = _.debounce(this.getAnswer, 500)
},
methods: {
getAnswer: function () {
if (this.question.indexOf('?') === -1) {
this.answer = 'Questions usually contain a question mark. ;-)'
return
}
this.answer = 'Thinking...'
var vm = this
axios.get('https://yesno.wtf/api')
.then(function (response) {
vm.answer = _.capitalize(response.data.answer)
})
.catch(function (error) {
vm.answer = 'Error! Could not reach the API. ' + error
})
}
}
})
</script>
Class与Style绑定
- 操作元素的 class 列表和内联样式,demo:
当有如下模板:
<div class="static"
v-bind:class="{ active: isActive, 'text-danger': hasError }">
</div>
和如下 data:
data: {
isActive: true,
hasError: false
}
结果渲染为:
<div class="static active"></div>
ps: class即为样式,(css选择器)[http://www.w3school.com.cn/cssref/css_selectors.ASP]
- 内联样式
<div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
data: {
activeColor: 'red',
fontSize: 30
}
条件渲染
就是一些 if else 之类的
列表渲染
就是for的使用
事件处理
- 可以用 v-on 指令监听 DOM 事件,并在触发时运行一些 JavaScript 代码。
示例:
<div id="example-1">
<button v-on:click="counter += 1">Add 1</button>
<p>The button above has been clicked times.</p>
</div>
var example1 = new Vue({
el: '#example-1',
data: {
counter: 0
}
})
- 为什么在 HTML 中监听事件? 你可能注意到这种事件监听的方式违背了关注点分离 (separation of concern) 这个长期以来的优良传统。什么是关注点分离?
表单输入绑定
表单相关
组件基础
组件相关
深入了解组件
vue.js官方的example
todomvc
-
vue 怎么会设计过滤器这种难以理解的东西
-
从数组删除元素用的是splice
firebase
- 搞清楚函数定义,类定义,对象定义。混乱的JavaScript语法,我靠
// vue实例内的computed的validation,并不是函数,而是对象{name: false, email: false}
computed: {
validation: function () {
return {
name: !!this.newUser.name.trim(),
email: emailRE.test(this.newUser.email)
}
},
isValid: function () {
var validation = this.validation
return Object.keys(validation).every(function (key) {
return validation[key]
})
}
}
validation(): Uncaught TypeError: validation is not a function
var person = {
name : ['Bob', 'Smith'],
age : 32,
gender : 'male',
interests : ['music', 'skiing'],
bio : function() {
alert(this.name[0] + ' ' + this.name[1] + ' is ' + this.age + ' years old. He likes ' + this.interests[0] + ' and ' + this.interests[1] + '.');
},
greeting: function() {
alert('Hi! I\'m ' + this.name[0] + '.');
},
validation: function () {
return {
name: false,
email: true
}
}
};
// person.validation(): {name: false, email: true}
grid
-
计算属性 filteredData 的值始终取决于 filterKey 等 props 的值,即 props filterKey值的变化,会触发计算属性 filteredData 的更新,从而更新到 Dom。
-
我们可以将同一函数定义为一个方法而不是一个计算属性。两种方式的最终结果确实是完全相同的。然而,不同的是计算属性是基于它们的依赖进行缓存的。只在相关依赖发生改变时它们才会重新求值。这就意味着只要 props 还没有发生改变,多次访问 filteredData 计算属性会立即返回之前的计算结果,而不必再次执行函数。
-
当异步时,应该使用watch(参考官方文档: https://cn.vuejs.org/v2/guide/computed.html)
-
data 的变化,也会触发计算属性 filteredData 的值的变化,从而更新到 Dom。
markdown
-
methods 里面的 update 方法,有入参 e: InputEvent,e.target.value 是 textarea 的值
-
_.debounce 是 lodash 的防抖工具函数
modal
- 组件定义的2种示例:(总共3种,还有1种在move-animations里面)
// 定义一个名为 button-counter 的新组件
Vue.component('button-counter', {
data: function () {
return {
count: 0
}
},
template: '<button v-on:click="count++">You clicked me 8 times.</button>'
})
<!-- template for the modal component -->
<script type="text/x-template" id="modal-template">
<transition name="modal">
<div class="modal-mask">
<div class="modal-wrapper">
<div class="modal-container">
<div class="modal-header">
<slot name="header">
default header
</slot>
</div>
<div class="modal-body">
<slot name="body">
default body
</slot>
</div>
<div class="modal-footer">
<slot name="footer">
default footer
<button class="modal-default-button" @click="$emit('close')">
OK
</button>
</slot>
</div>
</div>
</div>
</div>
</transition>
</script>
<!-- app -->
<div id="app">
<button id="show-modal" @click="showModal = true">Show Modal</button>
<!-- use the modal component, pass in the prop -->
<modal v-if="showModal" @close="showModal = false">
<!--
you can use custom content here to overwrite
default content
-->
<h3 slot="header">custom header</h3>
</modal>
</div>
<script>
// register modal component
Vue.component('modal', {
template: '#modal-template'
})
// start app
new Vue({
el: '#app',
data: {
showModal: false
}
})
</script>
- 事件的处理:
modal 组件内的 button 的 click 事件:@click=”$emit(‘close’)” -> modal 组件的 click 事件:@close=”showModal = false” -> 修改 vue 实例 app 的 data,或调用 vue 实例 app 的方法
- demo中有1个 transition tag, Vue 提供了 transition 的封装组件,在下列情形中,可以给任何元素和组件添加进入/离开过渡
move-animations
-
vue 实例里面,components 定义了一个 item 组件
-
lodash shuffle函数, 创建一个被打乱元素的集合
select2
-
vue 实例里面,直接使用 template 属性,使用 html 的 demo-template 模板
-
这个demo有点复杂,没看懂
其他demo
awesome-vue: 太多东西了,各种资源,教程,开源项目,等等
vue-typescript-dpapp-demo
https://github.com/SimonZhangITer/vue-typescript-dpapp-demo
- template 竟然可以这样写
<template lang="pug">
.main-wrapper
v-header
.content-wrapper
modules
div(v-if="load")
headline
board
super_sale
shop_list
.loading(v-else)
</template>
vue-loader 支持使用非默认语言,比如 CSS 预处理器,预编译的 HTML 模版语言,通过设置语言块的 lang 属性。例如,你可以像下面这样使用 Sass 语法编写样式:
<style lang="sass">
/* write Sass! */
</style>
更多细节可以在预处理器中找到。
模版的处理方式略有不同,因为大多数 webpack 模版处理器 (比如 pug-loader) 会返回模版处理函数,而不是编译的 HTML 字符串,我们使用原始的 pug 替代 pug-loader:
npm install pug –save-dev
<template lang="pug">
div
h1 Hello world!
</template>
- 通过https://github.com/WingGao/mpvue-ts-demo 这个demo,尝试将项目转为小程序,发现太多问题,解决不了,因为很多东西不了解,比如typescript,vuex等等。还是要先打基础,需要更多的时间投入学习
vuejsexamples
https://vuejsexamples.com
Mall-Vue
https://github.com/PowerDos/Mall-Vue
这是一个基于VUE + VUEX + iView做的一个电商网站前端项目, 附带前后端分离实现版本(在forMallServer分支),很强大,要学一下
项目预览地址(demo): https://powerdos.github.io/Mall-Vue/index.html