vue2 初学者指北

好多年前写的笔记移动到博客上

vue 基础

历史背景 一款渐进式 javascript 框架 尤雨溪(Evan You)

特点

  • 轻量 20kb min + gzip
  • 渐进式框架
  • 响应式更新机制
  • 学习成本低

vue 基础

环境

  • Chrome
  • vs code
  • node.js 8.9+ npm
    1
    2
    3
    4
    5
    6
    //  vue 实例
    let app = new Vue({
    el: '#app',
    data: {
    }
    })
    1
    2
    VUE CREATE  PROJECTNAME
    SCOPED css样式限制在 单文件组件内

属性 (万物皆属性 )

自定义属性 Props
原生属性 attrs
特殊属性 class, style

事件

普通事件(绑定事件)
修饰符事件(.stop)

插槽

普通插槽(slot=xxx)
作用域插槽(slot-scope=xxx)
双向绑定 单项数据流
  • model 更新 触发 view 的更新
  • view 更新 触发 model 更新
vue 双向绑定 or 单项数据流
  • vue 是单项数据流 ,不是双向绑定
  • vue 的双向绑定不过是语法糖
  • Object.defineProperty 是用来做响应式更新的和, 双向绑定没关系
理解虚拟 DOM 和 key 属性的作用
  • index 最好不能作为 key
数据驱动(核心思想)
  • 任何直接更改 dom 的行为都是作死
  • 状态是组件的自身的数据
  • 属性时来自父组件的数据
  • 状态 或 属性 改变 未必会触发更新
  • 在 data 里的数据会做实例化 getter setter 操作 才是响应式的 否则改变数据并不会对组件进行更新
计算 属性和监听器
计算属性(大量数据缓存)
  • 减少模板中计算逻辑
  • 数据缓存
  • 依赖固定的数据类型(响应数据)
watch
  • 监听数据是否改变
  • deep:true 深度监听 E:{d:{f:{}}} 都能监听到
  • 灵活通用 可以执行任何逻辑, 函数节流 ajax 操作 dom
  • watch 和 computed 能用 computed 的时候尽量用 computed
生命周期和函数式组件
  • 创建阶段
  • beforeCreate (初始化事件和生命周期)
  • created (数据观测 属性 监听器配置等)
  • beforeMount (编译到 render)
  • render
  • mounted (异步请求,操作DOM 定时器等)
  • 更新阶段
  • beforeUpdate 依赖数据改变或$forceUpdate 强制刷新(移除已添加的事件监听器等)(万万不可更改依赖数据)
  • render
  • updated 操作dom 添加事件监听器等 (万万不可更改依赖数据
  • 销毁阶段
  • beforeDestory (移除已添加的事件监听器等 定时器等)
  • destroyed
  • this.$nextTack() 数据更新并不保证子组件更新 所以需要变动的代码需要放在这个函数里边
函数式组件
  • functional: true
  • 无状态 无实例 没有this上下文 ,无生命周期
指令的本质是什么
  • 内置指令
  • 语法糖 标志位
  • v-text
  • v-html
  • v-show
  • v-if
  • v-else-if
  • v-else
  • v-for
  • v-bind(:)
  • v-on(@)
  • v-model
  • v-pre
  • v-once
  • v-cloak(单文件无作用)
  • 自定义指令钩子
  • bind
  • inserted
  • update
  • componentUpdated
  • unbind
高级特性(组件跨层级通信)
  • provide
  • inject
获取跨层级组件实例
  • ref (元素获取元素dom节点)(组件获取实例)
  • callback ref (主动回调)
  • setXxxRef
  • getXxxRef
  • 使用 provide 和 inject 制作回调

trmplate 对比 JSX

  • template (html 的扩展)
  • jsx (javacript的扩展)

生态

vuex

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

// main.js
import vuex from 'vuex'
Vue.use(vuex)
const store = new vuex.store({
state: {
count : 0
},
mutations: {
add(state, 参数) {
state.count ++
}
},
actions: {
addAsync({state}) {
setTimeout(( state.count +=3 )=>{ } ,300)
}
},
getters:{
count: state => state.count
}
})

new Vue({
store,
render: h =>h(组件)
}).$mount(‘#app’)

// app.vue
computed: {
count() {
// 获取
return this.$store.state.count
}
}
// 修改
// mutation
$store.commit('add' ,可以传参)
// actions
$store.dispatch('addAsync' ,可以传参)
// 获取 getter 和计算属性一样会缓存
$.store.getters.count

最佳实践
…mapState …mapGetters …mapMutetions…mapActions
mutation-type 常量
命名空间
灵活应用 createNamespaceHelpers 辅助函数

vue-router

- 监听 url 变化 变化后执行相应逻辑
- 不同的 url 对应不同组件
- 提供多种方式改变 url 的api(url 的改变不能导致 浏览器刷新)

使用方式

- 提供路由配置表
- 初始化路由实例 new VueRouter()
- 挂载到 Vue 实例上
- 提供一个路由占位, 用来挂载 url 匹配到的组件
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<!-- 引入 -->
import VueRouter from 'vue-router'
import fouter from './routers'
Vue.use(VueRouter)
const router = new VueRouter({
routers
})

new Vue({

router,
render ()
})

<!-- 配置表 -->
import component from './component.vue'

const router = [
{
path: '/',
component: component,
name: '3',
props: true,
children: [
{
path...
}
]
}
]

export default router

<router-view></router-view> // 占位符
<router-link></router-link> // 路由跳转
this.$route.push({
path: '/'
}) // 跳转 api

路由类型

- hash 模式 丑 无法使用锚点定位
- history 模式 需要后端配合

Nuxt

spa 缺点

- 不利于 seo
- 首屏加载慢
- 解决方案
    - ssr 服务端渲染( 动态渲染)
    - 预渲染 prerenderting (适用于静态页面)

nuxt做的事情

- 静态站点
- 动态渲染
- 简化配置

nuxt 核心点

- 生成两个 main.js 文件 一个是服务端一个是客户端的 

实战 Ant Design Pro

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 vue create ant-design-vue  
- manually (自定义)
- default (默认)
- 空格选中
<!-- 自定义 vue cli 配置 -->
- 根目录创建 vue.config.js
- 配置参考 https://cli.vuejs.org/zh/config/#css-loaderoptions
- 配置根目录 babel.config.js
- npm i babel-plugin-import
<!-- ant-design-pro 参考 -->
plugins: [
[
"import",
{ libraryName: "ant-design-vue", libraryDirectory: "es", style: true }
] // `style: true` 会加载 less 文件
]
  • router-view 可以作为一个父组件 渲染出子组件的元素
  • 路由 动态绑定slide 菜单 主题等

福利

数组有哪些方法支持响应式更新, 如果不支持如何处理 底层原理

  • 支持 push ,pop,shift,unshift,splice,sort,reverse
  • 不支持 filter concat slice
    原理是用 Object.defineProperty

bug

  • 隐藏 bug for循环key 如果是index 在输入框下 会出现 如
  • a b c 三个输入框
  • 当删除 b 的时候 c 会被删除
  • 是因为 key 是 index 而删除的时候删除了 b的key
  • 而c 的key在渲染的时候变成了原来的 b 的key

开发工具

- vetur  无法高亮 标签补全 lint 检查 格式化
    - scop 快速搭建 vue 模板
- ESlint
    - 代码规范
    - 错误检查
- Prettier
    - 格式化
- vue DveTools (官方调试工具)
    - chrome 插件

单元测试的重要性 (选择性单元测试 30 )

一些库

- resize-detector