Vue基础学习笔记

126 阅读6分钟

Vue:

  1. MV*,1.0 是 MVVM 框架,2.0 不是了

  2. Vue 的两个版本:完整版和运行时

    1. 完整版:vue.js/vue.min.js;非完整版:vue.runtime.js
    2. 完整版的体积大,功能强,支持直接写入 html;非完整版需要 render(h)才能写入 HTML
    3. 其中完整版多了一个编译器,但是非完整版更独立?
    4. webpack 可以做到我们看似是用带有编译器的写代码,其实是不带的,然后在打包时转化成能理解的??反正就是可以用体积更小的包更好的体验写代码
    5. 将编译器放在 build 里面,webpack+vue loader
    6. 引入方式
      1. cdn 引入
      2. webpack 引入,默认是非完整版,用完整版需要配置 alias
      3. @vue/cli 引入,默认是非完整版,完整版需要配置
      4. 到底怎么配置看文档
  3. vue 单文件组件

    1. 写一个组件
    2. 引入进 main.js
    3. el:"xxx",render(h){return h(Demo)}
    4. 这是有 vue-loader 时可以写的
  4. SEO 友好

    1. 搜索引擎优化
    2. curl 命令
    3. 把 description、title、keyword、h1、a 写好
    4. vue 中虽然 vue 会直接覆盖页面中的 dom 节点,但是搜索引擎依然可以 curl 到 div 中写的关键词
  5. ssr

    1. 不要用客户端的 js 去渲染内容,而是用服务器端的 js 去渲染内容,指的去获取数据库数据等
    2. 指的就是 node.js
  6. 最佳实践:总是使用非完整版,然后配合 vue-loader 和 vue 文件

    1. 只支持 h 函数
    2. vue 文件不用写 h 函数
    3. vue-loader 把 vue 文件里的 HTML 转为 h 函数
  7. 真正的工程师要做的事是封装!

const vm = new Vue(options);
  1. new Vue({})这就是构造一个 vue 实例
  2. 但凡是个函数,他的proto就是 Function,vue 就是个构造函数
  3. vm 对象封装了对视图的所有操作,包括数据读写、事件绑定、DOM 更新,没有 ajax
  4. 因为 vue 是视图层的,不会去包含网络层的东西
  5. options 是 new Vue 的参数,一般称之为选项或构造选项,参数选项啊
  6. :属性名="",表示""里的是 js 代码,引号和里面的没关系,也可以传函数

options

  1. 数据:data 数据、props 属性、propsData、computed 被计算出来的、methods 方法、watch 观察

    1. 方法与函数:
      1. 方法:面向对象概念;函数:数学概念
      2. obj.say()是面向对象的写法,say()是函数式编程的写法
    2. data:可以为对象,也可以为函数,返回对象,优先使用函数(为什么?在 vue 组件里,data 要写为函数,因为如果这个组件被引用了两次,那如果是对象就是引用了同一个内存地址,一个改变所有的都改变,函数就不一样,函数内的变量是有自己的作用域的,调用时时重新创建变量)
    3. methods:作为事件处理函数或普通函数(代替 filter)
      1. @click="add"
      2. {{add()}}
    4. props:外部属性,外部传参,父传子
    // main.js
    <Demo message="" />
    // Demo.vue
     <template>{{message}}</template>
     <script>
     export default {
         props: ['message']
     }
     </script>
    
  2. DOM:el 容器、template 内容、render 渲染、renderError

    1. el:挂载点,与$mount 有替换关系
  3. 生命周期钩子:11 个钩子函数 beforeCreate、created、beforeMount、mounted、beforeUpdate、updated、activated、deactivated、destroyed...

    1. 使用 debugger 等手段实验
    2. created:出现在内存中,没有出现在页面中
    3. mounted:出现在页面中
    4. updated:更新触发
    5. destroyed:消亡,再次创建是重新创建全新的。怎么使用它呢?通过 v-if 可以控制一个组件的显隐
  4. 资源:components 组件、directives 指令、filters 过滤器

    1. component 组件:可以组合的物件?

      1. 引入
      2. 可以直接创建、使用
      3. 还有一种见 App.vue
      4. 所以,直接 new Vue 就是实例,像上面几种方法创建的就是组件
      5. 组件用大写
      Vue.component("demo", {
        template: `
              <div>demo</div>
              `,
      });
      
    2. directives 指令:自定义指令

      1. Vue.directive('x', directiveOptions)=>全局指令
      2. 局部指令,只能用在该实例中
      new Vue({
         ...,
         directives: {
            "x": directiveOptions
         }
      })
      
      1. 指令主要作用:DOM 操作,减少重复的 DOM 操作
      2. VUE 实例/组件用于数据绑定、事件监听、DOM 更新
      3. 所有的 dom 操作都写在指令里面,经常使用的、复杂的 dom 操作封装指令
  5. 组合:extends 扩展、provide 提供、inject 注入、mixins 混合、parent

    1. mixins 就是复制。作用是减少 data、methods、钩子的重复
      1. 重复代码可以写在一个 js 文件里,然后导入后使用 mixins: [log],log 是 js 中 export default log,vue 导入的文件名
      2. 智能合并。如果有需要 vue 文件传参的地方,可以在 vue 文件的 data 中写,或者与 js 文件有一样的函数,也可以写,因为 mixins 可以智能合并
      3. 可以设置全局混入,在 main.js 里写就行,然后直接用,不用导入,但是这样所有的 vue 组件就都会被混入,会出现未定义等错误 Vue.mixin({})
    2. extends 继承。
      1. 跟 mixin 相似,同样需要新建 js 文件新建 myVue,继承 Vue 后写自己的代码const myVue = Vue.extend({}),然后其他 vue 组件就可以 extends myVue
      2. 跟 mixin 相似,同样需要导入 myVue,然后 extends:myVue
      3. 更高级的是,myVue 可以导入 mixin 文件,在里面 mixins,这样原先可能需要写很多遍的 mixins,可以在 myVue 中一次写完,然后其他组件可以继承一次这个 myVue 就可以
    3. provide 和 inject
      1. 当子组件想使用父组件的变量和函数时,可以把这些变量和函数放在 provide 里,然后使用 inject 注入到想使用的子组件
      2. 注意:如果变量是字符串,那么传过去的就只是这个字符串的复制品,直接在子组件里更改这个字符串没有任何意义。这时可以在父组件里添加函数进行修改,然后传这个函数。当然,变量是对象的时候是可以直接进行修改的,但是这样你的变量就会被任何人任意修改,会失控
      3. 作用:适用于大范围的data和methods共用
       if(x === 'a' || x === 'b' || x === 'c') {}
       相当于
       if(['a', 'b', 'c'].indexOf(x) >= 0) {}
    
  6. 其他

数据响应式-data

  1. {n:(...)}表示并不存在一个 n 属性,但可以通过 get 和 set 对他进行读写
    1. 虚拟属性 get 和 set
  2. 新增 set 和 get,使用 defineProperty:
    var _xxx = 0
    Object.defineProperty(obj1, 'age', {
       get() {
          return _xxx
       }
       set(value){
          _xxx = value
       }
    })
    
    注意:不要在 get 和 set 里使用新增的 age
  3. 监听和代理
  4. 当 vm=new Vue({data: myData})
    1. 让 vm 成为 myData 的代理 proxy
    2. 会对 myData 的所有属性进行监控
    3. 监控是为了防止 data 被改变 vm 还不知道,vm 知道就可以调用 render
  5. data 的 bug:没有这个属性还要使用(比如在其他地方赋值)
  6. 如果 data 中没有声明变量 a,那么其他引用/操作 a 的语句都无法成立,因为 vue 无法监听一个一开始不存在的变量
    1. 但是可以通过以下方法操作:
    2. Vue.set(obj, 'a', {})
    3. this.$set()
    4. 作用:新增 key;自动创建代理和监听;触发 UI 更新,但不是马上更新
    5. 纠错:this.$set 作用于数组时,并不会自动添加监听和代理,原因未知
  7. 数组的变异方法 push、pop 等 7 个方法,会在调用的同时添加/删除监听和代理

进阶属性 数据更新时除了更新 UI 还能干啥

  1. computed 计算属性:根据其他属性计算出的属性,是一个函数,但可以按变量读取

  2. computed 是怎么做到缓存的?

  3. watch 侦听:当数据变化时执行一个函数

  4. watch 是异步的,会先做完这个函数的事再去触发 watch,所以可以让函数等一会,但不能使用 timeout({},0),vue 封装的 watch 的立马执行函数是 this.$nextTick,所以函数内也要使用这个

  5. watch:第一次的值不监听,就是那个初始值

  6. 想做到监听第一次的值,可以在 handler 函数中写操作,然后设置 immediate=true

  7. 区别:

    1. computed:依赖于执行变化和缓存得到结果
    2. watch:更倾向于去执行一个东西,比如记录历史
    3. 英文翻译中文;用代码分别去描述
      1. computed 不需要用括号可以直接使用;根据依赖会自动缓存,依赖的值不发生改变就不会重新计算
      2. watch 有两个属性 immediate 和 deep;属性变化就去执行一个函数
  8. watch:

    1. 简单类型变了就是变了,复杂类型,比如引用类型 obj={a:'a'},a 变了,但 obj 并没有变,obj 变了,里面的不变
    2. a 变化,怎么才能让 obj 也变化:加属性 deep: true
    3. 千万不要使用箭头函数

模板 template

  1. template 里面不是 HTML,是 XML
  2. XML 有闭合标签这一说,必须闭合,XML 可以这么写:
    自闭合
  3. 三种写模板的方式:
    1. main.js 中使用 template,写在 HTML 里
    2. main.js 中在写在选项里
    3. xxx.vue 写在 HTML 里然后其他文件引入
  4. 展示内容:
    1. {{ 表达式/运算/函数 }}
    2. undefined 或 null 不显示
    3. v-text=""没啥意义
    4. 如果包含标签,富文本=> v-html=""
    5. 想展示{{ n }}:v-pre 不会对模板进行编译
  5. 绑定属性
    1. src: v-bind:src="x"
    2. v-bind: 简写=> :
    3. :src :style
    4. 100 默认表示为 100px
  6. 绑定事件
    1. v-on:事件名="函数名"
    2. 缩写:@click
  7. if...else
    1. v-if:
    2. v-else-if:
    3. v-else:
  8. for(value, key) in obj/arr
    1. v-for="(u, index) in users" :key="index"
    2. v-for 必须要写 :key
    3. key 一般是不会重合的、唯一性的值
    4. :key="index"有 bug
  9. v-show
    1. 不是所有看的见的元素 display 为 block
    2. table 的 display 为 table
    3. li 的 display 为 list-item
  10. 特点:
    1. XML
    2. {{}}
    3. 指令:操作 DOM 和实现循环和条件判断
  11. vue 是声明式编程,写的是声明式对应的是命令式操作
  12. 指令:v-model;v-slot;v-cloak;v-once

指令

  1. v-开头
  2. v-pre 没有值 v-on:click.prevent 阻止默认事件
  3. .prevent 叫做修饰符
    1. .stop 阻止事件传播/冒泡
    2. .prevent 阻止默认动作
    3. .stop.prevent 同时表示两个意思
  4. v-on 的修饰符可以为 keycode 或他的别名(Alias),比如 enter 键的 keycode 为 13,可以写为:
    1. @click.13 = ""
    2. @click.enter = ""
    3. 别名修饰符有 enter、tab、delete 等,找官网
  5. v-bind: .sync
    1. 组件不能修改 props 外部数据
    2. this.$emit 可以触发事件并传参
    3. event可以获取event可以获取emit 的参数
    4. :money.sync="total"相当于:money="total" v-on:update:money="total=event",表示先将total传到子组件,然后通过eventbustotal的变化传回来,子组件的写法是@click="event",表示先将total传到子组件,然后通过eventbus将total的变化传回来,子组件的写法是 @click="emit('update:money', money-100)"
    5. 这就是父和子组件互相传递啊
  6. v-model: .lazy .number .trim

v-model

  1. 双向绑定
    1. 内存改变时页面也会改变;页面改变内存也会改变(表单)
    2. input、多行文本、复选框、单选框、选择框、表单
      1. input,v-model="x"
      2. 多行文本textarea
      3. 复选框需要绑定不同的value,需要声明一个数组x
      4. 单选框,x="",最好把name写上,相同的name表示他们是一组的,radio
      5. select,options
    3. :value="1",这个1表示number,value="1",这个1是string,前者是动态绑定,加冒号:表示里面的是js语句,不然就是字符串
    4. form(@onSubmit.prevent="")+button(type="submit"),输入(v-model="user.username",v-model="user.password")后按回车可以自动提交,此时监听form的onSubmit事件输出变化的信息this.user,就可以拿到提交的信息
  2. 修饰符
    1. .lazy
      1. 表单在输入的时候,内存内的数据就变化了(input事件),想要让这个频率降低,使用v-model.lazy变成监听change事件
      2. input事件监听任何的改变,包括鼠标、键盘等输入设备
      3. change事件监听的是失去焦点
    2. .number
      1. 当变量初始化就是number类型,且输入的也只想要number类型就可以使用v-model.number,它会自动识别,比如输入21sss3,只会保存21,且021会自动省去0
    3. .trim
      1. 自动把前面和后面的空格去掉