vue基础&实战

550 阅读10分钟

todo

  • 文本无法不换行问题

vscode快捷键

1, command + p 类文件名搜索
2, Ctrl + tab 切换已经打开的导航文件,长按是所有打开的文件列表

@media媒体查询和移动端适配方案

image.png

setInterval()和setTimeout()区别

/**
 * 只会执行一次
 * 延迟2s执行一次run1()
 * 注意第一个参数是字符串函数
 * */
setTimeout('run1()',2000);
function run1() {
    console.log(1)
}
/**
 * 不停的执行
 * 每隔2s执行一次run2()
 * 注意第一个参数是字符串函数
 * */
var inter = setInterval('run2()',2000);
function run2() {
    console.log(2)
    let result = confirm("是否取消定时器?"); //确认返回true, 取消返回false
    if (result)
    {
        alert('取消成功')
        clearInterval(inter);
    }
}

Math.floor()、Math.ceil()和Math.round()

Math.floor()取最大整数、
Math.ceil()取最小整数
Math.round()四舍五入取整数

常用的第三方功能

1, 安装:
npm install --save vue-pdf

2, 使用方式:
<template>
  //可传递URL
  <pdf src="./static/relativity.pdf"></pdf>
</template>

<script>
import pdf from 'vue-pdf'

export default {
  components: {
    pdf
  }
}
1, 在浏览器和微信小程序中是支持的FormData(), 
2, 放到APP加载vue, FormData()不兼容(在iPhone7-ios11支持), formdata为空,所以后台接收不到formdata对象, 但在苹果浏览器中直接访问vue页面却可以接收到formdata对象.(神奇, 先用base64解决)

vue部署问题

部署vue项目注意事项:

  • 本地开发环境请求正常, 打包(部署)后,访问页面正常,请求接口404
原因:
1, 本地开发环境会使用代理,
`请求网络路径:`
http://172.16.14.39:8082/coalURL/AdminServer/Api/queryEncyclopediInfo
2, 打包(部署)后,前端请求的URL路径是不需要经过代理的,如果要做跨域出来,是需要后端在Nginx上做处理.
`请求的网络路径应该为:`
http://172.16.14.39:8082/AdminServer/Api/queryEncyclopediInfo
  • 图解: devServer只对本地开发环境有效(dev即代表开发环境) 代理.png

打包时需要修改的路径.png

图解本地&打包修改配置项.png

padding和margin的区别

  • padding是内边距,是与元素相关联的边距,会和元素显示相同的背景色.
  • margin是外边距,是元素之外的边距,不会显示元素的背景色.
  • padding的内边距可以用box-sizing:border把内边距计算到元素指定的宽高中
  • width是100%,元素margin的左右外边距都是10px,此时可以把width写成calc(100%-20px)

padding、margin,失效

如果标签设置了width:100%,可能导致padding或margin失效,这时候应该添加box-sizing:border-box;

image.png

什么是BFC?

Box:CSS布局的基本单位
Formatting context: 格式化上下文 / 格式化范围

Formatting context 是 W3C CSS2.1 规范中的一个概念。
它是页面中的一块渲染区域,并且有一套渲染规则,它决定了其子元素将如何定位,以及和其他元素的关系和相互作用。
最常见的 Formatting context 有 Block fomatting context (简称BFC)和 Inline formatting context (简称IFC)。
CSS2.1 中只有 BFC 和 IFC, CSS3 中还增加了 GFC 和 FFC。

BFC:块级格式化范围

BFC提供了一个环境,HTML元素在这个环境中按照一定规则进行布局。
一个环境中的元素不会影响到其它环境中的布局。
比如浮动元素会形成BFC,浮动元素内部子元素,主要受该浮动元素影响,两个浮动元素之间是互不影响的。
浮动元素会尽量接近往左上方(或右上方)

BFC的约束规则

- BFC里面的box都会以垂直方向排列 

- Box垂直方向的距离由margin决定。属于同一个BFC的两个相邻Box的margin会发生重叠。
➤p1和p2的margin都是10,那么我们看到p1和p2的实际间距为10.
➤需要把p1或p2用div包裹,然后给div激活BFC. 不能只把p1、p2激活BFC,因为他们还是在同一个BFC

- 每个盒子(块盒与行盒)的margin box的左边,与包含块border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。
➤无论是块级元素还是行级元素或设置了浮动的元素,都会与包含它们的容器(元素)的左边或右边相接触。

- BFC的区域不会与float box重叠。
➤所有的元素默认都不属于BFC、float,非BFC的p1和设置float的p2会重叠在父容器的左上角,当把p1设置为BFC时,
➤由于BFC和float盒子(元素)不会重叠,就会一个一个排列。又因为浮动元素会尽量接近左上或右上方,所以就会形成两列布局

- BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。

- 计算BFC的高度时,浮动元素也参与计算。
➤父容器中如有没有设置高度,子元素如果存在浮动,会导致父容器高度塌陷。
➤如果激活父容器的BFC,父容器高度会把浮动子元素的高度计算在内,正常显示。

怎么形成BFC?

  • float的值不为none
  • position的值不是static或者relative
  • display的值是inline-block、table-cell、flex、table-caption或者Inline-flex
  • overflow的值不是visible

BFC实际使用场景

①②③处的margin都生效了

前提知识:
(元素指标签view;box是元素的单位,可理解为元素本身),

BFC的约束规则其一:
Box垂直方向的距离由margin决定。
属于同一个BFC的两个相邻Box的margin会发生重叠。

注意:view1和view2是相邻box, 就算它们各自都激活了BFC
还是会发生margin重叠,因为它们始终是相邻的box,
所以应该给view1或view2外层套一层<view>,然后激活BFC。
<view class="view1"></view>
<view class="view2"></view>

为了使c1-view和c2-view设置的margin上下边距都生效,
需要给其中一个box激活BFC,
这样,c1-view和c2-view就不在同一个BFC环境中了,
他们各自的margin也就不会发生重叠了。

image.png

box-sizing

  • box-sizing: content-box;
前提知识:
1, rpx是微信自适应的单位,px = rpx/2
2, 谷歌浏览器,box-sizing默认为content-box;

结论:
view1和view2,
css指定宽高都是50px, 
padding都是25px,
border边框宽度都是5px.
由于box-sizing为content-box, 
padding,border都会计算到实际宽高中,但是margin不会计算到实际宽高中!!!
所以,view1和view2的实际宽高都是110px

image.png

  • box-sizing: border-box; 如果指定宽高不够减的, 那么,实际宽高=padding+border

image.png

//如果指定宽高不够减的,
那么,实际宽高=padding+border

view1和view2实际指定宽高都是50px, 但box-sizing设置为border-box时
padding和border都会计算到指定宽高中, margin不计算到指定宽高,
padding左右总宽为50,上下总高为50,已经占了指定宽高的总宽高, 所以实际宽高都为0。
元素的padding(内边距)和宽高都会显示相同的背景色,而 margin(外边距)不会显示元素设置的背景色

image.png

Vue.use内部会自动寻找install方法进行调用,接收的第一个参数是Vue(Vue可以理解为一个类或构造函数)

自动化引入模块

require.context 参数:
1. 文件夹路径
2. 是否递归查找子文件夹下的模块
3. 模块匹配规则,一般匹配文件后缀名
在开发中大型项目时,会将一个大功能拆分成一个个小功能,除了能便于模块的复用,也让模块条理清晰,后期项目更好维护。
require.context 一次引入文件夹所有的模块文件,而不需要逐个模块文件去引入。每当新增模块文件时,就只需要关注逻辑的编写和模块暴露,require.context 会帮助我们自动引入。
需要注意 require.context 并不是天生的,而是由 webpack 提供。在构建时,webpack 在代码中解析它。

对象生成新对象

        var a = {name:'mrhan'}
        var b = {
          ...a,
          'age':29
        }
        console.log(`b:${JSON.stringify(b)}`); //b:{"name":"mrhan","age":29}

路由懒加载(动态chunkName)

  • 常见用法

import Home from "../views/Home.vue";
let router = new Router({
  routes: [
    {
      path: "/",
      name: "Home",
      component: Home
    },
    // 通常我们还会为延迟加载的路由添加“魔法注释”(webpackChunkName)来自定义包名,在打包时,js文件会以魔法注释开头。
    {
      path:'/login',
      name:'login',
      component: import(/* webpackChunkName: "login" */ `@/views/login.vue`)  //魔法注释
    },
    {
      path: "/about",
      name: "About",
      // route level code-splitting
      // this generates a separate chunk (about.[hash].js) for this route
      // which is lazy-loaded when the route is visited.
      component: () =>
        import(/* webpackChunkName: "about" */ "../views/About.vue") //魔法注释
    }
  ]
})
  • 自动注入方式

const routeOptions = [
    {
      path: "/",
      name: "Home",
    },
    {
      path:'/login',
      name:'login',
    },
    {
      path: "/about",
      name: "About",
    }
];
// 假如routeOptions的对象中只有path和name属性,那么可以用下面的方法统一自动添加component
const routes = routeOptions.map(route => {
  if (!route.component) {
    route = {
      ...route,
      component: () => import(/* webpackChunkName: "[request]" */ `@/views/${route.name}.vue`)
    }
  }
  return route
})

函数组件

image.png

样式穿透

使用场景:在某个界面想要修改第三方库中的样式,由于style设置了scoped会导致样式没有生效的情况
原因:因为第三方组件的默认样式优先级比scoped中样式的优先级高!!但不完全都高,不生效的时候肯定是高.

解决方案:在需要穿透的样式前,添加>>>或/deep/

<style lang="less" scoped>
.van-circle {
  /deep/ .van-circle__text {
    color: blue;
  }
  //>>> .van-circle__text {
  //  color: blue;
  //}
}
</style>

监听组件生命周期

方式1: 在子组件的生命周期函数中,使用$emit调用父类的方法名

方式2: 使用@hook监听组件生命周期(created、updated、mounted)

<template>
    <child @hook:mounted="listenMounted" ></child>
</template>

页面销毁时清除定时器

方式1:定义全局变量timer

export default {
    mounted() {
        this.timer = setInterval(() => {
            console.log(Date.now())
        }, 1000)
    },
    beforeDestroy() {
        clearInterval(this.timer)
    }
}

方式2:通过$on或$once监听页面生命周期销毁,清除定时器

export default {
    mounted() {
        this.creatInterval('hello')
        this.creatInterval('world')
    },
    creatInterval(msg) {
        let timer = setInterval(() => {
            console.log(msg)
        }, 1000)
        this.$once('hook:beforeDestroy', function() {
            clearInterval(timer)
        })
    }
}

VSCode代码自动补全html标签、css属性及值

参考2

setting文件内容,替换为:
{
    "window.zoomLevel": 0,
    "terminal.integrated.rendererType": "dom",
    "editor.suggest.snippetsPreventQuickSuggestions": false,
    "files.associations": {
        "*.vue":"html"
    }
}

image.png

consoles用法

  • 输出内容: console.log('test')
  • 把数组以表格形式输出:console.table([1, 2, 3])
  • 输出当前界面的堆栈信息:console.trace('Test')

一套目前主流的前端技术栈。

1Node.js:服务器端的 JavaScript 运行环境,不管哪种前端开发,都必不可少的底层环境。

(2Webpack:语法转换工具,把 ES6/TypeScript/JSX 语法转成浏览器可以运行的代码。

(3Koa2:一个非常流行、简洁强大的 Node.js 后端的 Web 开发框架。

(4MongoDB:目前应用最广泛的非关系数据库之一,功能丰富,用法较简单。

(5Vue 全家桶:
    Vue:前端基础框架
    Vuex:配套的前端状态管理库。
    Vue Router:官方的路由插件,构建单页面应用必不可少。
    Vue CLI:脚手架工具,帮你快速上手 Vue 开发,无需再花多余时间去实现项目架构。
    Vant:有赞前端团队开发的轻量级移动端 Vue 组件库,让你快速使用已经封装好的各种页面组件。

vue-router钩子beforeRouteEnter函数获取到this实例

官方文档:
const Foo = {
  template: `...`,
  beforeRouteEnter (to, from, next) {
    // 在渲染该组件的对应路由被 confirm 前调用
    // 不!能!获取组件实例 `this`
    // 因为当钩子执行前,组件实例还没被创建
  },
  beforeRouteUpdate (to, from, next) {
    // 在当前路由改变,但是该组件被复用时调用
    // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
    // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
    // 可以访问组件实例 `this`
  },
  beforeRouteLeave (to, from, next) {
    // 导航离开该组件的对应路由时调用
    // 可以访问组件实例 `this`
  }
}
export default {
    data(){
        return {
             num: 18
        }
    },
    beforeRouteEnter(to, from, next){
        next(vm=>{
            vm.num=19;
        })
    }
}

vue的keep-alive组件清除缓存

//使用方法:
import { h_keepalivePath } from '@/components/global/toolway'
beforeRouteLeave(to, from, next) {
    h_keepalivePath(to,from,next,this,'/otherlistpagedetail');
}
//toolway.js
/* to, from, next为路由默认参数,that是调用者的this(因为要用到当前页的对象方法) path是跳转到下一页需要缓存当前页的路径(下一页的路由) */
export function h_keepalivePath(to, from, next, that, path) {
  if (to.path == path) { //去详情页的时候, 需要缓存列表, 否则不需要缓存走else
      from.meta.keepAlive = true;
  } else {
      let vnode = that.$vnode
      let parentVnode = vnode && vnode.parent;
      if (parentVnode && parentVnode.componentInstance && parentVnode.componentInstance.cache) {
          var key = vnode.key == null
              ? vnode.componentOptions.Ctor.cid + (vnode.componentOptions.tag ? `::${vnode.componentOptions.tag}` : '')
              : vnode.key;
          var cache = parentVnode.componentInstance.cache;
          var keys = parentVnode.componentInstance.keys;

          if (cache[key]) {
            that.$destroy()
              // remove key
              if (keys.length) {
                  var index = keys.indexOf(key)
                  if (index > -1) {
                      keys.splice(index, 1)
                  }
              }

              cache[key] = null
          }
      }
  }
  next();
}

export、export default、import

ES6 前,实现模块化使用的是 RequireJS 或者 seaJS(分别是基于AMD规范的模块化库,和基于CMD规范的模块化库)。
commonjs规范的 require(导入) module.exports(导出)
ES6 引入了模块化,化分为导出(export) 、导入(import)两个模块。

export 导出的语法有两种:
➤export 命名导出(每个模块包含任意数量)
➤export default 默认导出(每个模块只包含一个)
  • 在一个文件或模块中,export、import可以有多个,export default仅有一个。
  • 通过export方式导出,在导入时要加{},导入的变量名,须和导出的变量名相同,顺序可以不一致。
//test.js
export var a = "My name is Tom!";
export var b = "My name is Tom!";
//上面两行可以优化为:export {a,b}
注意:
const c = 66;
// export c; //error, 导出内容:应为声明或语句
export {c}; //export导出变量时,必须要加{}

//test2.js
//这里的a,b,c必须和test.js中的a,b,c名称保持一致,要想改变名称参考下面【练习】中的as用法
import {a,b,c} from './test.js'
  • export default方式导出,在导入时不需要{}
//test.js
var a = "My name is Tom!";
export default a;

//test2.js
//x表示:任意变量名
import x from './test.js'; //x不需要{}包裹
  • import多个文件,变量重名时,可以使用as改变变量名称 export & export default练习

要导出的文件(test.js)

//test.js
export var a = 1;
export const b = 2;
export let c = 2;
export let d = {
    name:'mrhan'
};
// 上面等价于下面这一行,注意:不能重复export相同的变量!
// export {a,b,c,d}
var e = 11;
export default e; //export default只能存在一个.

导入的文件(test2.js)

//这里修改了f的名称为f1, f失效.
import e,{ a,b,c,d,f as f1 } from "./test.js";
// 下面写法是错误的,{}后面必须紧跟from
// import { a,b,c,d },e from "../../api/api";

➤下面是使用导入变量的场景👇
//a:1, b:2, c:2, d:{"name":"mrhan"}, e:11, f:undefined, f1:55
console.log(`a:${a}, b:${b}, c:${c}, d:${JSON.stringify(d)}, e:${e}, f:${f}, f1:${f1}`); 

// a = 10; //error,只读
// b = 20; //error,只读
// c = 30; //error,只读
// d = {}; //error,不能改变d的引用指向,但可以改变d的属性
d.name = 'age'; //可以修改对象d的属性
// e = 22; //error
// f = 4; //f失效后变为undefined,这里相当于创建了个变量f=4
// f1 = 5; //error,只读

// a:1, b:2, c:2, d:{"name":"age"}, e:11, f:4, f1:55
console.log(`a:${a}, b:${b}, c:${c}, d:${JSON.stringify(d)}, e:${e}, f:${f}, f1:${f1}`); 

export 函数、 import 函数

  //导入&用法
  import { test2 } from '@/components/global/toolway'
  test2('我是参数params');
  
  //导出函数的用法1:
  export function test2(params) {
    console.log('diaoyong le' + params);
  }
  //导出函数的用法2:
  export const test2 = (params)=>{
    console.log('diaoyong le' + params);
  }

Promise用法

resolve和reject用法

  • resolve()和reject(), 只能传递一个参数,其余参数默认undefined 可以传一个对象
  • Promise对象的then和catch方法, 会默认返回Promise.resolve(data); data是then中的参数,默认传递
Promise.resolve().then(() => {
  return new Error('error!!!')
}).then(res => {
  console.log("then: ", res)
}).catch(err => {
  console.log("catch: ", err)
})

多个网络请求顺序执行

image.png

多个网络请求异步执行完成, 再执行最后一个网络请求

image.png

this.$router.back()失效

  • 原因: 使用了禁用安卓物理返回键导致
//禁止安卓的物理返回键
if (window.history && window.history.pushState) {
    //禁止侧滑返回
    history.pushState(null, null, document.URL);
    window.addEventListener('popstate', function () {
        history.pushState(null, null, document.URL);
    });
}

☆☆☆☆☆☆☆☆☆☆vue工具☆☆☆☆☆☆☆☆☆☆

页面中显示控制台日志插件(vconsole)

//在package.json中添加开发依赖:
"dependencies": {
  "vconsole": "^3.3.4"
}
//在main.js中引用
import Vconsole from 'vconsole'
let vConsole = new Vconsole()
Vue.use(vConsole)

浏览器适配查询