VUE-CLI

1.创建项目

  1. // 1.需要先删除旧版本cli
  2. npm uninstall vue-cli -g
  3. // 2.安装@vue/cli
  4. npm install @vue/cli -g
  5. // 3.查看vue版本
  6. vue --version
  7. // 4.创建vue项目
  8. vue create ym001
  9. 参考链接 https://www.jianshu.com/p/7cccc5b38dcc
  10. 参考链接 https://www.cnblogs.com/coober/p/10875647.html

2. 性能优化

https://www.yuque.com/fe9/basic/locx8c#728b4ded

Vue

注意事项:

vue组件样式添加了scoped 最外层的元素会被父组件样式穿透

  1. // index.vue
  2. <template>
  3. <div class="container">
  4. <page-header />
  5. <div class='content'>我的背景是红色的</div>
  6. </div>
  7. </template>
  8. <script>
  9. import PageHeader from '@/components/setting/page-header'
  10. export default {
  11. components: { PageHeader }
  12. }
  13. </script>
  14. <style lang="scss" scoped>
  15. .container{
  16. position: fixed;
  17. height: 100%;
  18. width: 100%;
  19. .content {
  20. background: red;
  21. }
  22. }
  23. </style>
  24. // page-header.vue
  25. <template>
  26. <div class="content">
  27. 我的背景也是红色的
  28. </div>
  29. </template>
  30. ...script ...style:scoped

Object.defineproperty / proxy

  1. 两者最大的区别在于proxy能监听对象的所有属性,
  2. defineproperty只能监听对象的某一个属性 ```javascript // Object.defineProperty// 不兼容IE8 var obj = {}; // obj.name = 666 // Object.defineProperty(obj,’name’,{ // value:666, // enumerable:false,// 是否可枚举, 是否能够循环的到 默认false // // writable:false, // 是否可以更改 默认不可改写 // // configurable:false // 是都可删除 delete 默认不可删除 // }); var t=666; Object.defineProperty(obj,’name’,{ // 数据劫持 get(){ //当name被调用的时候 会触发 这个 get;调用时 获取到的值 是 这个函数的返回值 console.log(‘get’) return t }, set(val){ // 当name属性被赋值的时候 会触发 这个set val对应的就是给name赋予的哪个值 console.log(‘set’,val) t = val; } });

    // Proxy var obj2 = { name:123, age:456, sex:7777, a:{ qqq:123 } } var tempObj2 = new Proxy(obj2,{ get(target,key){ // target就是 obj2 // key 就是我们调用的对应的属性的名字 console.log(‘get’,arguments) return target[key] }, set(target,key,val){ console.log(‘set’) target[key] = val } }); // Proxy 优势 不用挨个属性进行劫持

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Proxy

  1. <a name="XqSar"></a>
  2. ### 自定义指令 directive
  3. <a name="dMgp3"></a>
  4. ### mvvm v-model 原理
  5. ```javascript
  6. class myVue {
  7. constructor(options) {
  8. this.$el = document.querySelector(options.el)
  9. this.$data = options.data
  10. this.observe(this.$data) // 负责数据劫持
  11. this.nodeToFragment(this.$el, this)// 负责模板编译
  12. }
  13. observe(data) {
  14. // 把data中的属性进行劫持
  15. if (({}).toString.call(data).match(/ (\w+)]/)[1] != 'Object') return
  16. let keys = Object.keys(data)// 获取到了每一个属性名
  17. keys.forEach(key => {
  18. this.defineReactive(data, key, data[key])
  19. })
  20. }
  21. defineReactive(obj, key, value) {
  22. // 负责使用 defineProperty进行数据劫持
  23. this.observe(value)// 递归劫持
  24. let dep = new Dep()
  25. Object.defineProperty(obj, key, {
  26. get() {
  27. console.log('get')
  28. if (Dep.target) {
  29. dep.addSub(Dep.target)
  30. }
  31. return value
  32. },
  33. set(newVal) {
  34. console.log('set')
  35. if (value !== newVal) {
  36. value = newVal
  37. dep.notify()
  38. }
  39. }
  40. })
  41. }
  42. nodeToFragment(el, vm) {
  43. // 把节点转到 fragment上
  44. let fragment = document.createDocumentFragment()
  45. let child
  46. while (child = el.firstChild) {
  47. fragment.appendChild(child)
  48. this.compile(child, vm)
  49. }
  50. el.appendChild(fragment)
  51. }
  52. compile(node, vm) {
  53. // 编译 node中的 vue语法
  54. // 先判断 node的节点类型 看他是一个 元素节点 还是 文本节点
  55. if (node.nodeType == 1) {
  56. // 元素节点 // 要获取行内属性的
  57. let attrs = node.attributes;
  58. [...attrs].forEach(item => {
  59. // 查看当前的属性名是不是 v-xxx的
  60. if (/^v-/.test(item.name)) {
  61. // 证明这个属性 是 v-model 我i们要获取 后边的name这个字符
  62. let vName = item.nodeValue // name
  63. let val = vm.$data[vName]// 珠峰
  64. new Watcher(node, vName, vm)
  65. node.value = val// 把珠峰这两字 放到 input框中
  66. node.addEventListener('input', (e) => {
  67. vm.$data[vName] = e.target.value
  68. })
  69. }
  70. });
  71. // 处理当前元素的子元素
  72. [...node.childNodes].forEach(item => {
  73. this.compile(item, vm)
  74. })
  75. } else {
  76. // 文本节点
  77. let str = node.textContent// 获取文本字符串
  78. // console.log(str)// {{name}}
  79. if (/\{\{(\w+)\}\}/.test(str)) {
  80. console.log(str)
  81. str = str.replace(/\{\{(\w+)\}\}/, (a, b) => {
  82. new Watcher(node, b, vm)
  83. return vm.$data[b]
  84. })
  85. node.textContent = str
  86. }
  87. }
  88. }
  89. }
  90. //订阅器
  91. class Dep {
  92. constructor() {
  93. this.subs = []
  94. }
  95. addSub(sub) {
  96. this.subs.push(sub)
  97. }
  98. notify() {
  99. this.subs.forEach(sub => {
  100. // debugger
  101. // 让对应的事件执行 sub 就是哪些 watcher
  102. sub.update()
  103. })
  104. }
  105. }
  106. // 订阅者
  107. class Watcher {
  108. constructor(node, key, vm) {
  109. Dep.target = this
  110. this.node = node
  111. this.key = key
  112. this.vm = vm
  113. this.getValue()
  114. Dep.target = null
  115. }
  116. update() {
  117. this.getValue()
  118. // debugger
  119. if (this.node.nodeType == 1) {
  120. // 就是input框
  121. this.node.value = this.value
  122. } else {
  123. this.node.textContent = this.value
  124. }
  125. }
  126. getValue() {
  127. // 获取新值
  128. this.value = this.vm.$data[this.key]
  129. }
  130. }

vue.use

  1. 传入实参会默认执行某些方法, 会根据实参的类型进行不同操作

  2. 判断传入实参是否有install方法,并调用,若install方法不存在

  3. 再判断实参是不是一个函数,若是执行实参函数,若不是将不在往下执行

$nextTick原理

  1. nextTick内部有一个callbacks事件池, 还有一个pedding的状态
  2. 预先会进行浏览器能力检测, promies > setImmediate > MessageChannel > setTimeout
  3. 当用户调用nextTick方法, 往callbacks push箭头函数
  4. 若传入cb, cb.call执行,否则走promies微任务执行
  5. 判断pedding为false 改变状态调用timeFun方案挨个执行事件池方法
  6. 执行完状态改为false

provide/inject使用.父组件定义provide 子组件使用inject定义 泼歪德 in杰可特
https://juejin.im/post/5dc4cbeff265da4d1f51c7f1

$emit(父组件事件名,参数) 父组件使用@事件名= 方法 驼峰命名

动态组件
上述内容可以通过 Vue 的 元素加一个特殊的 is attribute 来实现:
动态更换组件
props
数组传,对象传,prop验证
https://cn.vuejs.org/v2/guide/components-props.html
禁用 Attribute 继承
inheritAttrs: false, 默认true
$listeners
.sync
https://www.jianshu.com/p/6b062af8cf01
插槽
组件里面必须有 可搭配component :is使用
插槽作用域 如果插槽中要使用data的数据
父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的。
具名插槽 可以在插槽上定义v-slot=”mySlot”
注意 v-slot 只能添加在