昨天大概粗糙的了解了一下 vue 的概况之后, 并没有从框架, 语法的细节来进一步学习. 那今天通过一个简单的实例来继续完善一下 Vue 这方面的空白, 用一些看得见的效果摸的着的代码在不断完成小目标的过程中慢慢消化一下相关的知识点. 当然用一个简单的实例来完全掌握 Vue 也不太现实, 只是通过这样一个例子来树立学习的信心, 了解 Vue 基础知识点.
Vue-cli-todolist, 是一个用 vue-cli3 工具初始化项目, 然后在此基础上完成 todolist 的案例, 相关的技术栈: Vue-cli3, Vue,VueRouter,Vuex.Element-ui,IView, Vux 等 UI 组件为辅助.
先看一下我们完成的效果:
https://jikeytang.github.io/vue-cli-todolist/
参考自: 所有前端技术实现的 todomvc.com http://todomvc.com/
尤大 vue-totolist
1. 安装 Vue-cli
分享前的约定: 以下大部分命令步骤基于 Mac 系统, Windows 系统差异点也会提到.
1.1 先在 GitHub 建立仓库
为了保持代码能够长期有效, 也方便面试时展示, 建议将代码以 Git 的方式存放, 比如: http://github.com,http://gitee.com,https://bitbucket.org / 等等. 选择任意一款新建仓库: vue-cli-todolist,Git clone 仓库到本地 (Windows 系统建议非桌面的盘符路径存储, 比如 D:/vue-todolist), 然后 cd .., 在 iTerm 新建一个 tab 准备进行安装 Vue-cli, 留存当前的 tab 等安装完成之后运行 NPM run serve.
1.2 Vue-cli 的作用
本地生成文件和配置, 减少繁琐的配置, 以最短的时间最小的文件结构让项目先跑起来, 让更多的精力关注开发本身. vue-cli3 中 vue.config.JS 不是必须, 新建之后自动覆盖默认设置.
那如果不使用 vue-cli 那怎么办? 就是手动在本地创始化 package.JSON, 然后其它相应文件手动创建手写配置, 效率低, 出错可能大.
1.3 Vue-cli 的全局安装
如果有旧版 vuecli 先得卸载, 然后才能安装新版.
- NPM uninstall -g vue-cli
- vue -V
输出: vue 不是内外部命令时说明卸载成功, 同样, 新版安装成功通过这个命令来验证.
安装前提必须安装 https://nodejs.org/en/ , 安装完之后通过 node -v 来确定是否安装成功, 如果输出类似 v10.15.3 字样表示安装成功.// 同时也安装了 NPM, 输入以下命令来确认 NPM -v, 如果输入 6.4.1 字样表示安装成功. call:node
通过
NPM install -g @vue/cli
命令安装最新版, 其中 - g 的意思是安装到全局, 就像一个全局变量一样, 以后在任何一个目录都可以运行创建命令 vue create.
PS: 如果是使用 Mac 的同学此处可能需要增加 sudo, 完整的命令就是这样:
sudo NPM install --global vue-cli
, 否则会报这样的错误
Error: EACCES: permission denied, access '/usr/local/lib/node_modules'
, 如果是 Windows 同学注意在右键用管理员方式打开 cmd.
vue create vue-cli-todolist
通过此命令在原来 Git clone 项目的 Tab 中来创建一个项目.
这时会有三个选项选择,
- Overwrite
- Merge
- Cancel
建议选择 Merge, 如果是 Overwrite 会删除. Git 隐藏文件, 导致不能进行 Git commit, 安装完成后通过 vue -V 来验证是否安装成功, 如果输出 3.7.0 这样的字样, 就说明安装成功了.
- $ cd vue-test
- $ NPM run serve
根据命令行中提示的端口号, 就可以预览到一个基础的项目页面.
然后删除根目录下. gitignore 文件中的 dist 目录, 说明以后 dist 目录也需要提交上传, Git 提交代码, 推送到远程, 在 GitHub 仓库刷新页面看到代码结构, 说明代码远程推送成功.
NPM i vue-router -S
通过此命令来安装路由组件, 很多朋友刚开始不太会区分 - S,-D 的区别, 这个 - S 表示上线依赖, 是 --save 缩写, 表示上线之后还需要存在的代码块, 比如 vue.js, 对应 package.JSON 中的 dependencies: {},-D 表示开发依赖, 是 --save-dev 缩写, 表示只是在开发阶段使用, 上线之后只使用他的结果文件就可以了, 比如 Sass-loader, babel, 对应 package.JSON 中的
- devDependencies: {
- }
- .
NPM i Sass-loader -D 通过此命令来安装我们后面用到的 SCSS, 也可以通过一个命令用空格分隔安装多个组件, 比如: NPM i Sass-loader vue-loader -D.
ps: call:NPM
2. 路由的配置
增加路由的目的还是为了让我们更方便的进行编程, 比如: 有些页面需要用户登录之后才能访问? 比如有些页面进入之后后退就不让他进入这个页面? 等等这样的场景都可以通过路由来实现.
在 src 目录下新建 router.JS, 引入相关的对象, 然后 use, 最后 export.
- import Vue from 'vue'
- import Router from 'vue-router'
- Vue.use(Router)
- export default new Router({
- routes: [
- {
- path: '/',
- name: 'home',
- component: () => import('@/views/home'),
- }
- ],
- })
这样 router 路由我们就建好了, 但是他还没有被使用, 所以还需要在 main.JS 中引入之后被使用, 这样配置的路由才会起作用, 根据路由访问时才会跳转到期望的画面.
- import router from './router'
- new Vue({
- router,
- render: h => h(App),
- }).$mount('#app')
然后刷新页面, 多了一个 /#/, 最后显示为
http://localhost:8080/#/
, 且显示画面没有报错, 说明我们的路由配置文件添加成功.
3. Sass-loader
加入 SCSS 的目的是让我们更快更方便的方式编写 CSS, 了解一下.
需要在项目中使用 SCSS, 只需要在. vue 组件中的 style 中添加 lang="scss", 就可以使用了:
- <style lang="scss">
- </style>
- //node-Sass 包比较难安装, 需要多次重新安装.
但是添加之后命令工具报错
Can't resolve'Sass-loader'
, 这时候就需要我们通过命令
NPM i Sass-loader -D
来安装依赖. 他主要的功能就是负责把 SCSS 编译为 CSS.
安装完成之后, 还是会报 Cannot find module 'node-sass', 我们继续 NPM i node-Sass -D 安装依赖.
安装完成之后刷新页面还是报错, 这时候需要重新启动服务了. 具体步骤为先: ctrl+c 停止服务, 然后输入命令 NPM run serve 启动, 再刷新页面, 画面重现.
因为这次的重点是 Vue-cli, 所以相关 html, CSS 直接复用, 刚好 todo 相关 CSS 已经有 NPM 包, 我们直接安装相关 CSS 模块,
NPM i todomvc-common todomvc-App-CSS -S
, 然后在 main.JS 中引入:
- import 'todomvc-common/base.css'
- import 'todomvc-app-css/index.css'
那到这一步我们前期的准备工作已经完成了, 下面就是根据页面特点进行组件的拆分了.
4. 组件
拆分组件的难点在于, 组织结构上趋于分散, 但数据处理上趋于集中, 集中的数据便于管理或驱动页面视图.
组件是 Vue 开发当中最小的组成单元, 以. vue 扩展名结尾, 他包括: HTML 结构, JS, CSS, 数据流, 监听处理子组件触发事件, 引用子组件 (ref).
如何拆分是一个开发习惯, 并没有一个准确的原则, 细拆可以拆分一个按钮为一个组件单元, 但拆的越细坏处是会造成页面维护的困难, 好处是页面组件的复用性更好. 如果拆的少, 组件结构关系比较简单, 但是页面组件复用性不高, 最终要达到期望效果还是要平衡和取舍.
根据当前页面的特点, 大体拆分为以下四个部分, 分别为: Header, List, Footer, Copyright, 新建对应的 *.vue 文件并且放置在 vue-cli-todolist/src/components 目录下, 然后相应的组件在 vue-cli-todolist/src/views/home.vue 中引入, 然后在增加:
components:{ Header, List, Footer }
需要注意的是 Copyright 在整个操作容器外部, 所以放在 App.vue 中.
4.1 home.vue
由于 Vue 单数据流的限制规则, 此组件页面是操作整个 Todolist 数据源的总页面, 所有对数据的操作方法都汇总在此组件来实现, 包括子组件对数据源的操作. 父级 prop 值的更新会向下传递, 但不能反向传递, 也不能在子组件直接修改 prop. 这样做的目的是为了防止从子组件意外改变父级组件的状态, 从而导致数据流向难以理解. 其实对 Todolist 的操作, 就是常说的是增删改查, 只是少了一个查找而已, 页面上的常规操作就是对 Todolist 数据源对象的的增加删除修改, 那对应的代码其实就是数据的 push, splice, forEach 等方法. 需要注意的是这些操作数据的结果都是基于浏览器的, 刷新之后并不存在, 解决办法后端接口存储和本地存储, 本案例中通过 localStorage 存储在本地.
然后我们找一行有特征引入组件的方式来分析一下, 比如:
<main-view :todos="filteredTodos" @del-todo="delTodo" @all-done="allDone"></main-view>
main-view 表示组件名称, 如果是全局组件那名称是唯一的.
:todos="filteredTodos", 冒号表示变量是动态的, 如果不是冒号默认是 String,todos 表示子组件接受数据的变量名称, filteredTodos 表示当前页面的变量名称. 子组件中通过 props 属性来接受父组件传来的数据, 通过 $emit 的方法触发事件然后在父组件修改数据, 整个的数据即能灵活的传下去, 也能有效的回转回来.
@del-todo="delTodo",@表示事件处理, del-todo 为子组件 $emit 方法名, delTodo 为当前组件事件处理方法名. 组件数据通过
:todos="filteredTodos"
传下去, 然后通过
@del-todo="delTodo" @all-done="allDone"
进行捕获处理.
4.2 Header.vue
home.vue 中输入
<header>....</header>
, 刷新页面之后发现并没有达到期望的效果, 只有
<header>....</header>
的代码片段. 这时候就发现组件名称不能与 HTML 的原有标签名称重复, 否则当普通的 HTML 标签解析. 修改 Header.vue 为 HeaderView.vue 之后刷新页面, 得到期望结果页面. 另外的一个办法就是大写, 比如:
- <Header>
- ....
- </Header>
- .
4.3 Main.vue
此页面虽然 HTML 元素不多, 但需要处理的东西还是挺多, 包括点击进行中处理, 双击进入编辑状态,.enter.blur 事件退出编辑状态, 基本每个 HTML 元素上都需要 JS 代码的处理, 这里边大概有这几点分享:
- 4.3.1 template
- v-model
扩展为:
- <input v-model="field" />
- <input :value="field" @input="field = $event.target.value" />
每当输入框内容发生变化时, 就会触发 oninput , 把最新的 value 传递给 field.
:class
对象语法 { active: isActive, 'text-danger': hasError }, 通过 Boolean 值控制是否有值
数组语法 [activeClass, errorClass], 通过变量合并显示
文档: https://cn.vuejs.org/v2/guide/class-and-style.html
@dblclick,@click
绑定事件的缩写形式, 完整的为: v-on:click="handle"
文档: https://cn.vuejs.org/v2/guide/events.html
{{ item.title }}
基础变量显示, 原始 HTML 需要 v-HTML="rawHtml" 指令.
- https://cn.vuejs.org/v2/guide/syntax.html
- @keyup.enter.prevent
通过事件修饰符连写, 达到处理冒泡, 阻止自定义事件等等的目的
- https://cn.vuejs.org/v2/guide/events.html
- computed -> set || get
一般计算属性默认都是 getter, 全选的处理需要主动的修改数据源.
- https://cn.vuejs.org/v2/guide/computed.html
- 4.3.2 script
props 接受数据, data 初始化变量
computed 中 allDone 通过进行中的数量是否为零来有效的在初始化时得到全选的状态.
util 方法就是对跨组件代码块复用的封装 export 然后 import 之后使用.
4.3.3 style
vh
css3 新单位, 相对于视口的高度的百分比, 视口被均分为 100 单位的 vh,1vh = 视口高度的 1%.
- h1 {
- font-size: 8vh;
- }
如果视口的高度是 200px, 那么上述代码中 h1 元素的字号将为 16px, 即 (8x200)/100=16
4.4 Footer.vue
点击状态每次切换需要切换画面, 画面的变化依赖于路由, 所以需要记录路由名称 this.current, 在 home.vue 中通过 watch 来实现:
- '$route' (to) {
- this.current = to.name
- },
4.5 Copyright.vue
版权页面布局采用 Flex 形式布局. 扩展认识: Flex 垂直水平居中对齐 https://juejin.im/post/58e3a5a0a0bb9f0069fc16bb
5. main.JS
如果说 App.vue 是项目的组件入口文件的话那么 main.JS 就是项目的代码入口, 所有相关 JS 的初始化以及 NPM 包的引用都在此文件处理. ES6 规定, import 必须放在首行, 有的组件需要 Vue.use, 有的则不需要.
Vue 全家桶相关的 Router, Vuex 都需要在此文件绑定.
6. package.JSON
dependencies 上线依赖, NPM i -S moduleName
devDependencies 开发依赖 NPM i -D moduleName
同时习惯于 vue-cli2 NPM run dev 方式的同学, 也可以在 package.JSON 中增加:
- "scripts": {
- "dev": "npm run serve",
- "serve": "vue-cli-service serve"
- }
可以用 NPM run dev 继续运行当前项目.
7. package-lock.JSON
记录当前状态下实际安装的各个 NPM package 的具体来源和版本号, package.JSON 文件只能锁定大版本, 也就是版本号的第一位, 并不能锁定后面的小版本你每次 NPM install 都是拉取的该大版本下的最新的版本, 为了稳定性考虑几乎是不敢随意升级依赖包的, 这将导致多出来很多工作量, 所以 package-lock.JSON 安装一个依赖的时候就锁定在你安装的这个版本.
8. NPM run build
在根目录增加 vue.config.JS,CSS,JS 默认访问根目录, 而我们发布之后的目录是 http://www.host.com/dist/, 多了一层 dist, 所以需要配置 publicPath, 否则控制台报找不到资源的错误:
- module.exports = {
- publicPath: './',
- productionSourceMap: false
- }
至此为止, 今天阶段性的学习就到此告一段落了. 学习到此处有疑问的同学, 加 QQ 群:
364912432
来源: https://www.cnblogs.com/jikey/p/10903699.html