## 框架和库的区别?> 框架(framework):一套完整的软件设计架构和**解决方案**。> > 库(library):对常用功能性函数的**封装**。> > 一般也可以认为框架大而全,库小而精。一个框架中可以包含或者集成多个库。 + 框架:是一套完整的解决方案;对项目的侵入性较大,项目如果需要更换框架,则需要重新架构整个项目。 + 库(插件):提供某一个小功能,对项目的侵入性较小,如果某个库无法完成某些需求,可以很容易切换到其它库实现需求。## 数组方法扩展- `Array.prototype.forEach`:替代for循环对数组进行循环遍历```JavaScriptvar list = [1,2,3,4,5]list.forEach(function(v,i){ // v是当前遍历的这一个元素 i是这个元素的索引 console.log('当前元素是' + v,'当前元素的索引是' + i)})```- `Array.prototype.map`:对数组进行遍历,同时会返回一个新数组,新数组中的每一项都是回调函数中的返回值```JavaScriptvar list = [1,2,3,4,5]var newArr = list.map(function(v,i){ // v是当前遍历的这一个元素 i是这个元素的索引 console.log('当前元素是' + v,'当前元素的索引是' + i) return v * 2})console.log(newArr) // [2,4,6,8,10]```- `Array.prototype.findIndex`:对数组进行遍历,会返回一个满足回调函数条件的元素的索引```JavaScriptvar list = [1,2,3,4,5]var index = list.findIndex(function(v,i){ // v是当前遍历的这一个元素 i是这个元素的索引 console.log('当前元素是' + v,'当前元素的索引是' + i) if(v == 4){ // 当return true时终止循环 同时将该元素的索引返回给findIndex函数 return true } // 简写成 // return v == 4})console.log(index) // 3```- `Array.prototype.filter`:对数组进行遍历,返回一个新数组,新数组中的每一项都是满足回调函数中条件的元素,当满足条件时需要`return true````JavaScriptvar list = [1,2,3,4,5]var newArr = list.filter(function(v,i){ // v是当前遍历的这一个元素 i是这个元素的索引 console.log('当前元素是' + v,'当前元素的索引是' + i) if(v%2 == 0){ return true } // 简写成 // return v%2 == 0})console.log(newArr) // [2,4] ```- `Array.prototype.some`:对数组进行遍历,返回一个布尔值,判断当前数组中是否有一个元素符合回调函数中的条件(特点:只要一个元素满足条件,最终返回结果就是true)```JavaScriptvar list = [1,2,3,4,5]var flag = list.some(function(v,i){ // v是当前遍历的这一个元素 i是这个元素的索引 console.log('当前元素是' + v,'当前元素的索引是' + i) if(v % 2 == 0){ // return true时则终止继续循环 return true }})console.log(flag) // true// 注意: 由于遍历的数组第二个元素就满足了条件 所以循环到第二个元素时 就停止循环了```- `Array.prototype.every`:对数组进行遍历,返回一个布尔值,判断当前数组中是否每一个元素都符合回调函数中的条件(特点:只要一个元素不满足条件,最终返回结果就是false)```JavaScriptvar list = [1,2,4,6,8]var flag = list.every(function(v,i){ // v是当前遍历的这一个元素 i是这个元素的索引 console.log('当前元素是' + v,'当前元素的索引是' + i) if(v % 2 == 0){ // return true时则终止继续循环 return true }})console.log(flag) // false// 注意: 由于遍历的数组第一个元素就不满足条件 实际上循环一次就停止了```## Vue基础> MVC:对项目的整体把控,M代表的是数据库中的数据,V代表的是前端的视图层,C用于处理M和V之间进行交互的业务逻辑(业务逻辑需要程序员自己控制,自己编写)> MVVM:主要用于一些前端的框架,对MVC三层架构中的视图层再次进行层次划分,M是当前一个视图中需要用到的数据,V就是当前视图,VM负责M和V之间的数据调度,内部已经帮你完成了数据的绑定和交互> MVC和MVVM之间的区别:MVC数据流通是单向的,MVVM是双向数据绑定> 双向数据绑定的意思就是模型中的数据可以之间更新到视图上,视图中的数据发生改变也可以直接更新到模型中能够做到双向数据绑定(通信)的原因:就是因为有VM的存在,VM内部的实现一般是框架已经处理完成,不需要程序员进行控制- 双向数据绑定原理: `Object.defineProperty`存取器> 使用`Object.defineProperty`提供的set方法可以在给对象赋值时,触发额外操作,即在set函数内部去处理视图的更新```JavaScript// 使用 Object.defineProperty 可以给对象赋值var obj = {};Object.defineProperty(obj,'name',{ value:'zxx'})console.log(obj.name)var obj = {};var initValue = 'zxx'Object.defineProperty(obj,'name',{ get:function(){ console.log('我被读取了') return initValue }, set:function(v){ console.log('我被赋值了') initValue = v }})obj.name = 'lxy'console.log(obj.name)```### Vue基本编码步骤1. 引入vue.js文件2. 定义一个vue的管理范围
vue1.0里面vue的管理区域的id可以定义在HTML以及body标签上 vue2.0里面不允许这样来做3. 定义一个vue的对象 var vm = new Vue({ el:'#app', // data定义vue实例的所有属性 data:{ // 定义将来要在vue管理区域中使用的数据 name:"zs" }, // methods定义vue实例所有的方法 methods:{ fn:function(){ this.name = 'ls' } } })### Vue系统指令- `{{}}`:插值表达式``` 作用:将vue对象中的数据以及表达式显示到vue托管区域中 {{这里书写vue对象中data里面的数据或者表达式}}```- `v-cloak`:解决表达式闪烁问题```1. 定义一个样式 [v-cloak]{
display:none
}
2. 使用
{{name}}
原理:当vue.js文件还没有加载出来时 使用[v-cloak]样式作用于当前指令所在标签,当vue.js能够起作用时,会自动删除v-cloak指令``` - `v-text`:输出文本数据``````- `v-html`:输出HTML结构数据```
data:{name:'zs'}```- `v-bind`:动态给标签或者组件绑定属性```
// 使用:简写v-bind
// 变量和常量组合跳转data:{cls: 'red blue',id: 1}``` - `v-on`:绑定事件```
// 简写
methods: { // 这个 methods属性中定义了当前Vue实例所有可用的方法 show: function () { alert('Hello') } }```- `v-model`:双向数据绑定```// 可以使用的标签:input textarea select 组件// name会和表单元素的value进行关联 value值变化 name值变化 反过来name值发生变化 value值也会发生变化```- `v-for`:循环输出HTML元素```
{{item.name}}
```- `v-if`:根据表达式值的真假决定元素的显示隐藏```// isShow为true显示div 为false隐藏div// v-if是直接操作DOM 即隐藏时会将该div从DOM结构中移除
```- `v-show`: 根据表达式值的真假决定元素的显示隐藏```// isShow为true显示div 为false隐藏div// v-show是操作div的样式 显示时添加 style = 'display:block'; 隐藏时添加style = 'display:none'
v-if 是删除DOM元素 效率比较低 会造成页面的结构重新绘制v-show 是控制样式 只会改变当前这一个元素的样式 不会造成页面结构的重新绘制```### 在Vue中使用样式#### 使用class样式1. 数组```
这是一个邪恶的H1
```2. 数组中使用三元表达式```
这是一个邪恶的H1
```3. 数组中嵌套对象```
这是一个邪恶的H1
```4. 直接使用对象```
这是一个邪恶的H1
```#### 使用内联样式1. 直接在元素上通过 `:style` 的形式,书写样式对象```
这是一个善良的H1
```2. 将样式对象,定义到 `data` 中,并直接引用到 `:style` 中 + 在data上定义样式:```data: { h1StyleObj: { color: 'red', 'font-size': '40px', 'font-weight': '200' }}``` + 在元素中,通过属性绑定的形式,将样式对象应用到元素中:```
这是一个善良的H1
```3. 在 `:style` 中通过数组,引用多个 `data` 上的样式对象 + 在data上定义样式:```data: { h1StyleObj: { color: 'red', 'font-size': '40px', 'font-weight': '200' }, h1StyleObj2: { fontStyle: 'italic' }}``` + 在元素中,通过属性绑定的形式,将样式对象应用到元素中:```
这是一个善良的H1
```### 过滤器> `过滤器`:对需要展示的数据进行加工处理后再展示到界面,并不会改变原数据- 全局过滤器:当前页面所有Vue实例的托管区域都可以使用```JavaScriptVue.filter('过滤器名称',function(value,arg){ // value就是需要处理的原始数据 arg是使用过滤器时传递的参数 // 对数据处理的业务逻辑 return 处理完毕的数据})使用方法:原始数据 | 过滤器名称(参数)```- 私有过滤器:只有当前定义过滤器的Vue实例所托管的区域可以使用```JavaScriptnew Vue({ el:'#app', // 私有过滤器 filters:{ '过滤器的名称':function(value){ return 处理完毕的数据 } }})```### 自定义指令> `指令`: 其实就是Vue给我们提供的操作DOM元素的一些方法- 全局指令```JavaScriptVue.directive('指令名称',{ // 指令第一次绑定到元素身上时执行(在内存中绑定到了DOM对象上边) bind:function(el,binding,VNode){ // el: 指令所在的DOM元素对象 // binging.value 指令等号右边表达式的值 // binging.expression 指令等号右边表达式 // VNode.context 当前指令所在托管区域对于的Vue实例对象 }, // 当前指令所在元素插入到父节点时调用(不保证DOM已经渲染完毕) inserted:function(){}, // 指令绑定的值发生变化时会去执行 update:function(){}, // 指令所在的组件值更新完毕时调用 componentUpdated:function(){}, // 自定义指令从当前元素解绑时调用 unbind:function(){}})```- 私有指令```JavaScriptnew Vue({ el:'#app', // 私有指令 directives:{ '指令名称':{ bind:function(el,binding){ } } }, // 私有过滤器 filters:{ '过滤器的名称':function(value){ return 处理完毕的数据 } }})```## 生命周期钩子函数> 回调函数:一个函数被当做参数进行传递的时候,称作这个函数为回调函数> 构造函数:一个函数被new 关键字引导执行的时候,称作这个函数为构造函数> 钩子函数: 一个应用程序或者框架内部提前定义好的一批函数,这些函数会在特定的时间段自动执行>> 生命周期: 一个程序会存在初始化 - 运行 - 销毁等阶段,这些阶段统称为该程序的生命周期```new Vue({ el:'#app', data:{}, methods:{}, beforeCreated(){}, // data中的数据和methods中的方法已经初始化完毕会去自动执行created方法 created(){ // 用于发生数据请求,也可以初始化一些数据 }, beforeMount(){}, // 真实DOM已经渲染完毕会执行mounted函数 mounted(){ // 操作真实DOM } beforeUpdate(){}, // data中的发生了变化而且被重新渲染到了界面上时才会执行 updated(){ // 数据更新后重新操作DOM }, // 实例销毁之前,实例上面的各种属性和方法都还可以正常访问,通常可以在这里手动回收一些页面没有被释放的变量,比如清楚定时器的操作。 beforeDestroy(){}, // 实例已经从内存中被销毁 destroyed(){}})```## vue-resource发生ajax请求> vue.studyit.io```javascript// get请求this.$http.get('url').then(function(res){ // res.body 里面就是请求回来的数据})// post 请求 application/x-www-form-urlencode -> name=zs&age=18// application/json => {'name':'zs','age':18}this.$http.post('url',{name:'zs',age:18},{emulateJSON:true}).then(function(res){ // res.body})// jsonp请求this.$http.jsonp('url').then(function(res){ // res.body})```- **JSONP**:JSON数据格式的一种使用方式,用于解决跨域问题- **跨域**: 由于浏览器同源策略的限制,不同源的URL不能互相通信,这种现象叫做跨域- **同源策略**: 两个域名只有 **协议** **主机地址** **端口号**完全一致时才能相互通信访问- **JSONP实现原理**:利用script标签的src属性发送请求不受同源策略的限制这个机制去实现跨域资源共享(script标签能够跨域访问是历史遗留问题,并不安全) 1. 动态创建一个script标签,并且将需要请求的URL地址设置给script标签的src属性,同时在URL地址后面拼接上一个回调函数名称``` function getJson(data){ console.log(data) }// getJson就是在前端本地定义好的一个方法的方法名 ``` 2. 后台接收到该请求后,先根据参数判断是否是JSONP请求,如果是,则将客户端请求的数据整理好,和前端发送过来的方法名一起拼接成一个函数调用的字符串,客户端需要的数据就是这个函数调用时传的参数``` // 假设要发送给前端的数据是 'ok' 'getJson('ok')' // 响应给前端 res.end('getJson('ok')') ``` 3. 由于后台响应回来的数据是一个字符串,而且是函数调用,所以前端拿到响应回来的数据相当于调用了该方法,那么前端定义好的方法会自动执行,而且方法内的形参可以接收到实参值,也就是后台拼接的数据``` function getJson(data){ console.log(data) // ok }``` 4. 数据拿到之后,一般这个动态创建的script标签会被删除掉## vue过渡动画### 原生css类实现```JavaScript// 1. 将需要实现动画的元素使用transition标签包裹起来
我是p元素
我是span元素我是一个组件中的元素
我也是组件中的元素我是p元素
我是span元素"export default{",
" $2 ",
"}",
"","",
"$3 ",
""],"description": "create a vue template"}```## yarn的使用```// 1. 使用npm全局安装yarnnpm i yarn -g// 2. 初始化命令yarn init -y// 3. 安装包yarn add package-name // 会将安装的包记录到dependencies节点里面yarn add package-name --dev // 会将安装的包记录到devDependencies节点里面yarn global add package-name // 安装全局包// 4. 删除包yarn remove package-name// 5. 执行命令yarn run devyarn global bin 查看全局包安装的路径```## vue-cli脚手架的使用```// 1. 安装vue-cli脚手架npm i vue-cli -g// 2. 初始化项目模板vue init webpack 项目名称eslint(语法规范化插件) 不要安装 当安装之后只能按照ESLint中规定的语法格式去书写代码e2e(测试框架) 不要安装unit test(单元测试框架) 不要安装// 3. 进入项目安装所有依赖npm i// 4. 运行npm run devconfig/index.js中 17/18行改端口号和自动打开浏览器```## 将项目提交到码云```// 1. 在项目文件夹初始化gitgit init// 2. 将代码提交到暂存区git add .// 3. 提交代码git commit -m '描述信息'// 4. 关联远程分支git remote add origin https://gitee.com/UniverseKing/tes.git// 5. 推送到远程分支git push -u origin master// 6. 查看文件信息git status// 7. 查看loggit log --oenline// 8. 切换版本记录git reset --hard 版本号```## vue-loader深度作用选择器> 如果希望在父组件中去改变子组件中的样式,有时候通过普通子类选择器无法实现,主要是由于添加了`scoped`属性导致,`vue-loader`中提供了[深度作用选择器](https://vue-loader.vuejs.org/zh-cn/features/scoped-css.html)可以实现> 这种问题主要出现在使用第三方组件时,需要改第三方组件的样式时```CSS/*假设.content是父组件中的类 img是子组件中的标签*//*css中使用>>>*/.content >>> img {}/*scss或者less中使用/deep/*/.content /deep/ img {}```## Promise> `Promise` 是异步编程的一种解决方案.简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,`Promise` 是一个对象,可以从该对象获取异步操作的消息。```Promise有几种状态?Promise有三种状态promsie实例一被创建 默认就是pending状态(表示异步操作进行中)如果异步操作成功 状态会从 pending 变成 fulfilled(表示异步操作成功)如果异步操作失败 状态会从 pending 变成 rejected(表示异步操作失败)```### 基本用法```js// 1. 创建promise实例,在实例中执行异步操作(比如发送网络请求)// 2. 异步操作成功时,调用reslove函数传递数据// 3. 异步操作失败时,调用reject函数传递错误信息const promise = new Promise(function(resolve, reject) {// 异步操作// ... if (/* 异步操作成功 */){resolve(value);} else {reject(error);}});// 4. 使用promise实例then方法接收reslove或reject返回的数据promise.then(function(value) {// 此处数据即为reslove回来的数据 // success}, function(error) {// 此处数据即为reject回来的数据// failure});```### 网络请求案例```js// 1. 定义一个使用promise封装的请求函数,函数内部返回一个promise实例function fetch(){// 函数内部返回一个promise实例return new Promise(function(reslove,reject){// 发送异步请求axios.get('http://www.lovegf.cn:8090/api/getlunbo').then(function(res){// 请求正常if(res.status == 1){reslove(res.data)}else{reject(res.error)}})})}// 2. 调用函数发送请求,通过Promise.prototype.then方法获取resolve或reject出来的数据fetch().then(function(res){// res为reslove函数传出的数据},function(err){// err为reject函数传出的错误})```### 解决回调地狱> 假设有三个请求A、B、C,B请求需要依赖A请求的数据,C请求需要依赖B请求的数据.> > 传统回调函数式写法如下:```jsfunction dependices_fetch(){// A请求axios.get('A').then(function(res){if(res.status == 1){// B请求axios.get('B').then(function(res){if(res.status == 1){// C请求axios.get('C').then(function(res){// 请求完毕,执行后续逻辑})}})}})}```> 这种代码虽然能够满足业务,但是代码组织结构非常不便于阅读> > 通过Promise可以封装代码,使用链式方式解决这种多个异步依赖的回调> > 如下:```jsfunction fetch(url){return new Promise(function(reslove,reject){axios.get(url).then(function(res){if(res.status == 1){reslove(res.data)}else{reject(res.error)}})})}//then方法内部返回的promise实例reslove或reject出来的对象会在下一个then方法内部得到fetch('A').then(function(res){// A 请求正常return fetch('B')// 这里返回一个新的promise实例,在后面的then中可以得到该实例reslove或reject出来的对象}).then(function(res){// B 请求正常return fetch('C')}).then(function(res){// C 请求正常// 请求完毕})```### 多个异步请求结果组合问题> 假设有A、B、C三个异步请求,需要三个请求的数据都回来之后,将数据整合后再渲染页面,这种需求可以使用`Promise.all()`> > Promise.all方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。```jsfunction fetch(url){return new Promise(function(reslove,reject){axios.get(url).then(function(res){if(res.status == 1){reslove(res.data)}else{reject(res.error)}})})}const p1 = fetch('A')const p2 = fetch('B')const p3 = fetch('C')const p = Promise.all([p1, p2, p3]);p.then(function(res){// res是一个数组,存放着p1,p2,p3的返回值})```## async 和 await 的使用> async 和 await 是ES7中新提供的两个操作异步函数的关键字,本质是对Promise进一步的封装> await 只能用在 async 定义的函数内部,await 可以等待异步操作,并同步的得到异步操作的返回值```JavaScript// 1. 基于Promise的异步操作函数const fs = require('fs')function getFileByPath(fpath) { return new Promise(function (resolve, reject) { fs.readFile(fpath, 'utf-8', (err, dataStr) => { if (err) return reject(err) resolve(dataStr) }) })}// 2. 基于 await 的异步依赖问题(异步操作3依赖异步操作2,异步操作2依赖异步操作1)// 2.1 先使用async定义异步操作const start = async function(){// 2.2 在async内部使用await 同步操作 const n1 = await getFileByPath('./1.txt') const n2 = await getFileByPath('./2.txt') const n3 = await getFileByPath('./3.txt') // n3会等待n2 n2 会等待n1}```## axios 使用```JavaScript1. 安装axiosnpm i axios qs --save2. 在main.js中导入axios,并将axios 挂载到Vue的原型中improt axios from 'axios'Vue.prototype.$axios = axios 3. get请求this.$axios.get('url').then(function(res){ // 注意: // 1. 响应的数据在res.data中 // 2. 在回调函数内部的this 不是Vue实例(通常会将这个回调函数改成箭头函数)})4. post 请求// 注意:当后台要求传递的参数数据格式是 application/x-www-form-urlencode// 需要对参数进行序列化// 使用qs模块序列化qs.stringify({name:'zs',age:18})// 如果后台要求的参数格式 是json格式 appliction/json 不需要序列化this.$axios.post('url',qs.stringify({name:'zs',age:18})).then(res=>{})5. 全局配置// 5.1 设置全局的请求根域名axios.defaults.baseURL = 'http://vue.studyit.io/';// 5.2 通过设置请求拦截器 配置post参数序列化axios.interceptors.request.use(function (config) { // 统一处理post请求的参数 为application/x-www-form-urlencode if (config.method == 'post') { config.data = qs.stringify(config.data) } return config;});```## Vue插件开发```JavaScript1. 单独新建一个JS文件,在这个文件中导入需要制作成Vue插件的模块import axios from 'axios'2. 在该模块身上定义一个install函数,可以接受两个参数,第一个用于接收Vue构造函数第二个用于配置插件的一些选项axios.install = function(Vue,config){ // 1. 注册全局组件 // 2. 将属性挂载到原型中}3. 导出制作好的Vue插件模块export default axios4. 使用插件// 能够使用Vue.use的前提就是传入的对象一定要有install方法// 调用Vue.use()的时候 会自动去调用 传入对象的 install方法import axios from '插件路径'Vue.use(axios) // 会自动调用axios的install方法```## 去除webpack打包后的严格模式> 在使用babel-loader的时候,会将所有转换的代码加上严格模式```JavaScript// 方法一: .babelrc文件中忽略不需要使用严格模式转换的文件路径 "ignore": [ "./src/js/mui/mui.min.js" ]// 方法二: babel-loader配置中排除掉不需要严格模式转换的文件{ test: /\.js$/, use: 'babel-loader', exclude: /mui\.min\.js/}// 方法三: babel-plugin-transform-remove-strict-mode 移除整个项目打包编译时的严格模式// https://www.npmjs.com/package/babel-plugin-transform-remove-strict-mode1. 安装babel-plugin-transform-remove-strict-modenpm install babel-plugin-transform-remove-strict-mode --save-dev2. babelrc中添加{ "plugins": ["transform-remove-strict-mode"]}```## 路由模式> 通过给`vue-router`配置`mode`属性,可以指定URL路径的显示方式> `mode`属性默认值是`hash`,此时URL中有#,如:`http://localhost:8888/#/home`,实现方式即`window.location.hash`> 如果`mode`设置成`history`,此时URL路径没有#,如:`http://localhost:8888/home`,实现方式为`window.history`,这种方式同一个URL不能再其他页面打开,需要服务端配置```JavaScriptnew VueRouter({ mode:'hash', routes:[ ]})```## Vuex的使用> Vuex是一个状态管理库,或者说是专为Vue应用程序开发设计的状态管理模式,它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。> 注:所谓状态,可以理解成项目中各个组件需要用到的数据。> Demo:https://gitee.com/UniverseKing/vuex-study### 初始化公共状态``` JavaScript1. 安装vuexnpm i vuex --save2. 入口文件中实例化Storeimport Vuex from 'vuex'Vue.use(Vuex)var store = new Vuex.Store({ // 1. 用于定义状态(公共数据),类似于Vue实例中的data方法 state:{ msg:'初始化的数据' }, // 2. 用于修改状态,类似于Vue实例中methods mutations:{ change(state,arg){ // 更改状态 state.msg = arg } }, // 3. 用于获取数据(获取数据之前可以进行一些操作),类似于Vue实例中的过滤器和计算属性 // getters 主要会用在跨组件传值 // getters 中定义的方法内部依赖的数据发生变化会自动重新调用函数计算返回值 getters:{ fixmsg(state){ return `${state.msg}----处理后的数据` } }, // 4. actions和mutations都是定义对数据进行操作的方法,mutations中都是同步方法,mutations中定义异步方法 // Action 提交的是 mutation,而不是直接变更状态。所以需要修改状态还是需要使用mutations中定义的方法 // 从网络请求回来的数据需要保存到store // 发送网络请求的方法可以定义到actions中 // actions主要用于处理异步方法 actions:{ asyncchange(context,arg){ // 异步方法 setTimeout(() => { context.commit('change',arg) }, 3000) } }})3. 注入到Vue实例中new Vue({ el:'#app', store})```### 使用状态``` JavaScript1. 使用state中的数据JavaScript: this.$store.state.msgHTML: $store.state.msg2. 使用getters中的数据JavaScript: this.$store.getters.fixmsgHTML: $store.getters.msg```### 变更状态(修改数据)> 状态的变更必须使用mutations中提供的方法进行修改``` JavaScript1. 提交mutations中的变更方法this.$store.commit('change','我是被修改的数据')2. 异步提交actions中的变更方法this.$store.dispatch('asyncchange','我是被异步修改的数据')```### 使用辅助函数> 辅助函数可以直接将`state`,`getters`中的数据映射到Vue组件中的计算属性上,可以将`mutations`,`actions`中的方法映射到组件中的`methods`中``` JavaScriptimport { mapState } from 'vuex'import { mapGetters } from 'vuex' import { mapMutations } from 'vuex'import { mapActions } from 'vuex'new Vue({ computed:mapGetters([ 'count' ])})// ==>等价于new Vue({ computed:{ count(){ return this.$store.state['count'] }})```## vue-cli配置代理解决开发阶段跨域问题```JavaScript// webpack.config.js配置文件导出对象中加入 devServer:{ // 代理跨域 proxy: { '/api': { target: 'http://vue.studyit.io/api', // 需要被代理的api根域名 changeOrigin: true, // 是否跨域 pathRewrite: { '^/api': '' // 重写(target中只有根域名时不需要配置此选项) } } } }---------------------------// vue-cli中config/index.js中proxyTable: { '/api': { target: 'http://vue.studyit.io/api', changeOrigin: true, pathRewrite: { '^/api': '' } }},```## webpack打包优化> 目前项目中所有资源都会被打包到最终生成的一个build.js中,而build.js又被引用到index.html中,当打开index.html时,首先需要从互联网下载build.js,只有build.js全部下载完毕,浏览器的解析引擎才会开始执行该js代码进行代码解析,当解析引擎将代码解析完毕后再交给渲染引擎开始进行渲染,所有工作几乎都是同步执行,当build.js体积非常大时,往往应用的首页加载速度比较慢,而且会看到白屏效果.可以从以下三方面进行优化首页加载速度过慢问题:1. 下载文件速度慢2. 解析JS比较慢3. 渲染比较慢### 服务端渲染(SSR)> SEO优化> 在服务端先将JS进行解析,解析完成之后生成HTML片段,再将HTML返回给前端,前端直接执行渲染界面### 抽取CSS> 将项目中所有CSS抽取到单独的文件中进行加载,减小了build.js的体积,只要build.js下载完成即可开始解析代码> https://github.com/webpack-contrib/extract-text-webpack-plugin```JavaScript1. 安装插件npm install extract-text-webpack-plugin --save-dev2. webpack.config.js中引入插件var ExtractTextPlugin = require('extract-text-webpack-plugin');3. 修改css-loader配置{ test: /\.css$/, use: ExtractTextPlugin.extract({ fallback: "style-loader", use: "css-loader" })},{ test: /\.less$/, use: ExtractTextPlugin.extract({ fallback: 'style-loader', use: ['css-loader', 'sass-loader'] })}, // 处理 less 文件的 loader{ test: /\.scss$/, use: ExtractTextPlugin.extract({ fallback: 'style-loader', use: ['css-loader', 'sass-loader'] })}4. plugin配置中使用插件new ExtractTextPlugin('app.css')```### 分离第三方包> 将项目中引用的第三方JS代码抽取到一个单独的文件,也可以减少build.js的体积,还是只需要build.js下载完毕浏览器解析引擎即可开始进行解析,然后浏览器同时再去下载其他JS和CSS> 一般将发布阶段所需要依赖的包全部进行分离,即`package.json`中`dependencies`中的所有包进行分离```JavaScript 1. 引入webpack和路径处理模块var webpack = require('webpack');var path = require('path');2. 修改入口文件entry: { app: path.resolve(__dirname, 'src/main.js'), // 需要分离的第三方包名写在数组中 vendors: ['vue', 'vue-resource', 'vue-router', 'vuex', 'mint-ui', 'moment', 'vue-preview']},3. plugin中配置插件// 分离第三方包插件new webpack.optimize.CommonsChunkPlugin({ name: 'vendors', filename: 'vendors.js' // 分离出来的js文件的名称})```### 组件按需加载> vue-router提供的路由懒加载可以按需加载组件。> 特点: 当没有访问到某个页面路由时,不去加载对应的组件代码,节约数据请求量,加快首页DOM渲染速度```将import home from './components/Home.vue' 这种导入方式换成const home = () => import('../components/Home.vue');```## 路由导航钩子函数> 在跳转路由时,进行拦截,一般用于权限验证或登录等操作> https://router.vuejs.org/zh-cn/advanced/navigation-guards.html### 路由独享守卫```JavaScriptconst router = new VueRouter({ routes: [ { path: '/home', component: HomeContainer, // 进入路由之前进行拦截 beforeEnter: (to, from, next) => { // from 从哪个路由来 // to 到哪个路由去 // 释放守卫 进入下一个环节 } } ]})```### 全局守卫```JavaScriptrouter.beforeEach((to, from, next) => { })```## Cmder使用> window系统下增强型命令行工具,免安装,解压即用```JavaScript// 1. 将cmder.exe加入环境变量1. window + R 输入 sysdm.cpl2. 选中 高级 - 环境变量 - 系统变量 - Path3. 将cmder.exe所在目录添加到Path中// 2. 天假右键菜单在cmder.exe所在目录打开命令行窗口 输入 Cmder.exe /REGISTER ALL```## HBuilder打包> HBuilder打包 是将前端开发的HTML/CSS/JS文件进行打包,打包成可以直接安装在手机上面的App,不借助浏览器就可以直接运行```JavaScript1. 使用webpack将项目进行打包,打包好的文件会在dist目录webpack -p2. 打开Hbuilder,新建移动App项目,然后删掉css/js/imgs文件夹和index.html文件3. 将使用webpack打包的dist目录里面的文件全部拷贝到新建的移动项目目录中4. 选中HTML文件,点击HBuilder导航上面的`发行`-`打原生安装包`,直接下一步,选安卓公共证书-`打包`5. 在项目的`unpackage\release`中可以得到打包完毕的apk文件```## cordova打包> 直接在本地进行打包> 需要电脑配置Java环境和Android环境 `gradle````JavaScript// 1. 安装全局cordovanpm i cordova -g// 2. 创建cordova项目cordova create cordova_project// 3. 添加需要打包的平台cordova platform add android// 4. 运行或者打包cordova run androidcordova build android```## vue-cli打包完成后1. 错误信息:`postcss-svgo: Error in parsing SVG: Unquoted attribute value` - 需要修改mui.css中的 **图片引用** 单引号全部改成双引号2. 提示必须使用服务器的方式打开,即使用localhost方式打开 // 1. 安装http-server npm i http-server -g // 2. 使用hs -o命令打开index.html文件 hs -o3. 如果打包完成后希望直接用file协议打开,需要修改config/index.js 中的build下的`assetsPublicPath: '/'`换成`assetsPublicPath: './'`## Parcel使用```JavaScriptnpm i parcel-bundler -gparcel index.html```----> 项目地址:https://gitee.com/UniverseKing/vue_cms> [Vue组件](https://github.com/UniverseKing/awesome-github-vue#%E5%BA%94%E7%94%A8%E5%AE%9E%E4%BE%8B)## MVC 和 MVVM 区别> MVC从后台业务逻辑对项目进行分层开发 数据流通是单向的,所有的数据流通都需要C进行控制> MVVM是前端框架的一种设计模式,核心是双向数据绑定,M和V可以直接进行通信,VM只负责数据的绑定## 你平时开发项目,有没有遇到比较难的问题,是怎么解决的?- vue-loader 深度作用选择器(父组件中不能给v-html渲染出来的标签添加样式)- babel-loader在编译代码时,会给所有的代码加上严格模式,不能使用call,callee,arguments..## 项目接口:> http://www.escook.cn:3000/> http://www.lovegf.cn:8899/## 真机调试```1. 手机开一个WiFi热点2. 使用电脑连接手机的WiFi热点3. 在电脑上打开CMD命令行 输入ipconfig命令 查看的IP地址是 无线局域网下面的ipv4地址4. 在项目中使用--host IP地址 重启项目5. 在手机中访问项目的IP地址```