一个合格的中级前端工程师需要掌握的技能笔记(下)

Github来源:一个合格的中级前端工程师需要掌握的技能 | 求星星 ✨ | 给个❤️关注,❤️点赞,❤️鼓励一下作者

大家好,我是魔王哪吒,很高兴认识你~~

哪吒人生信条:如果你所学的东西 处于喜欢 才会有强大的动力支撑

每天学习编程,让你离梦想更新一步,感谢不负每一份热爱编程的程序员,不论知识点多么奇葩,和我一起,让那一颗四处流荡的心定下来,一直走下去,加油,2021加油!欢迎关注加我vx:xiaoda0423,欢迎点赞、收藏和评论

不要害怕做梦,但是呢,也不要光做梦,要做一个实干家,而不是空谈家,求真力行。

前言

如果这篇文章有帮助到你,给个❤️关注,❤️点赞,❤️鼓励一下作者,接收好挑战了吗?文章公众号首发,关注 程序员哆啦A梦 第一时间获取最新的文章

如何实现路由懒加载

{ path: '/login', component: () => import('@/views/login/index'), hidden: true },

路由懒加载中的魔法注释

通过在注释中指定webpackChunkName,可以自定义这个文件的名字。

components = () => import(/* webpackChunkName:"login"*/ "../component/Login.vue")

windows环境搭建Vue开发环境

一个合格的中级前端工程师需要掌握的技能笔记(下)_第1张图片 image.png

设置nodejs prefix(全局)和cache(缓存)路径

在nodejs安装路径下,新建node_global和node_cache两个文件夹

  • 设置缓存文件夹

npm config set cache "D:\vueProject\nodejs\node_cache"
  • 设置全局模块存放路径

npm config set prefix "D:\vueProject\nodejs\node_global"

基于 Node.js 安装cnpm(淘宝镜像)

npm install -g cnpm --registry=https://registry.npm.taobao.org

设置环境变量可以使得住任意目录下都可以使用cnpm、vue等命令,而不需要输入全路径

// 系统环境变量
...\nodejs\node_global
// 用户变量
... \nodejs\node_modules

安装Vue

cnpm install vue -g

vue-cli 脚手架

cnpm install vue-cli -g

根据模版创建新项目

vue init webpack-simple mytest
一个合格的中级前端工程师需要掌握的技能笔记(下)_第2张图片 image.png
  • build,最终发布代码的存放的位置

  • config,配置目录,包括端口号

  • node_modules,这是执行npm install后产生的,里面包含了Node.js和npm依赖的文件以及后续安装的第三方组件或第三方功能

  • src,存放开发页面相关的文件

  • assets,放置一些图片

  • components,存放了组件文件

  • App.vue,是项目入口文件

  • main.js,项目的核心文件

  • router,项目的路由

  • static,一般用于存放静态资源,如图片,字体等

  • .babelrc文件,用来设置转码的规则和插件的,一般情况不需要设置

测试一下该项目是否能够正常工作

cnpm run dev

Prop的双向绑定

在父子组件通讯的时候,子组件都禁止直接修改父级传过来的prop,父组件总需要在子组件身上监听一个事件,然后由子组件去触发它,好让父组件来接收到payload去改变state。

自定义组件上的v-model指令以及.sync修饰符可以解决子组件修改父组件state

一个组件上的 v-model 默认会利用名为 value 的 prop 和名为 input 的事件

双向绑定的效果:


通过v-model

父组件通过v-model传递val值:

而子组件内通过model选项去绑定这个prop:

export default {
  model: {
    prop: 'anyKey',  // 不一定非要是value
    event: 'anyEventName'  // 不一定非要是input
  },
  props: {
    anyKey: {
      type: Number
    }
  },
  methods: {
    handleClick() {
      this.$emit('anyEventName', this.anyKey+2)
    }
  }
}

通过.sync修饰符

父组件通过.sync修饰符传递val值:

子组件,vue内部帮我们绑定了update:myPropName这样一个事件

export default {
  props: {
    val: {
      type: Number
    }
  },
  methods: {
    handleClick() {
      this.$emit('update:val', this.val+2)
    }
  }
}

v-bind.sync=”{ title: doc.title }”这种绑定字面量对象,修饰符是无法正常工作的

PropSync的用法

import { Vue, Component, PropSync } from 'vue-property-decorator'
 
@Component
export default class YourComponent extends Vue {
  @PropSync('name', { type: String }) syncedName!: string
}

以上代码等同于:

export default {
  props: {
    name: {
      type: String,
    },
  },
  computed: {
    syncedName: {
      get() {
        return this.name
      },
      set(value) {
        this.$emit('update:name', value)
      },
    },
  },
}
// 父组件

 

import { Vue, Component } from 'vue-property-decorator';
import Child from './Child.vue';
 
@Component({components: { Parent }})
export default class ParentPage extends Vue {
  private name = '父组件名字';
}

 
// 子组件

 

import { Component, Vue, PropSync} from 'vue-property-decorator';
 
@Component
export default class ChildComponent extends Vue {
  @PropSync('name', { type: String }) syncedName!: string; // 用来实现组件的双向绑定,子组件可以更改父组件穿过来的值
 
  changeName(): void {
    this.syncedName = '子组件修改过后的syncedName!'; // 双向绑定,更改syncedName会更改父组件的name
  }
}
 

@Model的作用

@Model(event?: string, options: (PropOptions | Constructor[] | Constructor) = {})

@Model装饰器允许我们在一个组件上自定义v-model,接受两个参数:

event: string类型,表示事件名;
options: PropOptions | Constructor[] | Constructor与@Prop的第一个参数一致;
@Component
export default class YourComponent extends Vue {
  @Model('change', { type: Boolean }) readonly checked!: boolean
}

等同于以下代码:

export default {
  model: {
    prop: 'checked',
    event: 'change',
  },
  props: {
    checked: {
      type: Boolean,
    },
  },
}

ModelSync的用法

@ModelSync(propName: string, event?: string, options: (PropOptions | Constructor[] | Constructor) = {}) 
@ModelSync装饰器可接受三个参数:

propName: string类型,表示类型名称;
event: string类型,表示事件名;
options: PropOptions | Constructor[] | Constructor与@Prop的第一个参数一致;

看下面例子:

import { Vue, Component, ModelSync } from 'vue-property-decorator'
 
@Component
export default class YourComponent extends Vue {
  @ModelSync('checked', 'change', { type: Boolean })
  readonly checkedValue!: boolean
}

以上代码等同于:

export default {
  model: {
    prop: 'checked',
    event: 'change',
  },
  props: {
    checked: {
      type: Boolean,
    },
  },
  computed: {
    checkedValue: {
      get() {
        return this.checked
      },
      set(value) {
        this.$emit('change', value)
      },
    },
  },
}

@Provide

import { Component, Inject, Provide, Vue } from 'vue-property-decorator'

const symbol = Symbol('baz')

@Component
export class MyComponent extends Vue {
  @Inject() readonly foo!: string
  @Inject('bar') readonly bar!: string
  @Inject({ from: 'optional', default: 'default' }) readonly optional!: string
  @Inject(symbol) readonly baz!: string

  @Provide() foo = 'foo'
  @Provide('bar') baz = 'bar'
}

等同于:

const symbol = Symbol('baz')

export const MyComponent = Vue.extend({
  inject: {
    foo: 'foo',
    bar: 'bar',
    optional: { from: 'optional', default: 'default' },
    baz: symbol,
  },
  data() {
    return {
      foo: 'foo',
      baz: 'bar',
    }
  },
  provide() {
    return {
      foo: this.foo,
      bar: this.baz,
    }
  },
})

@ProvideReactive和@InjectReactive

这些装饰器是@Provide和@Inject的响应式版本。如果父组件修改了提供的值,则子组件可以捕获此修改。

const key = Symbol()
@Component
class ParentComponent extends Vue {
  @ProvideReactive() one = 'value'
  @ProvideReactive(key) two = 'value'
}

@Component
class ChildComponent extends Vue {
  @InjectReactive() one!: string
  @InjectReactive(key) two!: string
}

@Emit(event?: string) decorator

import { Vue, Component, Emit } from 'vue-property-decorator'

@Component
export default class YourComponent extends Vue {
  count = 0

  @Emit()
  addToCount(n: number) {
    this.count += n
  }

  @Emit('reset')
  resetCount() {
    this.count = 0
  }

  @Emit()
  returnValue() {
    return 10
  }

  @Emit()
  onInputChange(e) {
    return e.target.value
  }

  @Emit()
  promise() {
    return new Promise((resolve) => {
      setTimeout(() => {
        resolve(20)
      }, 0)
    })
  }
}

等同于

export default {
  data() {
    return {
      count: 0,
    }
  },
  methods: {
    addToCount(n) {
      this.count += n
      this.$emit('add-to-count', n)
    },
    resetCount() {
      this.count = 0
      this.$emit('reset')
    },
    returnValue() {
      this.$emit('return-value', 10)
    },
    onInputChange(e) {
      this.$emit('on-input-change', e.target.value, e)
    },
    promise() {
      const promise = new Promise((resolve) => {
        setTimeout(() => {
          resolve(20)
        }, 0)
      })

      promise.then((value) => {
        this.$emit('promise', value)
      })
    },
  },
}

@Ref(refKey?: string) decorator

import { Vue, Component, Ref } from 'vue-property-decorator'

import AnotherComponent from '@/path/to/another-component.vue'

@Component
export default class YourComponent extends Vue {
  @Ref() readonly anotherComponent!: AnotherComponent
  @Ref('aButton') readonly button!: HTMLButtonElement
}

等同于:

export default {
  computed() {
    anotherComponent: {
      cache: false,
      get() {
        return this.$refs.anotherComponent as AnotherComponent
      }
    },
    button: {
      cache: false,
      get() {
        return this.$refs.aButton as HTMLButtonElement
      }
    }
  }
}

@VModel(propsArgs?: PropOptions) decorator

import { Vue, Component, VModel } from 'vue-property-decorator'

@Component
export default class YourComponent extends Vue {
  @VModel({ type: String }) name!: string
}

等同于:

export default {
  props: {
    value: {
      type: String,
    },
  },
  computed: {
    name: {
      get() {
        return this.value
      },
      set(value) {
        this.$emit('input', value)
      },
    },
  },
}

排除打包

vue.config.js, 添加 externals 项

configureWebpack: {
    externals: {
      'vue': 'Vue',
      'element-ui': 'ElementUI',
      'xlsx': 'XLSX'
    },
    resolve: {
      alias: {
        '@': resolve('src')
      }
    },
}

引用网络资源

  • 引用CDN:

    • 减少应用打包出来的包体积

    • 加快静态资源的访问

    • 利用浏览器缓存,不会变动的文件长期缓存

vue-cli3.0 开发环境构建

vue-cli安装

(1)若已全局安装vue-cli (1.x 或 2.x),需先卸载

npm uninstall vue-cli -g

(2)全局安装 vue-cli3.0

npm install -g @vue/cli

(3)创建项目

vue create 项目名
>(*) Babel
 ( ) TypeScript
 ( ) Progressive Web App (PWA) Support //支持渐进式网页应用程序
 ( ) Router //路由管理器
 ( ) Vuex //状态管理模式(构建一个中大型单页应用时)
 ( ) CSS Pre-processors //css预处理
 (*) Linter / Formatter //代码风格、格式校验
 ( ) Unit Testing // 单元测试
 ( ) E2E Testing // 即端对端测试

启动项目

// 1、进入项目
cd 项目名

 // 2、运行
npm run serve

单页面

一个合格的中级前端工程师需要掌握的技能笔记(下)_第3张图片 image.png

前端路由模式hash

“#”代表网页中的一个位置,右面的字符就是代表的位置信息。

“#”意味着它不管怎么变化都不会影响请求URL,即它只针对浏览器的。

在第一个#后面出现的任何字符,都会被浏览器解读为位置标识符。这意味着,这些字符都不会被发送到服务器端。如果需要发送需要先转码。

“#”意味着单单改变#后的部分,浏览器只会滚动到相应位置,不会重新加载网页。

改变#会改变浏览器的访问历史

window.location.hash这个属性可读可写。读取时,可以用来判断网页状态是否改变;写入时,则会在不重载网页的前提下,创造一条访问历史记录。

路由模式history

(1)History.length (只读)
返回一个整数,该整数表示会话历史中元素的数目,包括当前加载的页。

(2)History.state (只读)
返回一个表示历史堆栈顶部的状态的值

(3)History.scrollRestoration
允许Web应用程序在历史导航上显式地设置默认滚动恢复行为。

vue element input 限制输入数字后几位小数点

onkeyup="if(isNaN(value)) {value = null } if(value.indexOf('.')>0) { value = value.slice(0, value.indexOf('.')+5) }"

vue实现audio进度拖拽播放及拖拽播放问题解决

经初步分析,出现这种问题的原因是audio的timeupdate方法约每秒触发一次,js代码在播放音频时没有进行处理,此方法一直在修改slider的model值,当把滑块拖到目标位置(过程超过1s)松开时,slider拖动的实际值已经被timeupdate修改成了currentTime,所以松手后滑块会立刻回到currentTime值的位置。

只要在拖动滑块不松开的过程中timeupdate方法不修改slider的model值就行了,即增加一个flag,给滑块加上鼠标事件mousedown、mouseup,鼠标按下(意味着在拖动)flag为true,鼠标松开(拖动结束)flag为false,timeupdate事件只在flag为false时才对slider的model值进行修改就行了。



private audio: any = { // 音频当前播放时长 currentTime: 0, // 音频最大播放时长 maxTime: 0, // 该字段是音频是否处于播放状态的属性 playing: false, // 是否静音 muted: false, speed: 1, waiting: true, preload: 'auto', isDraging: false } timeupdateFunc(e){     if(!this.isDraging){         this.playProcess = (e.target.currentTime)/this.totalTimes*100;         this.currentTime = e.target.currentTime;     } },

git fetch vs  git pull

都是从远程拉取代码到本地,git fetch只是拉取到本地,git pull不仅拉取到本地还merge到本地分支中。所以git pull是git fetch与git merge的集合体。

npm config list

$ npm config list
; "builtin" config from c:\vue\node_global\node_modules\npm\npmrc

; prefix = "C:\\Users\\da\\AppData\\Roaming\\npm" ; overridden by user

; "user" config from C:\Users\da\.npmrc

ca = [""]
cache = "C:\\vue\\node_cache"
get = "registry"
prefix = "c:\\vue\\node_global"
registry = "https://registry.npmjs.org/"
strict-ssl = true

; node bin location = C:\vue\node.exe
; cwd = C:\HBuilderProjects
; HOME = C:\Users\da
; Run `npm config ls -l` to show all defaults.
npm config set registry https://registry.npmjs.org

npm config set registry https://registry.npm.taobao.org

原因是https的自签名失败

临时解决办法:关闭ssl

npm config set strict-ssl false
$ npm get registry
https://registry.npmjs.org/
$ npm uninstall -g vue-cli
npm ERR! code EPERM
npm ERR! syscall mkdir
npm ERR! path c:\vue\node_global\node_modules\.vue-cli-SVGezKmI
npm ERR! errno -4048
npm ERR! Error: EPERM: operation not permitted, mkdir 'c:\vue\node_global\node_modules\.vue-cli-SVGezKmI'
npm ERR!  [Error: EPERM: operation not permitted, mkdir 'c:\vue\node_global\node_modules\.vue-cli-SVGezKmI'] {
npm ERR!   errno: -4048,
npm ERR!   code: 'EPERM',
npm ERR!   syscall: 'mkdir',
npm ERR!   path: 'c:\\vue\\node_global\\node_modules\\.vue-cli-SVGezKmI'
npm ERR! }
npm ERR!
npm ERR! The operation was rejected by your operating system.
npm ERR! It's possible that the file was already in use (by a text editor or antivirus),
npm ERR! or that you lack permissions to access it.
npm ERR!
npm ERR! If you believe this might be a permissions issue, please double-check the
npm ERR! permissions of the file and its containing directories, or try running
npm ERR! the command again as root/Administrator.
一个合格的中级前端工程师需要掌握的技能笔记(下)_第4张图片 image.png a5b255465f4aad9bad6b092984ad9234.png image.png
$ node -v
v14.17.3

$ vue -V
2.9.6

$ npm -v
7.20.1

$ vue -V
@vue/cli 4.5.13

vue 创建项目有必要安装Progressive Web App(PWA)Support吗

简单说一下:
一是给项目添加一些webapp支持,比如在手机端支持发送到桌面图标,根据不同平台和浏览器尝试去掉浏览器自带的地址栏、底栏实现全屏体验,这个主要是视觉上和体验上的,没有什么实际功能。
实现方式就是勾选pwa支持后项目会生成manifest.json,在里面配置即可
二是增加可离线支持。其实可离线也不一定非要用pwa,有不少其他手段。可离线就是比如你的项目不是一定要全程联网才能实现功能,只要用户访问过一次你的网站,下一次进入时哪怕没有网络,你的项目也不会白屏,而是照常运行或者开放部分功能,或者给个断网提示等等。对于那些功能性网站挺有用的,举例来说什么在线计算器,在线算税小工具等。
通过配置项目生成的registerServiceWorker.js来注册serviceworker实现,具体操作还是很复杂的,详情百度.

PWA 的主要特点包括下面三点:

  • 可靠 - 即使在不稳定的网络环境下,也能瞬间加载并展现

  • 体验 - 快速响应,并且有平滑的动画响应用户的操作

  • 粘性 - 像设备上的原生应用,具有沉浸式的用户体验,用户可以添加到桌面

PWA 具有下面一些特性:

  • 渐进式 - 适用于所有浏览器,因为它是以渐进式增强作为宗旨开发的

  • 连接无关性 - 能够借助 Service Worker 在离线或者网络较差的情况下正常访问

  • 类似应用 - 由于是在 App Shell 模型基础上开发,因为应具有 Native App 的交互和导航,给用户 Native App 的体验

  • 持续更新 - 始终是最新的,无版本和更新问题

  • 安全 - 通过 HTTPS 协议提供服务,防止窥探和确保内容不被篡改

  • 可索引 - 应用清单文件和 Service Worker 可以让搜索引擎索引到,从而将其识别为『应用』

  • 粘性 - 通过推送离线通知等,可以让用户回流

  • 可安装 - 用户可以添加常用的 webapp 到桌面,免去去应用商店下载的麻烦

  • 可链接 - 通过链接即可分享内容,无需下载安装

manifest 的目的是将Web应用程序安装到设备的主屏幕,为用户提供更快的访问和更丰富的体验。

为了这样做,我们需要添加一个manifest.json文件并且在index.html文件中进行声明

pwa-manifest-webpack-plugin能够让我们在应用构建的时候生成文件:

npm i pwa-manifest-webpack-plugin --save

我们接着能够通过编辑build/webpack.dev.conf.js 以及build/webpack.prod.conf.js来更新构建过程。

在顶部引入pwa-manifest-webpack-plugin :

const manifestPlugin = require('pwa-manifest-webpack-plugin')

将它添加到插件:

plugins: [
    new manifestPlugin({
      name: '程序员', // 标题 指定了Web App的名称。
      short_name: '程序员', // 短标题 short_name其实是该应用的一个简称。一般来说,当没有足够空间展示应用的name时,系统就会使用short_name。
      description: '程序员', // 这个字段的含义非常简单,就是一段对该应用的描述。
      display: 'standalone', // fullscreen:全屏显示,会尽可能将所有的显示区域都占满;standalone:独立应用模式,这种模式下打开的应用有自己的启动图标,并且不会有浏览器的地址栏。因此看起来更像一个Native App;minimal-ui:与standalone相比,该模式会多出地址栏;browser:一般来说,会和正常使用浏览器打开样式一致。
      start_url: '/', // 这个属性指定了用户打开该Web App时加载的URL。相对URL会相对于manifest。这里我们指定了start_url为/,访问根目录。
      orientation: 'portrait-primary', // 控制Web App的方向。设置某些值会具有类似锁屏的效果(禁止旋转),例如例子中的portrait-primary。具体的值包括:any, natural, landscape, landscape-primary, landscape-secondary, portrait, portrait-primary, portrait-secondary。
      icon: {
        // icons本身是一个数组,每个元素包含三个属性:
        //
        // sizes:图标的大小。通过指定大小,系统会选取最合适的图标展示在相应位置上。
        // src:图标的文件路径。注意相对路径是相对于manifest。
        // type:图标的图片类型
        src: path.resolve('src/assets/logo.png'),
        sizes: [200]
      },
      background_color: '#2d8cf0', // background_color是在应用的样式资源为加载完毕前的默认背景,因此会展示在开屏界面。background_color加上我们刚才定义的icons就组成了Web App打开时的“开屏图”。
      theme_color: '#2d8cf0' // 定义应用程序的默认主题颜色。 这有时会影响操作系统显示应用程序的方式(例如,在Android的任务切换器上,主题颜色包围应用程序)。此外,还可以在meta标签中设置theme_color:
    })
]
最后,在 index.html中声明使用manifest.json:

在 index.html中声明使用manifest.json:


 

    
    
    
    

 

    
    
    
    
    

配置完上面的步骤之后,你可能需要重启一下  npm run dev

service worker 是一个 WEB API,是 Web Workers 的一种实现,功能是可以拦截、处理请求,配合 CacheStorage 等 api,可以做到将资源存储到本地等,实现离线访问。

service workers 的生命周期有:

  • 安装 install

  • 激活 activate

新建文件service-worker.js

如何把vue项目改造成支持PWA的功能(第二章:加入service-worker)

Mixins(混入)

Mixins 有点像是函数或者是宏,当某段 CSS 经常需要在多个元素中使用时,可以为这些共用的 CSS 定义一个 Mixin,然后只需要在需要引用这些 CSS 地方调用该 Mixin 即可。

sass中可用mixin定义一些代码片段,且可传参数,方便日后根据需求调用。比如说处理css3浏览器前缀:

@mixin error($borderWidth: 2px) {
  border: $borderWidth solid #F00;
  color: #F00;
}
.generic-error {
  padding: 20px;
  margin: 4px;
  @ include error(); //这里调用默认 border: 2px solid #F00;
}
.login-error {
  left: 12px;
  position: absolute;
  top: 20px;
  @ include error(5px); //这里调用 border:5px solid #F00;
}

在sass中,还支持条件语句:

@if可一个条件单独使用,也可以和@else结合多条件使用

代码如下:

$lte7: true;
$type: monster;
.ib{
    display:inline-block;
    @if $lte7 {
        *display:inline;
        *zoom:1;
    }
}
p {
  @if $type == ocean {
    color: blue;
  } @else if $type == matador {
    color: red;
  } @else if $type == monster {
    color: green;
  } @else {
    color: black;
  }
}

区别

  • node-sass 是用 node(调用 cpp 编写的 libsass)来编译 sass;dart-sass 是用 drat VM 来编译 sass;

  • node-sass是自动编译实时的,dart-sass需要保存后才会生效 推荐 dart-sass 性能更好(也是 sass 官方使用的),而且 node-sass 因为国情问题经常装不上

ESLint with error prevention only

  • 只配置使用 ESLint 官网的推荐规则

  • 这些规则在这里添加链接描述 ESLint + Airbnb config

  • 使用 ESLint 官网推荐的规则 + Airbnb 第三方的配置

  • Airbnb 的规则在这里添加链接描述 ESLint + Standard config

  • 使用 ESLint 官网推荐的规则 + Standard 第三方的配置

  • Standard 的规则在这里 添加链接描述 ESLint + Prettier

  • 使用 ESLint 官网推荐的规则 + Prettier 第三方的配置

  • Prettier 主要是做风格统一。代码格式化工具

? Pick a unit testing solution: (Use arrow keys)
> Mocha + Chai //mocha灵活,只提供简单的测试结构,如果需要其他功能需要添加其他库/插件完成。必须在全局环境中安装
Jest //安装配置简单,容易上手。内置Istanbul,可以查看到测试覆盖率,相较于Mocha:配置简洁、测试代码简洁、易于和babel集成、内置丰富的expect
一个合格的中级前端工程师需要掌握的技能笔记(下)_第5张图片 image.png
$ yarn config get registry
https://registry.yarnpkg.com

$ npm config get registry
https://registry.npmjs.org/

$ yarn config get registry
https://registry.npm.taobao.org

$ cnpm config get registry
https://registry.nlark.com/

[click.left&contextmenu&click.middle]


    
    
         
              

安装:

npm install -g @vue/cli
# OR
yarn global add @vue/cli

创建一个项目:

vue create my-project
# OR
vue ui
vue-cil是vue的脚手架工具)

$ npm install -g vue-cli

新建一个自己的vue项目

$ vue init webpack vuedemo
Vue CLI 2

npm install -g @vue/cli-init
# `vue init` 的运行效果将会跟 `[email protected]` 相同
vue init webpack my-project
一个合格的中级前端工程师需要掌握的技能笔记(下)_第6张图片 1632819948.png 一个合格的中级前端工程师需要掌握的技能笔记(下)_第7张图片 1632820571(1).png
$ yarn config get registry
https://registry.npm.taobao.org

$ yarn config set registry https://registry.npmjs.org --global
yarn config v1.22.11
success Set "registry" to "https://registry.npmjs.org".
Done in 0.06s.

$ cnpm config get registry
https://registry.nlark.com/

@vue-cli3创建项目报错:ERROR command failed: npm install --loglevel error --registry=https://registry.npm.taobao.org --di

一个合格的中级前端工程师需要掌握的技能笔记(下)_第8张图片 image.png
{
  "useTaobaoRegistry": false,
  "presets": {
    "jeskson": {
      "useConfigFiles": true,
      "plugins": {
        "@vue/cli-plugin-babel": {},
        "@vue/cli-plugin-typescript": {
          "classComponent": true,
          "useTsWithBabel": true
        },
        "@vue/cli-plugin-router": {
          "historyMode": true
        },
        "@vue/cli-plugin-vuex": {},
        "@vue/cli-plugin-eslint": {
          "config": "base",
          "lintOn": [
            "save"
          ]
        },
        "@vue/cli-plugin-unit-mocha": {},
        "@vue/cli-plugin-e2e-cypress": {}
      },
      "vueVersion": "2",
      "cssPreprocessor": "dart-sass"
    }
  },
  "packageManager": "yarn"
}

[Error: unable to get local issuer certificate while running yarn command]

yarn config set "strict-ssl" false -g

$ yarn config list
yarn config v1.22.11
info yarn config
{
  'version-tag-prefix': 'v',
  'version-git-tag': true,
  'version-commit-hooks': true,
  'version-git-sign': false,
  'version-git-message': 'v%s',
  'init-version': '1.0.0',
  'init-license': 'MIT',
  'save-prefix': '^',
  'bin-links': true,
  'ignore-scripts': false,
  'ignore-optional': false,
  registry: 'https://registry.npm.taobao.org',
  'strict-ssl': false,
  'user-agent': 'yarn/1.22.11 npm/? node/v14.17.3 win32 x64',
  lastUpdateCheck: 1632822666163
}
info npm config
{
  cache: 'C:\\vue\\node_cache',
  prefix: 'c:\\vue\\node_global',
  ca: [
    ''
  ],
  'strict-ssl': false,
  registry: 'https://registry.npm.taobao.org/',
  get: 'registry'
}
Done in 0.16s.
npm config set registry https://registry.npm.taobao.org

$ yarn config get registry
https://registry.npmjs.org

npm i 选项–global,–save,–save-dev

-global: 简写 -g

    npm i express -g 为全局安装,这种就可以直接使用express命令, 否则会提示express不是内部或外部命令

-save: 简写 -S, 作用是在package.json的dependencies字段增加或修改安装包和版本号

-save-dev: 简写 -D, 是修改devDependencies, 这样就不用安装了某个包之后手动修改package.json

~ 与 ^ 版本

版本分为: 主版本号、次版本号、补丁版本号

"devDependencies": {
    "vue": "~2.2.2",            // 匹配最近小版本,如,会匹配所有的2.2.x版本,但最高不会匹配2.3.0
    "vue-router": "^2.2.0"        // 最近的一个大版本,所有 2.x.x但不不包括3.0.0,相当于 2.0.0 <= version < 3.0.0
}

详细介绍了npm的使用,以及参数相关配置

https://javascript.ruanyifeng.com/nodejs/npm.html

vue-cli-service serve 命令会启动一个开发服务器 (基于 [webpack-dev-server]) 并附带开箱即用的模块热重载 (Hot-Module-Replacement)。

使用 vue.config.js 里的 [devServer] 字段配置开发服务器。

vue-cli-service build 会在 dist/ 目录产生一个可用于生产环境的包,带有 JS/CSS/HTML 的压缩,和为更好的缓存而做的自动的 vendor chunk splitting。它的 chunk manifest 会内联在 HTML 里。

@vue/cli-plugin-eslint 会注入 vue-cli-service lint 命令

缓存和并行处理

  • cache-loader 会默认为 Vue/Babel/TypeScript 编译开启。文件会缓存在 node_modules/.cache 中——如果你遇到了编译方面的问题,记得先删掉缓存目录之后再试试看。

  • thread-loader 会在多核 CPU 的机器上为 Babel/TypeScript 转译开启。

Git Hook

在安装之后,@vue/cli-service 也会安装 [yorkie],它会让你在 package.json 的 gitHooks 字段中方便地指定 Git hook:

{
  "gitHooks": {
    "pre-commit": "lint-staged"
  },
   "lint-staged": {
    "*.{js,vue}": [
      "vue-cli-service lint",
      "git add"
    ]
  }
}

浏览器兼容性

browserslist

你会发现有 package.json 文件里的 browserslist 字段 (或一个单独的 .browserslistrc 文件),指定了项目的目标浏览器的范围。这个值会被 [@babel/preset-env] 和 [Autoprefixer]用来确定需要转译的 JavaScript 特性和需要添加的 CSS 浏览器前缀。

Polyfill

useBuiltIns: 'usage'

一个默认的 Vue CLI 项目会使用 [@vue/babel-preset-app],它通过 @babel/preset-env 和 browserslist 配置来决定项目需要的 polyfill。

默认情况下,它会把 [useBuiltIns: 'usage'] 传递给 @babel/preset-env,这样它会根据源代码中出现的语言特性自动检测需要的 polyfill。这确保了最终包里 polyfill 数量的最小化。然而,这也意味着如果其中一个依赖需要特殊的 polyfill,默认情况下 Babel 无法将其检测出来。

如果有依赖需要 polyfill,你有几种选择:

  1. 如果该依赖基于一个目标环境不支持的 ES 版本撰写:  将其添加到 vue.config.js 中的 [transpileDependencies]选项。这会为该依赖同时开启语法转换和根据使用情况检测 polyfill。

  2. 如果该依赖交付了 ES5 代码并显式地列出了需要的 polyfill:  你可以使用 @vue/babel-preset-app 的 [polyfills]选项预包含所需要的 polyfill。注意 es.promise 将被默认包含,因为现在的库依赖 Promise 是非常普遍的。

// babel.config.js
module.exports = {
  presets: [
    ['@vue/app', {
      polyfills: [
        'es.promise',
        'es.symbol'
      ]
    }]
  ]
}
  1. 如果该依赖交付 ES5 代码,但使用了 ES6+ 特性且没有显式地列出需要的 polyfill (例如 Vuetify):请使用 useBuiltIns: 'entry' 然后在入口文件添加 import 'core-js/stable'; import 'regenerator-runtime/runtime';。这会根据 browserslist 目标导入所有 polyfill,这样你就不用再担心依赖的 polyfill 问题了,但是因为包含了一些没有用到的 polyfill 所以最终的包大小可能会增加。

构建库或是 Web Component 时的 Polyfills

当使用 Vue CLI 来[构建一个库或是 Web Component]时,推荐给 @vue/babel-preset-app 传入 useBuiltIns: false 选项。这能够确保你的库或是组件不包含不必要的 polyfills。通常来说,打包 polyfills 应当是最终使用你的库的应用的责任。

现代模式

有了 Babel 我们可以兼顾所有最新的 ES2015+ 语言特性,但也意味着我们需要交付转译和 polyfill 后的包以支持旧浏览器。这些转译后的包通常都比原生的 ES2015+ 代码会更冗长,运行更慢。现如今绝大多数现代浏览器都已经支持了原生的 ES2015,所以因为要支持更老的浏览器而为它们交付笨重的代码是一种浪费。

Vue CLI 提供了一个“现代模式”帮你解决这个问题。以如下命令为生产环境构建:

vue-cli-service build --modern

Vue CLI 会产生两个应用的版本:一个现代版的包,面向支持 [ES modules]的现代浏览器,另一个旧版的包,面向不支持的旧浏览器。

  • 现代版的包会通过 

你可能感兴趣的:(scipy,crm,ipad,relativelayout,workflow)