Vue基础总结

1、库和框架

Vue是一个渐进式(逐步集成更多的功能)的javascript框架

库:封装属性或方法

框架:拥有自己的规则和元素,比库强大的多

Vue开发模式:传统&工程化开发方式(基于webpack,推荐)

2、@vue-cli

// 安装@vue-cli
yarn global add @vue/cli

// 查看@vue-cli是否安装成功
vue -V

// 创建脚手架
vue create 项目名称

// 启动服务器
yarn serve

3、文件说明

main.js:项目的打包入口文件——Vue初始化

App.vue:Vue页面入口

index.html:浏览器运行的文件

main.js => App.vue => index.html

4、webpack配置文件vue.config.js

module.exports = {
  devServer: {
    port: 3000, // 修改端口号为3000
    open: true, // 打包后自动打开
  }
}

5、关闭eslint

// 在vue.config.js中进行配置
lintOnSave: false

6、单Vue文件

template里只能有一个根标签
js是独立作用域,变量之间互不影响
style可以使用scoped设置局部样式

7、插值表达式

目标:在dom标签中,直接插入vue数据变量

语法:{{表达式}}

vue数据变量:data函数返回的对象上的键值对

8、设计模式

设计模式:对代码分层,引入一种架构的概念

MVVM:模型(Model),视图(View),视图模型(View-Model)双向关联

好处:减少DOM操作,提高开发效率

9、指令

(1)v-bind

语法:v-bind:属性名="vue变量"

简写::属性名="vue变量"

(2)v-on:绑定事件

v-on:事件名="简单代码"

v-on:事件名="处理函数名"

v-on:事件名="处理函数(参数)"

v-on简写:v-on <=> @

处理函数:在默认导出的methods对象中定义

(3)Vue中事件处理函数中的事件对象

语法:

如果没有参数,可以直接使用e获取到事件对象

如果传了参数,想要获得事件对象,需要传入$event,处理函数接收
(4)事件修饰符

.stop -阻止事件冒泡

.prevent -组织默认行为

.once -程序运行期间,函数只执行一次

用法:@事件+事件修饰符——eg:@click.prevent

(5)按键修饰符

@keydown.enter 按下回车键

@keydown.esc 按下取消键

(6)v-model(用于表单标签)

双向数据绑定:变量变化,视图自动同步;视图变化,变量自动同步

用法:v-model="表单变量"

重点:

**下拉菜单的v-model写在select上,值为option的value

**遇到表单复选框,v-model的变量值

非数组——关联的是checked

数组——关联的是value属性

**Vue变量初始值会影响表单的默认状态

v-model修饰符:

.number:转成数值类型赋给Vue数据变量

.trim:去掉首尾的空格

.lazy:当文本框失去焦点(onchange事件发生)的时候再更新Vue数据

(7)v-text&v-html(有安全风险,XSS注入)

作用:将Vue变量设置为标签的内容

区别:v-text不会解析标签,v-html会解析标签

注意:v-html&v-text会将标签中的插值表达式覆盖

(8)v-show&v-if(赋值为true/false控制标签的显示隐藏)

v-show隐藏:采用display: none(频繁切换)

v-if隐藏:采用从DOM树上直接移除(移除)

v-if可以配合v-else或者v-else-if使用

(9)v-for

用法:

v-for="(只变量, 索引变量) in 目标结构"

v-for="值变量 in 目标结构"

目标结构可以是数组/对象/数字

目标结构变化,触发v-for的更新:

(1)数组变更方法,就会导致v-for的更新,页面更新

(2)数组非变更方法,返回一个新的数组,不会导致v-for更新,可采用覆盖数组

(3)非变更方法想让v-for更新

将非变更方法返回的新数组赋值给原来的数组
使用$set(更新的目标结构, 更新位置, 要更新的值)

10、虚拟DOM

虚拟DOM:在内存中的一个JS对象,保存DOM关键信息

好处:提高DOM更新的性能, 不频繁操作真实DOM, 在内存中找到变化部分, 再更新真实DOM(打补丁)

11、(比较新旧虚拟DOM)diff算法

(1)同级比较:根元素改变——删除重建整个DOM树

(2)同级比较:根元素不变,属性改变——DOM复用,只更新属性

(3)同级比较:子元素或内容改变

无key,就地更新
有key,按照key比较
key值要求:唯一不重复的字符串或数值(优先使用id)
key的好处:配合虚拟DOM提高更新的性能

12、动态设置class/style

// 控制是否有这个类名
:class="{类名:布尔值}"
// 控制是否有这个样式
:style="{属性名:属性值变量}"

13、过滤器(应用:日期格式化)

转换格式过滤器就是一个函数,传入值返回处理后的值,只能在插值表达式和v-bind动态属性里使用
使用场景:字符串翻转、字母转大写

// main.js中定义全局过滤器
Vue.filter('过滤器名', (值) => {return '返回处理后的值'})
// vue文件中定义局部过滤器,可以定义多个
filters: {
  过滤器名字: (值) => {return '返回处理后的值'},
  ……
}

// 使用语法
Vue变量 | 过滤器名称

可同时使用多个过滤器,或者给过滤器传参

// 多个过滤器使用
Vue变量 | 过滤器1 |过滤器2

14、计算属性computed(购物车)

(1)一个变量的值,依赖另外一些数据计算而来的结果

computed: {
  "计算属性名"() {
    return "值"
  }
}

(2)计算属性也是变量,所以不可以和data中的数重名

(3)计算属性的优势:

带缓存
计算属性对应的函数执行后,会把return值缓存起来
依赖项不变,多次调用都是从缓存中取之
依赖项的值发生变化时,函数会“自动”执行,并缓存新的值
(4)计算属性完整写法(给计算属性复制的时候才需要写完整写法)

computed: {
  "计算属性名": {
    set(值) {
      
    },
    get() {
      return "值"
    }
  }
}

案例:

小选影响全选(every)
全选影响小选
最后进行反选

15、侦听器watch(可以侦听data/computed属性值的改变)

watch: {
    变量名 (newVal, lodVal) {
    // 变量名对应值改变这里自动触发
  }
}

// 侦听复杂类型,或者立即执行侦听函数
watch: {
  "要侦听的属性名": {
    immediate: true, // 立即执行
    deep: true, // 深度侦听复杂类型内变化
    handler (newVal, oldVal) {
      
    }
  }
}

16、组件(可复用的页面结构、js代码)

组件优点:独立作用域、代码复用

(1)注册全局组件

// main.js中
// 1、导入组件文件
import 组件变量 from './components/组件文件'
// 2、注册组件
Vue.component('组件名称', 组件变量)

(2)注册局部组件

// .vue文件中
// 1、导入组件文件
import 组件变量 from './components/组件文件'
// 2、注册组件
components: {
  组件名: 组件变量
}

(3)使用组件

<!-- 以导入注册组件MyProduct为例 -->
<!-- 格式1 -->
<MyProduct></MyProduct>
<!-- 格式2 -->
<MyProduct />

<!-- 小写,驼峰式短杠连接 -->
<my-product></my-product>

(4)组件样式不冲突scoped

(5)父给子传值(自定义属性)

在父组件中给子组件绑定自定义属性,在子组件中使用props接收自定义属性传过来的值

循环使用组件:变量和组件都是独立的

(6)单项数据流

从父到子的数据流向

子组件修改数据不通知父亲,父组件的值不会改变

props属性为只读的

(7)子向父传值(自定义函数)

在父组件内,给子组件绑定自定义事件和事件处理函数

语法:@自定义事件名="父methods里函数名"

子组件内,恰当的时机,触发父绑定的自定义事件,导致父methods里事件处理函数执行

(8)组件间的传值(EventBus)

17、Vue的生命周期(从在页面上创建到销毁的过程——Vue实例的生命周期)

(1)生命周期:创建-挂载-更新-销毁

(2)钩子函数

初始化:beforeCreate created
created生命周期中,可以向服务器发送请求并且操作data中的数据

挂载:beforeMount mounted
mounted生命周期中,真实DOM已经挂载,可以操作页面上的DOM元素

更新:beforeUpdate updated
updated生命周期中,可以获取到修改之后的真实DOM

销毁:beforeDestroy destroyed
在这两个钩子函数中,可以停掉已经弃用但是仍然在执行的定时器

18、使用axios发送网络请求

(1)导入axios

import axios from 'axios'

(2)设置请求的基地址

axios.defaults.baseUrl = '请求地址'

(3)将axios挂载到Vue实例对象上

Vue.prototype.$axios = axios

(4)使用axios正式发送请求

this.$axios({
  url: ''
  //默认使用get方式提交数据
  method: 'get/post'
  // get发送数据
  params: {},
  // post发送数据
  data: {}
}).then(res => { // 因为使用axios请求回来的数据格式是Promise对象,因此需要使用.then获取请求到的数据
  // 业务逻辑
})

19、ref获取原生DOM元素

template

<template>
  <div>
      <!-- 1. 获取原生DOM元素 -->
            <h1 id="h" ref="myH">我是一个h1</h1>
            <!-- 2. 获取组件对象 - 可调用组件内一切 -->
            <Demo ref="de"></Demo>
            <!-- 3. vue更新DOM是异步的 -->
            <p ref="myP">{{ count }}</p>
            <button @click="btn">点击count+1, 马上提取p标签内容</button>
  </div>
</template>

demo

<template>
  <div>
      <p>我是Demo组件</p>
  </div>
</template>

<script>
export default {
    methods: {
        fn(){
            console.log("demo组件内的方法被调用了");
        }
    }
}
</script>

script

<script>
import Demo from './Demo'
export default {
    mounted(){
        // 通过id获取DOM元素
        console.log(document.getElementById("h")); // h1
        // 给DOM元素添加ref属性,通过this.$refs获取DOM元素
        console.log(this.$refs.myH); // h1
                
        // 使用子组件的时候,为其设置ref属性,可以通过this.$refs获取到子组件的属性和方法
        let demoObj = this.$refs.de;
        demoObj.fn()
    },
    components: {
        Demo
    },
    data(){
        return {
            count: 0
        }
    },
    methods: {
        btn(){
            // vue监测数据更新, 开启一个DOM更新队列(异步任务),因此直接获取不到修改后的DOM内容
            this.count++;
            // console.log(this.$refs.myP.innerHTML); // 0

            // 原因: Vue更新DOM异步
            // 解决: this.$nextTick()
            // 过程: DOM更新完会挨个触发$nextTick里的函数体,$nextTick是一个异步微任务
            this.$nextTick(() => {
                console.log(this.$refs.myP.innerHTML); // 1
            })
        }
    }
}
</script>

20、动态组件

<component :is="保存组件名称的变量"></component>
// 组件缓存
<keep-alive>
  <component :is="保存组件名称的变量"></component>
</keep-alive>

// 组件缓存触发激活钩子函数
activated () {}
deactivated () {}

21、组件插槽

(1)匿名插槽

<!-- Child.vue -->
<div>
  <slot>默认内容</slot>
</div>
<!-- Parent.vue -->
<Child>代替内容</Child>

(2)具名插槽

<!-- Child.vue -->
<div>
  <slot name="title">默认内容</slot>
  <slot name="content">默认内容</slot>
</div>
<!-- Parent.vue -->
<Child>
    <template v-slot:title>title内容</template>
  <template #content>content内容</template>
</Child>

(3)作用域插槽

<!-- Child.vue -->
<template>
    <div>
    <p>{{obj.title}}</p>
    <slot :data="obj">默认内容</slot>
    </div>
</template>
<script>
export default {
  data() {
    return {
      obj: {
        title: 'title',
        content: 'content'
      }
    }
  }
}
</script>

<!-- Parent.vue -->
<Child>
  <template v-slot="scope">
        <p>{{scope.data.content}}</p>
  </template>
</Child>

22、自定义指令

inserted函数触发:指令所在标签,被插入到网页上触发

(1)全局注册

Vue.directive('自定义指令名', {
  inserted(el) {
    // 可以对el标签扩展额外功能
  }
})

(2)局部注册

directives: {
  自定义指令名: {
    inserted(el) {
      // 可以对el标签扩展额外功能
    }
  }
}

(3)自定义指令传值

directives: {
  自定义指令名: {
    inserted(el, binding) {
      // binding可以接收到指令传的值
    },
    update(el, binding) {
      // 指令对应数据/标签更新时,此方法执行
    }
  }
}

23、路由

(1)路由的基本使用(声明式导航)

相当于a链接,to属性相当于href,点击的会自动激活,添加类名

router-link-exact-active(准确匹配)和router-link-active(模糊匹配)

URL中的hash值和to的值完全相同,就是准确匹配,会添加2个类名
URL中的hash值包含to的值时,就是模糊匹配,值天价router-link-active

// 使用路由跳转页面
<router-link to="路由"></router-link>
// 设置挂载点-路径切换时,显示对应的组件
<router-view></router-view>


// 导入路由模块
import VueRouter from 'vue-router'
// 注册路由模块
Vue.use(VueRouter)
// 设置路由的路径以及对应组件
const routes = [{
  path: 路由的路径,
  component: 路由对应的组件
}, {
  ……
}]
// 生成路由对象
const router = new VueRouter({
  routes
})
new Vue({
  // 将路由对象注入到vue实例中,this可以访问$route和$router
  router,
  render: h => h(App),
}).$mount('#app')

(2)声明式导航跳转传值

查询字符串传值

传值:to="/path?参数名=值"

接收:$route.query.属性名

动态路由传值

传值:to="/path/:属性名"

接收:$route.params.属性名

(3)路由重定向(redirect: 强制要切换到的路由)

// 将/重定向到/path
{
  path: '/',
  redirect: '/path'
}, {
  path: '/path',
  component: 组件名
}

(4)路由404设置

{
  path: '*',
  component: 组件名
}

(5)路由模式

hash路由:http://localhost:8080/#/home

history路由:http://localhost:8080/home(以后上线需要服务器支持,否则找的是文件夹)

修改路由模式:在实例化路由对象时,传入mode选项和值修改

const router = new VueRouter({
  routes,
  mode: 'history'
})

(6)编程式导航

使用name进行跳转的时候,URL的hash值还是切换path路径值

$router.push({ path: '路由路径' })
$router.push({ name: '路由名称' })

跳转传参

使用path进行传参会忽略params

传参推荐使用:name+query

如果当前url上"hash值和?参数"与将要跳转到的"hash值和参数"一致,会爆出冗余导航问题,不会跳转路由

(6)路由嵌套

一级路由从/开始定义
二级路由往后path直接写名字
嵌套路由在上级路由的children数组里编写路由信息对象

const routes = [{
  path: '/',
  redirect: '/index'
}, {
  path: '/index',
  component: Index,
  children: [{
    path: 'content', // 等同于/index/contents
    component: Content
  }]
}]

(7)路由导航守卫

语法:router.beforeEach((to, from, next) => {})

posted @ 2022-11-22 16:13  SultanST  阅读(21)  评论(0编辑  收藏  举报