vue 可以挂载界面元素

nvm

NVM, 全名为"Node Version Manager", 是非常好用的Node版本管理器。

  1. 安装
  2. 新建一个页面
  3. 做一些简单的变量的渲染
  4. 实现页面的跳转 (路由)
  5. 实现页面间的参数的传递 (路由)
  6. 实现真实的http请求(访问接口)
  7. 提交表单
  8. 使用一些技巧来让代码层次化(组件)
1
2
3
4
在Vuejs中创建页面需要两步:

1. 新建路由
2. 新建vue页面

使用

载入

1
<script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script>

webpack

1
npm i @vue/cli -g

指令

指令决定怎么渲染data里面的数据

  • v-text —— 将数据解析为纯文本。另外还可以使用 {{ }},它也会将数据解析为纯文本,与 v-text 的区别就是花括号在网络加载慢的时候会显示 {{ *** }}。
  • v-html —— 输出真正的 HTML,在 v-html 中可以使用 HTML 标签,但是请注意防范 XSS 攻击。
  • v-if —— 通过值 true 或者 false添加/删除标签,一般会结合三元表达式使用。与 v-show 的区别是,v-if 的标签,如果为 false 是直接删掉该节点,而 v-show 是通过 display:none 来控制标签。同时,v-ifv-else-ifv-else 可以配套使用。
  • v-show —— 通过值 true 或者 false 来切换 display 显示/隐藏标签,一般会结合三元表达式。
  • v-for —— 常见形式:v-for="(item, index) in itemsitem 是单个元素,index 是数组下标。其他形式:v-for="item of items
  • v-bind —— 可以通过 v-bind 或者其简写 :bind 绑定到 HTML 的属性字段上,例如 <a> 标签动态绑定 url 的时候 :url 或者自定义属性 :disabled 或者动态绑定 classstyle 中使用 :classstyle 等……
  • v-on —— 可以通过 v-on 或者其简写 @ 来绑定到 HTML 事件上,例如点击事件 @click 或者鼠标回车事件 v-on:keyup.enterv-onmethods 是一对搭档。
  • v-model —— 双向数据绑定。通常与 <input><textarea><select> 进行绑定。
  • v-once —— 只渲染元素和组件一次。之后重新渲染,该元素及其子元素会被视为静态内容忽略。

数据监听

watchcomputed

  • computed 强调计算。例如 c = a + b,因为你只要显示 c,所以不需要理会 ab 的值是否动态传入,只需要使用 computed 监察 c 即可。
  • watch 属性强调自身值的变化前后的动作。如果需要完成 c = a + b,那么你需要 watch 数据 ab 的变化,在这两者变化的时候,在方法中执行 c = a + b
  • watch 在处理异步操作或者开销较大的操作上有优势。执行异步操作不能串行返回结果、执行开销较大的操作避免堵塞主线程的时候,使用 watch
  • 简单且串行返回的,使用 computed
  • computed 对绑定的值有依赖,如果每次操作的值不变化,则不进行计算,具有缓存特性。
  • watch 会侦听前后变化的状态,无论操作的值是否变化,都会执行定义的函数体,所以会有 data(newVal, oldVal)

样式

类型 说明
:class 动态绑定 Class,可以通过多分类::class="{ a: true, 'b', c: false },或者结合计算属性 :class="computedClass",或者通过三元表达式::class="{ a ? a == 1 : a == 2 }"
:style 动态绑定行内样式,如果是 font-size 之类的,最好通过驼峰式 fontSize 来编写。如果采用 :style="{styleOne, styleTwo}" 的形式,当遇到 transform 时,Vue 会自动添加相应的前缀。

数组操作

改变原数组的方法

  • push() - 向数组尾部添加元素
  • pop() - 删除并导出数组最后一个元素
  • shift() - 删除并导出数组第一个元素
  • unshift() - 向数组开头添加元素
  • splice() - 向数组中添加/删除元素并返回新的数组
  • sort() - 排序
  • reverse() - 反转数组

不改变原数组的方法

  • filter() - 过滤数组
  • concat() - 拼接两至多个数组
  • slice() - 获取数组指定位置数据

不改变原数组的方法比改变原数组的方法高效,至于怎么姿势才爽,那就看个人感受了。

事件修饰符

  • .stop - 阻止事件冒泡。例如:@click.stop="say" 阻止 say 方法传递到上一级 DOM。
  • .prevent - 阻止默认事件。例如:@click.prevent="say",阻止点击事件,然后执行 say
  • .capture - 给元素添加监听器,在一个 HTML 模块中,如果有 4 层嵌套,前 2 层使用了 .capture 修饰符,第 3/4 层未使用,点击第 4 层触发点击事件,则顺序为:1 -> 2 -> 4 -> 3,因为 .capture 会先触发。
  • .self - 只触发该 DOM 本身的事件。相比于 .stop 阻止事件冒泡,.self 忽略事件冒泡和捕获的影响。
  • .once - 事件将只会触发一次。例如:@click.once='doOnce'doOnce 只会执行一次。
  • .passive - 不要阻止事件的默认行为。例如:v-on:scroll.passive="onScroll",在进行滚动的时候同时执行 onScroll,而不是等 onScroll 执行完再滚动。

按键修饰符

v-on:keyup.13 = @click.enter

  • .enter - 回车
  • .tab - Tab 键
  • .delete - Back Space 或者 Delete
  • .esc - Esc 键
  • .space - 空格键
  • .up - 上箭头
  • .down - 下箭头
  • .left - 左箭头
  • .right - 右箭头
  • .ctrl - Ctrl 键
  • .alt - Alt 键
  • .shift - Shift 键

父子组件及其通讯

  • 基础组件的写法
  • 全局组件与局部组件
  • 父组件传递数据给子组件
  • 子组件传递数据给父组件
  • 父子组件的 v-model 实现
  • <slot> - 默认插槽与其具名插槽
  • :is 的灵活应用
  • <keep-alive> 缓存状态,避免重新渲染

静态赋值 propstitle="My name is jsliang";动态赋值 props:title="article.title + ' by ' + article.nameprops 可以传入 StringNumberBooleanArrayObjectDateFunctionSymbol 并且对其进行以上类型验证。

过渡动画

  • 单组件过渡 <transition>
  • 过渡 6 状态:v-enterv-enter-activev-enter-tov-leavev-leave-activev-leave-to
  • 过渡系统 + 第三方 CSS 动画库(Animate.css
  • 过渡时间::duration
  • 过渡钩子:@:before-enter@:enter@:after-enter@:enter-cancelled@:before-leave@:leave@:after-leave@:leave-cancelled
  • key<transition> 的作用
  • 过渡模式:in-outout-in
  • 数字过渡
  • 颜色过渡

自定义指令

  • 局部指令:directives
  • 全局指令:Vue.directive
  • 自定义指令钩子函数:bindinsertedupdatecomponentUpdatedunbind

作用

  • focus 自动聚焦

过滤器

使用方法:{{ message | messageFilter }},然后定义 filters: { messageFilter(value) { // ...代码 } }

  • 局部过滤器
  • 全局过滤器
  • 串联过滤器

Vue Router

  • Vue Router 的基础使用。
  • 动态路由匹配,动态设置匹配路径,动态匹配任意路径。
  • 路由可以嵌套匹配,每个页面都可以有自己的 <router-view></router-view>
  • 编程式导航:不仅可以通过 <router-link :to="..."></router-link> 来定义导航链接,也可以通过 router.push("...") 的形式来实现。同时,我们还可以采用 router.replace("...") 来实现路由替换,通过 router.go(n) 来实现前进或者后退多少步路由。
  • 命名路由的两种形式:在 <router-link> 中通过 :to="{name, params}" 或者在 router.push() 中通过 {name, params} 来定义。
  • 一个页面可以同时存在多个 <router-view>,只需要通过给它们命名 name 就可以实现。
  • 路由可以通过 redirect 进行重定向,或者通过 alias 取别名,从而自由地将 UI 结构映射到任意的 URL。
  • 路由还可以进行传参,通过取代与 $route 的耦合或者通过 props 解耦。其中有三种模式:布尔模式、对象模式以及函数模式。
  • Vue Router 的默认模式是 hash 模式,我们可以通过 mode,将其设置为 history 模式。
  • 通过 router.beforeEach((to, from, next) => { ... }) 来注册全局路由守卫,它会在访问某个路由前进行拦截。其中 to 为即将进入的目标,from 为当前路由即将离开的位置,next 类似于 Promise 的 resolve。在 2.5+ 版本添加了 router.beforeResolve,作用类似于 router.beforeEach
  • 路由全局后置钩子:router.afterEach((to, from) => {})
  • 可以针对某个路由进行守卫,即在 new VueRouter({}) 中通过 beforeEnter: (to, from, next) => {} 进行守卫。
  • 可以直接在路由组件中定义:beforeRouteEnterbeforeRouteUpdate 以及 beforeRouteLeave
  • 完整的导航解析流程:
  1. 导航被触发。
  2. 在失活的组件里调用离开守卫。
  3. 调用全局的 beforeEach 守卫。
  4. 在重用的组件里调用 beforeRouteUpdate 守卫。
  5. 在路由配置里调用 beforeEnter
  6. 解析异步路由组件。
  7. 在被激活的组件里调用 beforeRouteEnter
  8. 调用全局的 beforeResolve 守卫。
  9. 导航被确认。
  10. 调用全局的 afterEach 钩子。
  11. 触发 DOM 更新。
  12. 用创建好的实例调用 beforeRouteEnter 守卫中传给 next 的回调函数。
  • Vue Router 通过定义 meta,可以制定路由鉴权,缓存,标题信息等。
  • 通过给 <router-view> 添加 <transition> 包裹,并给 <transition> 设置不同的 name,则添加过渡效果。同时,可以根据当前路由与目标路由的关系,动态设置过渡效果。
  • Vue Router 的引用,可以让我们动态设置数据是在导航完成之后获取还是在导航完成之前获取。
  • 路由可以设置滚动行为,在切换到新路由时,可以滚动到顶部或者保持原先的滚动位置。
  • 当路由过多,组件过大的时候,我们应该把不同的路由对应的组件分割成不同的代码块,从而使这些路由被访问的时候才加载对应组件,从而提高加载效率。使用 const Foo = () => import('./Foo.vue') 即可。同时,这些组件都可以通过 /* webpackChunkName: "***" */ 的形式,进行命名 chunk。

Vue Cli

  • 安装:npm install -g @vue/cli
  • 创建项目:vue create my-project 或者 vue ui
  • 兼容 VueCli 2.0 版本:npm i @vue/cli-init,然后就可以使用 vue init webpack 了。

Vuex

  • 为什么使用 Vuex ?
  1. 数据的综合交错,很容易使代码难以维护。
  2. 数据传参非常繁琐,尤其是兄弟组件。
  • 什么情况下使用 Vuex ?
  1. 开发大型应用
  2. 数据庞大且繁杂

命名规范

知识点 1. 组件名应该始终是多个单词的,根组件 App 除外。这样做可以避免跟现有的以及未来的 HTML 元素相冲突,因为所有的 HTML 元素名称都是单个单词的。例如:todo-itemTodoItem

知识点 2. 只要有能够拼接文件的构建系统,就把每个组件单独分成文件。例如:

1
2
3
components/
|- TodoList.vue
|- TodoItem.vue

知识点 3. 单文件组件的文件名应该要么始终是单词大写开头 PascalCase,要么始终是横线连接 kebab-case。例如:

1
2
3
4
5
6
7
components/
|- MyComponent.vue

或者

components/
|- my-component.vue

知识点 4. 基础文件名,即应用特定样式和约定的基础组件 (也就是展示类的、无逻辑的或无状态的组件) 应该全部以一个特定的前缀开头,比如 BaseAppV。例如:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
components/
|- BaseButton.vue
|- BaseTable.vue
|- BaseIcon.vue

或者

components/
|- VButton.vue
|- VTable.vue
|- VIcon.vue

知识点 5. 如果某个组件,像菜单栏、左侧菜单一样,全局中只拥有一个,那就以 The 前缀命名。例如:

1
2
3
components/
|- TheHeading.vue
|- TheSidebar.vue

知识点 6. 和父组件紧密耦合的子组件应该以父组件名作为前缀命名。例如:

1
2
3
4
components/
|- TodoList.vue
|- TodoListItem.vue
|- TodoListItemButton.vue

知识点 7. 组件名应该以高级别的 (通常是一般化描述的) 单词开头,以描述性的修饰词结尾;并且组件名应该倾向于完整单词而不是缩写。例如:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
components/
|- SearchButtonClear.vue
|- SearchButtonRun.vue
|- SearchInputQuery.vue
|- SearchInputExcludeGlob.vue
|- SettingsCheckboxTerms.vue
|- SettingsCheckboxLaunchOnStartup.vue

而不是

components/
|- ClearSearchButton.vue
|- ExcFromSearchInput.vue
|- LaunchOnStartupCheckbox.vue
|- RunSearchButton.vue
|- SearchInput.vue
|- TermsCheckbox.vue

全局规范

知识点 1. 尽量别在组件模板中使用 JS 来 bb 套太多话语,毕竟 HTML 就尽量让它做 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
26
|- HTML
<img
  src="https://vuejs.org/images/logo.png"
  alt="Vue Logo"
>
{{ normalizedFullName }}


|- JS
// 复杂表达式已经移入一个计算属性
computed: {
  normalizedFullName: function () {
    return this.fullName.split(' ').map(function (word) {
      return word[0].toUpperCase() + word.slice(1)
    }).join(' ')
  }
}

而不是

|- HTML
{{
  fullName.split(' ').map(function (word) {
    return word[0].toUpperCase() + word.slice(1)
  }).join(' ')
}}

知识点 2. 尽可能在 HTML、CSS 中使用双引号("),在 JS 中使用单引号(’)。例如:

1
2
3
4
5
6
7
8
9
<input type="text">

<AppSidebar :style="{ width: sidebarWidth + 'px' }">

而不是

<input type=text>

<AppSidebar :style={width:sidebarWidth+'px'}>

JS 规划

知识点 1. 组件的 data 必须是一个函数。当在组件中使用 data 属性的时候 (除了 new Vue 外的任何地方),它的值必须是返回一个对象的函数。例如:

1
2
3
4
5
data() {
  return {
    name: 'jsliang'
  }
}

知识点 2. Prop 的定义应该尽量详细,至少指定其类型。并且在声明的时候采用 camelCase,在使用的时候采用 kekab-case。例如:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
<WelcomeMessage greeting-text="hi"/>

props: {
  status: {
    type: String,
    required: true,
    validator: function (value) {
      return [
        'syncing',
        'synced',
        'version-conflict',
        'error'
      ].indexOf(value) !== -1
    }
  },
  greetingText: String
}

知识点 3. 总是用 key 配合 v-forkey 的作用:a.key 的特殊属性主要用在 Vue 的虚拟 DOM 算法,在新旧 nodes 对比时辨识 VNodes。b. 在 v-for 中使用 key,方便 Vue 跟踪每个节点,从而重用和重新排序现有元素。例如:

1
2
3
4
5
6
7
<ul>
  <li v-for="item in items" :key="item.id">...</li>
</ul>

<transition>
  <span :key="text">{{ text }}</span>
</transition>

知识点 4. 永远不要把 v-ifv-for 同时用在同一个元素上。例如:

1
2
3
4
5
6
7
8
<ul v-if="shouldShowUsers">
  <li
    v-for="user in users"
    :key="user.id"
  >
    {{ user.name }}
  </li>
</ul>

CSS 规范

知识点 1. 为组件样式设置作用域。给每个组件的 CSS 使用 scoped,避免组件之间的样式互相影响。

1
2
3
4
5
6
<style module>
.button {
  border: none;
  border-radius: 2px;
}
</style>