推荐大家安装的 VScode 中的 Vue 插件

  1. Vue 3 Snippets https://marketplace.visualstudio.com/items?itemName=hollowtree.vue-snippets
  2. Vetur https://marketplace.visualstudio.com/items?itemName=octref.vetur

什么是 vue

  1. 构建用户界面
    • 用 vue 往 html 页面中填充数据,非常的方便
  2. 框架
    • 框架是一套现成的解决方案,程序员只能遵守框架的规范,去编写自己的业务功能!
    • 要学习 vue,就是在学习 vue 框架中规定的用法!
    • vue 的指令、组件(是对 UI 结构的复用)、路由、Vuex、vue 组件库
    • 只有把上面老师罗列的内容掌握以后,才有开发 vue 项目的能力!

vue 的两个特性

  1. 数据驱动视图:

    • 数据的变化会驱动视图自动更新
    • 好处:程序员只管把数据维护好,那么页面结构会被 vue 自动渲染出来!
  2. 双向数据绑定:

    在网页中,form 表单负责采集数据,Ajax 负责提交数据

    • js 数据的变化,会被自动渲染到页面上
    • 页面上表单采集的数据发生变化的时候,会被 vue 自动获取到,并更新到 js 数据中

注意:数据驱动视图和双向数据绑定的底层原理是 MVVM(Mode 数据源、View 视图、ViewModel 就是 vue 的实例)

vue 指令

1. 内容渲染指令

  1. v-text 指令的缺点:会覆盖元素内部原有的内容!
  2. {{ }} 插值表达式:在实际开发中用的最多,只是内容的占位符,不会覆盖原有的内容!
  3. v-html 指令的作用:可以把带有标签的字符串,渲染成真正的 HTML 内容!

2. 属性绑定指令

注意:插值表达式只能用在元素的内容节点中,不能用在元素的属性节点中!

  • 在 vue 中,可以使用 v-bind: 指令,为元素的属性动态绑定值;

  • 简写是英文的 :

  • 在使用 v-bind 属性绑定期间,如果绑定内容需要进行动态拼接,则字符串的外面应该包裹单引号,例如:

    <div :title="'box' + index">这是一个 div</div>
    

3. 事件绑定

  1. v-on: 简写是 @

  2. 语法格式为:

    <button @click="add"></button>
    
    methods: {
       add() {
    			// 如果在方法中要修改 data 中的数据,可以通过 this 访问到
    			this.count += 1
       }
    }
    
  3. $event 的应用场景:如果默认的事件对象 e 被覆盖了,则可以手动传递一个 $event。例如:

    <button @click="add(3, $event)"></button>
    
    methods: {
       add(n, e) {
    			// 如果在方法中要修改 data 中的数据,可以通过 this 访问到
    			this.count += 1
       }
    }
    
  4. 事件修饰符:

    • .prevent 阻止浏览器的默认事件

      <a @click.prevent="xxx">链接</a>
      
    • .stop 阻止事件冒泡

      <button @click.stop="xxx">按钮</button>
      

4. v-model 指令

  1. input 输入框
    • type=”radio”
    • type=”checkbox”
    • type=”xxxx”
  2. textarea
  3. select

5. 条件渲染指令

  1. v-show 的原理是:动态为元素添加或移除 display: none 样式,来实现元素的显示和隐藏
    • 如果要频繁的切换元素的显示状态,用 v-show 性能会更好
  2. v-if 的原理是:每次动态创建或移除元素,实现元素的显示和隐藏
    • 如果刚进入页面的时候,某些元素默认不需要被展示,而且后期这个元素很可能也不需要被展示出来,此时 v-if 性能更好

在实际开发中,绝大多数情况,不用考虑性能问题,直接使用 v-if 就好了!!!

v-if 指令在使用的时候,有两种方式:

  1. 直接给定一个布尔值 true 或 false

    <p v-if="true">被 v-if 控制的元素</p>
    
  2. 给 v-if 提供一个判断条件,根据判断的结果是 true 或 false,来控制元素的显示和隐藏

    <p v-if="type === 'A'">良好</p>
    

v-for中的 必须有key值的要求

只能是 字符串或者数字类型 布尔类型和对象不可以

必须具有唯一性

index值也不具备唯一性 没有任何意义

6. 过滤器

注意点 :
  1. 定义到filters节点下,本质是一个函数
  2. 在过滤器函数中,一定要有return值
  3. 在过滤器形参中,就可以获取到’ | ‘前待处理的那个值
  4. 如果全局过滤器和私有过滤器名字冲突则就近原则调用私有过滤器

连续调用多个过滤器

7.侦听器

immediate的作用 控制侦听器是否可以自动触发一次

watch

8.计算属性

实现了代码的复用 ,只要依赖数据源发生变化就会重新计算

axios

专注于发请求

     document.querySelector('.getts').addEventListener('click', async function () {
      const { data } = await axios({
        method: 'GET',
        url: 'http://www.liulongbin.top:3006/api/getbooks',
      });
      console.log(data);
    })




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


npm install -g @vue/cli@latest

npm config set cache "D:\Program Files\DevTools\node.js\node_cache"
D:\Program Files\nodejs\node_global

npm config set prefix "D:\Program Files\nodejs\node_global"
npm config set cache "D:\Program Files\nodejs\node_cache"
系统环境变量中的path路径为global
npm install -g @vue/cli
npm config set registry https://registry.npm.taobao.org


https://github.com/coreybutler/nvm-windows/releases 
D:\Program Files\nodejs




nvm install 16.14.2 
nvm install 14.19.1 
nvm uninstall 14.19.1
nvm uninstall 16.14.2 
nvm use 16.14.2 

组件化开发

​ 根据封装的思想,把页面上的可重用的UI结构封装为组件,从而方便项目的维护和开发。

props自定义属性

声明自定义属性,可以通过default来定义属性的默认值。

props:{
	init:{
		defalut:0,
		type:Number,
		required:true
	}
}

在父组件中想要改变子组件的样式时 需要 样式穿透 /deep/ h5

生命周期

created阶段可以发起ajax请求 ,经常在里面 调用methods中的方法,请求服务器的数据。并将数据转存到data中,模板渲染使用

lifecycle

组件传值

父组件向子组件传值

image-20221014115437075

子组件向父组件传值

image-20221014115609238

兄弟组件传值

image-20221014121510876

ref

获取 DOM 元素或组件的引用

this.$nextTick(cb)方法

组件的$nextTick(cb)方法, 等DOM组件更新完后,再执行cb回调函数.从而保证cb回调函数可以操作到最新的DOM元素.

<input type="text" v-if="inputVisble" @blur="showButton" ref="fs" />
     <button v-else @click="showInput">展示输入框</button>
export default {
  name: 'App',
  data () {
    return {
      flag:true,
      countfromson:0,
      inputVisble:false
    }
  },
  methods: {
    showButton(){
      this.inputVisble=false
    },
    showInput(){
      this.inputVisble=true;
      // inputVisble数据为最新的数据,页面没来得及重新渲染
      this.$nextTick(()=>{
            this.$refs.fs.focus()
      })
    }
    }
  },

动态组件

指 动态切换组件的显示与隐藏

image-20221014214351545

image-20221014214405561

image-20221014215741368

image-20221014215748326

插槽

默认插槽

 <Left>
        <!-- 默认情况下,在使用组件的时候,提供的内容都会被填充到名字为 default 的插槽之中 -->
        <!-- 1. 如果要把内容填充到指定名称的插槽中,需要使用 v-slot: 这个指令 -->
        <!-- 2. v-slot: 后面要跟上插槽的名字 -->
        <!-- 3. v-slot: 指令不能直接用在元素身上,必须用在 template 标签上 -->
        <!-- 4. template 这个标签,它是一个虚拟的标签,只起到包裹性质的作用,但是,不会被渲染为任何实质性的 html 元素 -->
        <!-- 5. v-slot: 指令的简写形式是 # -->
        <!-- <template #default>
          <slot></slot>
        </template> -->
        <p>用户自定义指令</p>
      </Left>

具名插槽 作用域插槽

<template>
  <div class="article-container">
    <div class="header-box">
      <slot name="title"></slot>
    </div>
    <div class="content-box">
      <slot name="content"></slot>
    </div>
    <div class="footer-box">
      <slot name="footer" :user="userInfo" msg="The world is beautiful, remember to try to be better"></slot>
    </div>
  </div>
</template>



APP组件中
 <Articles>
      <template #title>
        <p>这是我写的具名插槽 title内容</p>
      </template>
      <template #content>
         <div>
          <h6>小田加油,未来会变得更好</h6>
          <h5>小田,加油,未来会更加好的</h5>
         </div>
      </template>
     <!-- 作用域插槽  -->
     <template #footer="scope">
        <div>
          <h3>小田小田,一直很甜</h3>
          <h1>{{scope.msg}}</h1>
        </div>
      </template>
    </Articles>

自定义指令

  • 私有自定义指令
  • 全局自定义指令
// directives: {
    // 定义名为 color 的指令,指向一个配置对象
    /* color: {
      // 当指令第一次被绑定到元素上的时候,会立即触发 bind 函数
      // 形参中的 el 表示当前指令所绑定到的那个 DOM 对象
      bind(el, binding) {
        console.log('触发了 v-color 的 bind 函数')
        el.style.color = binding.value
      },
      // 在 DOM 更新的时候,会触发 update 函数
      update(el, binding) {
        console.log('触发了 v-color 的 update 函数')
        el.style.color = binding.value
      }
    } */
    //  当bind和update的功能相同时可简化
     color(el, binding) {
      el.style.color = binding.value
     }
   }
   
   Promise.allSettled()  
   Promise.resolve()
   Promise.all()
   react fiber diff的思路
   //  全局自定义   再main.js中写
   
   Vue.directive('mm',function(el,binding){
  el.style.color=binding.value
	})

axios 挂载到main.js 全局中的缺点

  • 无法实现api接口的复用

路由

路由(英文:router)就是对应关系

什么是前端路
  • Hash 地址与组件之间的对应关系
前端路由的工作方式
  • ① 用户点击了页面上的路由链接
  • ② 导致了 URL 地址栏中的 Hash 值发生了变化
  • ③ 前端路由监听了到 Hash 地址的变化
  • ④ 前端路由把当前 Hash 地址对应的组件渲染都浏览器中

vue-router

  • ① 安装 vue-router 包
  • ② 创建路由模块
  • ③ 导入并挂载路由模块
  • ④ 声明路由链接和占位符

vue2 中安装 npm i vue-router@3.5.2 -S

创建路由模块

image-20221018173833777

导入并挂载到路由模块

image-20221018173858072

声明路由链接和占位符

image-20221018173922424

声明路由匹配规则

image-20221018174016793

重定向

image-20221018174036875

动态路由

image-20221018184531567

在hash地址中, / 后面的参数项,叫做 路径参数

在路由的参数对象中,需要使用 this.$route.params来访问 路径参数

在hash地址中, ?后面的参数项,叫做 查询参数

在路由的参数对象中,需要使用 this.$route.query来访问 查询参数

this.$route 中, path只是路径部分,fullpath是完整的地址

$route.params

image-20221018184555972

使用 props 接收路由参数

image-20221018184700293

声明式导航 & 编程式导航

​ 浏览器中 ,点击链接实现导航的方式,称为声明式导航,

​ 例如:普通网页中点击<a>链接, vue项目中点击<router-link>

​ 在浏览器中,调用API方法实现导航的方式, 称为 编程式导航

普通网页中调用 location.href 跳转到新页面的方式,属于编程式导航

vue-router中的编程式导航API

  • ① this.$router.push(‘hash 地址’) ⚫ 跳转到指定 hash 地址,并增加一条历史记录

  • ② this.$router.replace(‘hash 地址’) ⚫ 跳转到指定的 hash 地址,并替换掉当前的历史记录

  • ③ this.$router.go(数值 n) ⚫ 实现导航历史前进、后退

$router.push

image-20221018224802642

$router.replace

调用 this.$router.replace() 方法,可以跳转到指定的 hash 地址,从而展示对应的组件页面。

push 和 replace 的区别:

  • push 会增加一条历史记录
  • replace 不会增加历史记录,而是替换掉当前的历史记录
$router.go

调用 this.$router.go() 方法,可以在浏览历史中前进和后退

image-20221018225018920

$router.go 的简化用法

  • ① $router.back() 在历史记录中,后退到上一个页面
  • ② $router.forward() 在历史记录中,前进到下一个页面

行内使用编程式导航的时候, this必须省略

导航守卫

全局前置守卫

image-20221018231140743

守卫方法的回调函数中接收的3个形参

image-20221018231238560

image-20221018231433102

ES6模块化

在 node.js 中体验 ES6 模块化
  • ① 确保安装了 v14.15.1 或更高版本的 node.js
  • ② 在 package.json 的根节点中添加 “type”: “module” 节点
ES6 模块化的基本语法

主要包含如下 3 种用法:

  • ① 默认导出与默认导入
  • ② 按需导出与按需导入
  • ③ 直接导入并执行模块中的代码
按需导出与按需导入的注意事项
  • ① 每个模块中可以使用多次按需导出
  • ② 按需导入的成员名称必须和按需导出的名称保持一致
  • ③ 按需导入时,可以使用 as 关键字进行重命名
  • ④ 按需导入可以和默认导入一起使用

Promise

回调地狱

代码耦合性太强,牵一发而动全身,难以维护 、 大量冗余的代码相互嵌套,代码的可读性变差

Promise概念
  • ① Promise 是一个构造函数

    • 我们可以创建 Promise 的实例 const p = new Promise()
    • new 出来的 Promise 实例对象,代表一个异步操作
  • ② Promise.prototype 上包含一个 .then() 方法

    • 每一次 new Promise() 构造函数得到的实例对象,
    • 都可以通过原型链的方式访问到 .then() 方法,例如 p.then()
  • ③ .then() 方法用来预先指定成功和失败的回调函数

    • p.then(成功的回调函数,失败的回调函数)
    • p.then(result => { }, error => { })
    • 调用 .then() 方法时,成功的回调函数是必选的、失败的回调函数是可选的
基于 Promise 按顺序读取文件的内容

Promise 支持链式调用,从而来解决回调地狱的问题

import thenFs from 'then-fs'

thenFs.readFile('./files/1.txt','utf-8').then((r1)=>{
  console.log(r1);
  return thenFs.readFile('./files/2.txt','utf-8')
})
.then((r2)=>{
  console.log(r2);
  return thenFs.readFile('./files/3.txt','utf-8')
}).then((r3)=>{
  console.log(r3);
})

通过 .catch 捕获错误

在 Promise 的链式操作中如果发生了错误,可以使用 Promise.prototype.catch 方法进行捕获和处理

如果不希望前面的错误导致后续的 .then 无法正常执行,则可以将 .catch 的调用提前

import thenFs from 'then-fs'

thenFs.readFile('./files/11.txt','utf-8').catch(err=>{
  console.log(err.message);
})
.then((r1)=>{
  console.log(r1);
  return thenFs.readFile('./files/2.txt','utf-8')
})
.then((r2)=>{
  console.log(r2);
  return thenFs.readFile('./files/3.txt','utf-8')
}).then((r3)=>{
  console.log(r3);
})
Promise.all() 方法

Promise.all() 方法会发起并行的 Promise 异步操作,等所有的异步操作全部结束后才会执行下一步的 .then 操作(等待机制)

Promise.race() 方法会发起并行的 Promise 异步操作,只要任何一个异步操作完成,就立即执行下一步的 .then 操作(赛跑机制)

import thenFs from "then-fs";

const promiseArr=[
  thenFs.readFile('./files/1.txt','utf-8'),
  thenFs.readFile('./files/2.txt','utf-8'),
  thenFs.readFile('./files/3.txt','utf-8')
]

// 一次性拿到所有Promise的结果
Promise.race(promiseArr).then((result)=>{
  console.log(result);
})

. 基于 Promise 封装读文件的方法

​ 方法的封装要求:

  • ① 方法的名称要定义为 getFile
  • ② 方法接收一个形参 fpath,表示要读取的文件的路径
  • ③ 方法的返回值为 Promise 实例对象
import fs from 'fs'
function getFile(fpath){
  return new Promise(function(reslove,reject){
      fs.readFile(fpath,'utf-8',(err,dataStr)=>{
        if(err) return reject(err)
        reslove(dataStr)
      })
  })
}

getFile('./files/111.txt').then((r1)=>{
  console.log(r1);
})
async/await

async/await 是 ES8(ECMAScript 2017)引入的新语法,用来简化 Promise 异步操作。在 async/await 出 现之前,开发者只能通过链式 .then() 的方式处理 Promise 异步操作。

.then 链式调用的优点: 解决了回调地狱的问题 .then 链式调用的缺点: 代码冗余、阅读性差、 不易理解

async/await 的使用注意事项
  • ① 如果在 function 中使用了 await,则 function 必须被 async 修饰
  • ② 在 async 方法中,第一个 await 之前的代码会同步执行,await 之后的代码会异步执行
import thenFs from "then-fs";
console.log('A');
async function getFile(){
  console.log('B');
  const s1=await thenFs.readFile('./files/1.txt','utf-8');
  console.log(s1);
  const s2=await thenFs.readFile('./files/2.txt','utf-8');
  console.log(s2);
  console.log('D');
}

getFile();
console.log('C');

// - 在 async 方法中,第一个 await 之前的代码会同步执行,await 之后的代码会异步执行
// 主线程退出执行C  然后再

EventLoop

同步任务和异步任务

为了防止某个耗时任务导致程序假死的问题,JavaScript 把待执行的任务分为了两类:

  • ① 同步任务(synchronous)

    • 又叫做非耗时任务,指的是在主线程上排队执行的那些任务
    • 只有前一个任务执行完毕,才能执行后一个任务
  • ② 异步任务(asynchronous)

    • 又叫做耗时任务,异步任务由 JavaScript 委托给宿主环境进行执行
    • 当异步任务执行完成后,会通知 JavaScript 主线程执行异步任务的回调函数

image-20221021093906638

import thenFs from "then-fs";

console.log('A');
thenFs.readFile('./files/1.txt','utf-8').then((dataStr)=>{
  console.log('B');
})
setTimeout(() => {
  console.log('C');
}, 0);

console.log('D');
// A\D是同步任务,根据代码顺序依次执行 
//  C 定时器 耗时0秒,立即去执行,放到任务队列中去,  
//  B 读文件是一个耗时的异步操作,  js将 该操作委托给宿主环境去执行  过一会,读文件操作完成,然后将其放到任务队列中去

宏任务和微任务

划分如下

image-20221021100337702

image-20221021100632049

// import thenFs from "then-fs";

// console.log('A');
// thenFs.readFile('./files/1.txt','utf-8').then((dataStr)=>{
//   console.log('B');
// })
// setTimeout(() => {
//   console.log('C');
// }, 0);

// console.log('D');  A D C B
// A\D是同步任务,根据代码顺序依次执行 
//  C 定时器 耗时0秒,立即去执行,放到任务队列中去,  
//  B 读文件是一个耗时的异步操作,  js将 该操作委托给宿主环境去执行  过一会,读文件操作完成,然后将其放到任务队列中去
// setTimeout(function() {
//  console.log('1'); 
// });

// new Promise(function(reslove){
//   console.log('2');
//   reslove()
// }).then(function(){
//   console.log('3');
// })

// console.log('4'); 2 4 3 1
// 先执行所有的同步任务  2    然后.then微任务放置队列等待 执行同步 4 后,再去执行微任务 3 然后再执行宏任务

console.log('1'); //同步
setTimeout(function() {
  console.log('2');
  new Promise(function(resolve){
    console.log('3');
    resolve()
  }).then(function(){
    console.log('4');
  })
});  //宏任务
// 1 5  6  2 3 4 7 8  9
new Promise(function(resolve){
  console.log('5');  //先执行  同步
  resolve()
}).then(function(){
  console.log('6');  // 微任务 
})
setTimeout(function(){// 宏任务
  console.log('7');
  new Promise(function(resolve){
    console.log('8');  //8
    resolve()
  }).then(function(){ 
    console.log('9'); // 9 微任务 
  })
})

组件化开发

什么是单页面应用程序

​ 一个 Web 网站中只有唯一的一个 HTML 页面,所有的 功能与交互都在这唯一的一个页面内完成。

一旦页面加载完成了,SPA 不会因为用户的操作而进行页面的重新加载或跳转。而是利用 JavaScript 动态地变换 HTML 的内容,从而实现页面与用户的交互

单页面应用程序的优点
  • ① 良好的交互体验
    • ⚫ 单页应用的内容的改变不需要重新加载整个页面
    • ⚫ 获取数据也是通过 Ajax 异步获取
    • ⚫ 没有页面之间的跳转,不会出现“白屏现象”
  • ② 良好的前后端工作分离模式
    • ⚫ 后端专注于提供 API 接口,更易实现 API 接口的复用
    • ⚫ 前端专注于页面的渲染,更利于前端工程化的发展
  • ③ 减轻服务器的压力
    • ⚫ 服务器只提供数据,不负责页面的合成与逻辑的处理,吞吐能力会提高几倍
单页面应用程序的缺点
  • ① 首屏加载慢

    • ⚫ 路由懒加载
    • ⚫ 代码压缩
    • ⚫ CDN 加速
    • ⚫ 网络传输压缩
  • ② 不利于 SEO

    • ⚫ SSR 服务器端渲染
什么是组件化开发

根据封装的思想,把页面上可重用的部分封装为组件,从而方便项目的开发和维护。

组件化开发的好处

  • 提高了前端代码的复用性和灵活性
  • 提升了开发效率和后期的可维护性

组件化的构成

vue 组件的构成

在 vue 2.x 的版本中, <template> 节点内的 DOM 结构仅支持单个根节点 template节点内的所有元素,最外层必须有 唯一的根节点进行包裹,否则报错

在 vue 3.x 的版本中, <template> 节点内的 DOM 结构支持多个根节点

让 style 中支持 less 语法 npm install less -D

vue3 组件注册时名称的大小写
  • ① 使用 kebab-case 命名法(俗称短横线命名法,例如 my-swiper 和 my-search)
  • ② 使用 PascalCase 命名法(俗称帕斯卡命名法或大驼峰命名法,例如 MySwiper 和 MySearch)

通过 name 属性注册组件

组件之间的样式冲突问题

vue2中 使用/deep/ .title vue3中 :deep(.title)

// /deep/ .title {
//   color: blue;
// }

:deep(.title) {
  color: blue;
}
以数组语法绑定 HTML 的 class
<h3 class="thin" :class="[isItalic?'italic':'',isDelete?'delete':'']">MyStyles组件</h3>

<script>
export default {
  name: 'MyStyle',
  data() {
    return {
      // 字体是否倾斜
      isItalic: false,
      // 是否应用删除效果
      isDelete: false
    }
  }
}
</script>

<style lang="less">
// 字体变细
.thin {
  font-weight: 200;
}

// 倾斜字体
.italic {
  font-style: italic;
}

.delete {
  text-decoration: line-through;
}
</style>
以对象语法绑定 HTML 的 class
<h3 class="thin" :class="classObj">MyStyles组件</h3>
    <button @click="classObj.italic=!classObj.italic">斜体</button>
    <button @click="classObj.delete=!classObj.delete">删除</button>
    
<script>
export default {
  name: 'MyStyle',
  data() {
    return {
      // 字体是否倾斜
      isItalic: false,
      // 是否应用删除效果
      isDelete: false,
      classObj:{
        italic:false,
        delete:false
      }
    }
  }
}
</script>
<style lang="less">
// 字体变细
.thin {
  font-weight: 200;
}

// 倾斜字体
.italic {
  font-style: italic;
}

.delete {
  text-decoration: line-through;
}
</style>
以对象语法绑定内联的 style

原文地址:http://www.cnblogs.com/Gurad/p/16814772.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性