VUE 学习笔记

vue 学习

1. 组件基础

1.1 什么是组件

组件是可以服用的 vue 实例,说白了是一组可以重复使用的模板。组件里面可以套用组件。

//定义组件
//使用Vue.component来定义组件
Vue.component("my-component-li",{
    template: "
  • 这是一个名为my-component-li的组件
  • " }) //组件定义好了,引用组件
      //1
    //但是上面的方法只是把li 显示出来,一般li 是需要做列表渲染的,也就是要把数据传进去的,所以需要做一些改动 //1.要把data数据里的数组渲染到 li 里,先给 li 组件绑定 v-for 循环。 //2.然后把 item替换到li里

    2. 前端,服务器和数据库

    [图片上传失败...(image-3a922-1656668459121)]

    解释:前端可以是 vue 等框架,服务器可以是由 node 搭建的也可以是 node 的框架 express,数据库使用 MySQL

    3 vue 从零开始一个项目

    3.1 安装 vue

    安装 vue 的方法有四种

    • 在页面上以 CDN 引入

      
      
    • 下载 javascript 文件并自行托管

      即下载 vue 的 .js 文件然后放到自己的工程文件中,然后在项目中去引用。

    • 使用 npm 安装它

      npm 为你和你的团队打开了连接整个 JavaScript 天才世界的一扇大门。它是世界上最大的软件注册表,每星期大约有 30 亿次的下载量,包含超过 600000 个 包(package) (即代码模块)。来自各大洲的开源软件开发者使用 npm 互相分享和借鉴。包的结构使您能够轻松跟踪依赖项和版本。
      
      下面是关于 npm 的快速介绍:
      
      npm 由三个独立的部分组成:
      
      网站
      注册表(registry)
      命令行工具 (CLI)
      网站 是开发者查找包(package)、设置参数以及管理 npm 使用体验的主要途径。
      
      注册表 是一个巨大的数据库,保存了每个包(package)的信息。
      
      CLI 通过命令行或终端运行。开发者通过 CLI 与 npm 打交道。
      
    • 使用 vue 脚手架 CLI 来构建它。推荐使用 vue 脚手架。

      Vue 提供了一个官方的 CLI,为单页面应用 (SPA) 快速搭建繁杂的脚手架。它为现代前端工作流提供了功能齐备的构建设置。只需要几分钟的时间就可以运行起来并带有热重载、保存时 lint 校验,以及生产环境可用的构建版本。更多详情可查阅 Vue CLI 的文档
      

    3.1.1 使用 vue-cli 创建项目

    • 安装 node.js 使用 vue-cli 必须先安装 node

    • 安装 vue cli

      npm install -g @vue/cli
      
    • 创建项目名

      vue create 项目名
      
    • 根据提示进行选择

    ps. 因为 npm 的包的下载速度很慢,可以使用淘宝的镜像资源 cnpm 来加快速度:

    npm install -g cnpm --registry=https://registry.npm.taobao.org
    使用 npm 去安装 cnpm
    

    当项目使用 vue create 项目名并且选择配置完成以后会自动生成一些文件

    cd 项目名 // 进入项目中
    npm run serve 启动项目
      App running at:
      - Local:   http://localhost:8080/
      - Network: http://192.168.31.146:8080/
      即项目启动成功
    

    [图片上传失败...(image-974b78-1656668459121)]

    img

    [图片上传失败...(image-27abf5-1656668459121)]

    方法和计算属性

    方法定义在
    methods(){
        方法体
    }
    computed:{
        计算属性
    }
    两个使用中非常相似,不同点是计算属性是静态的。相当于把计算结果缓存起来成为静态的属性,避免系统开销
    

    4. mysql

    mysql 环境变量配置了以后可以直接用 cmd 去启动 mysql

    mysql -uroot -p
    //连接的命令
    如果不配置环境变量,则每次需要进入到 mysql 的安装文件的bin目录的去启动,本机的安装目录是 C:\Program Files\MySQL\MySQL Server 8.0\bin 
    即,如果没有配置环境变量,则需要在 cmd 中输入 cd C:\Program Files\MySQL\MySQL Server 8.0\bin 进入到这个目录中再链接数据库。
    
    本数据库的账户密码都是 root
    

    5. node.js

    5.1 创建一个经典的服务器

    1. 创建空文件夹 nodejsdemo

    2. 初始化 npm init

    3. 在文件目录中看到主入口文件是 index.js, 所以创建 index.js

    4. [图片上传失败...(image-1d4eff-1656668459121)]

    5. 在 index.js 中写入 console.log(1234), 终端输入node index.js 运行输出 1234说明 node 运行了 index.js

    6. 这样一个简单的服务器就做好了

      
      // setServers
      
      const http = require("http"); // require 引入模块的方法,http 是一个默认的模块,所以可以直接写不用再从第三方引入
      const hostname = "127.0.0.1"; //定义本地地址(服务器地址)
      const port = 3000; //定义端口号
      
      //http有createServer 方法(接受参数,req 为请求参数,res 为响应参数)
      var server = http.createServer((req,res)=>{
          res.statusCode = 200;
          res.setHeader("Content-type","text/plain")
          res.write("hello node")
          res.end()
      });
      
      //server 启动以后使用listion 方法去看是否启动成功
      server.listen(port, hostname, ()=>{
          console.log("服务器已启动");
      })
      
      • nodemon 自动重新启动项目
        • 先全局安装 npm i nodemon -g
        • 然后在 package.json 文件里添加 “serve”:nodemon index.js

      5.2 node中的 http 模块

      1. http 服务端

        • 在服务端使用

        • 请求对象(IncomingMessage类的实例)和相应对象(ServerResponse类的实例)

      2. http客户端

        • 客户端使用(request, get)
        • 请求对象(ClientRequest类的实例)和相应对象(IncomingMessage类的实例)

      5.3 node 的其他模块(看文档)

      • Buffer 模块
      • url 模块
      • fs 模块
      • crypto模块
      • path模块
      • 模板引擎

    6. express.js

    基于 node.js 的极简,快速,开放的 web 开发框架。exprss 和 node 的关系就如同 jQuery 和 js 的关系。

    6.1 express 安装

    • npm init 初始化文件

    • 安装 express 并将其保存在依赖列表中

      npm install express //因为express 是第三方的库,所以要安装才能使用
      
    • 安装完成进入 hello wold 页面

      const express = require("express"); //引入express模块
      var app=express(); //express 函数运行以后赋值给 app。 app 即是应用对象
      
      //使用get方法
      app.get("/",function(req,res){
          res.send("hello express")
      })
      
      //使用 liston方法监听
      app.listen(3000,function(){
          console.log("运行环境")
      })
      
    • 代码赋值到 index.js(如果在 package.jason文件中改了入口文件,那么就需要运行改动后的文件。index.js 是默认的入口文件), node 运行 index.js

    • 浏览器中运行 localhost:3000

    6.2 请求本地的 json 数据

    module.expors={
        "name":"zhangsan",
        "age":20
    }
    //module.exports 意思是当我们创建了一个 data的js 文件以后,我们要把这个文件暴露出去,这样别的程序可以访问的到
    

    6.3 静态资源

    为了提供如图片,js,css文件之类的静态资源,使用 express 中的中间件 express.static.

    例如,图片放在 static 文件加下面,我们如果要使用这些静态资源则使用

    app.use(express.static("static")),那么 static 文件夹里的文件就对外开放了。

    app.use(express.static("",))
    

    6.4 路由

    路由的目的,上面的所有get/put/path等接口都写在了主文件 mian.js里,这样太乱了,为了把这些接口函数放到一个专门的地方,所以引入了路由的概念。

    • 创建一个文件夹 route
    • 在文件夹里创建文件 index.js 文件

    7. 链接 mysql

    • 现在终端安装mysql

      npm install mysql
      
    • 在路由文件去引入 mysql

    var mysql = require(mysql)
    

    8. dos 命令

    • cd xx 进入到哪个文件
    • cd ../ or cd.. 进入上一个文件夹
    • cls 清除

    实战项目

    1. 安装 node 搭建后台 (略)

    2. 搭建后台项目

      1. cmd 输入 npm init 初始化项目。 (npm init -y 快速初始化项目)
      2. 初始化成功后将在项目里出现 package.json 文件
      3. 创建与入口文件同名的文件js
      4. 新增项目启动命令
      5. nodemon: 自动重启项目当code内容改变以后
        npm i nodemon -g
        然后在 package.json 文件里添加 “serve”:nodemon index.js
      
    3. package.json 字段解释

      "dependencies": 项目依赖
      "devDependencies":开发依赖(只在开发的时候会用,项目打包上线的时候,这个部分不会被打包)
      "name": "expressdemo", 项目名称
      "version": "1.0.0", 项目版本
      "description": "", 项目描述
      "main": "main.js" 项目的入口文件
      
    4. 如果 npm 比较满,安装一下淘宝镜像 cnpm

    5. 安装并使用 koa + koa-router

      koa 基于 node.js 的下一代 web 开发框架。

      koa 是新的框架由 express 原班人马打造,致力于成为 web 应用和 api 开发的更小的,更富有表现力的基石。

      koa 建立在 es6+ 之上,提升现代的 js 语法。

      使用 generators 和 async / await

      优雅,简洁,灵活,体积小

      相关名利 npm - koa -s, npm - koa-router -s

    //入口文件的基本设置
    
    //1. 引入 koa 
    const Koa = require("koa");
    
    //2. 实例化 koa
    const App = new Koa();
    
    //3. 搭建服务
    App.use(async ctx=>{
        ctx.body = "荆承鹏学习前端";
    })
    
    //4. 监听端口
    App.listen(5000, ()=>{
        console.log("服务器启动成功:5000")
    })
    
    // nodemon index.js 启动服务 http://localhost:5000 可以访问
    
    // 这个时候有个问题,上面的无法指定特定的 api 端口,比如 http://localhost:5000/index, http://localhost:5000/index1 是不同的路径,这个时候就需要 koa-router
    
    // 安装 koa-router : npm i koa-router -s
    
    1. 引入 koa-router 以后需要做的

      //1. 引入 koa 
      const Koa = require("koa");
      const Router = require("koa-router");
      
      //2. 实例化 koa
      const App = new Koa();
      const router = new Router();
      
      //3. 搭建服务
      // App.use(async ctx=>{
      //     ctx.body = "荆承鹏学习前端";
      // })
      // 使用 koa-router 来启动服务,并且可以指定不同的路径
      
      router.get("/index", async ctx=>{
          ctx.status = 200;
          ctx.body = "荆承鹏学习前端koa-router";
      })
      
      router.get("/index1", async ctx=>{
          ctx.status = 200;
          ctx.body = "月薪过万不是梦"
      })
      
      //配置路由
      // 调用router.routes()来组装匹配好的路由,返回一个合并好的中间件
      // 调用router.allowedMethods()获得一个中间件,当发送了不符合的请求时,会返回 `405 Method Not Allowed` 或 `501 Not Implemented`
      App.use(router.routes());
      App.use(router.allowedMethods());
      
      
      
      //4. 监听端口
      App.listen(5000, ()=>{
          console.log("服务器启动成功:5000")
      })
      
    1. 搭建数据库环境 (安装 mysql 略)

    2. 安装 Navicat premium (mysql 的图形管理系统)

    3. 编写后台接口

      使用 node 连接 sql 数据库
      安装依赖
       数据库 npm i mysql -s
       跨域 npm i koa2-cors -s 
       获取body 请求参数 npm i koa-bodyparser -s
      封装 bd.js: 对链接数据库的函数进行模块封装
      编写接口:接口 koa-router+mysql编写接口
      测试接口:使用 vscode 中postman 插件进行接口测试
      
      bd.js 内容
      // 引入 bd.js 作为数据库的链接文件
      // 引入 mysql
      const mysql = require("mysql");
      
      //声明变量用来存储数据库绑定连接以后的对象属性
      
      const poolSql = mysql.createPool({
          host: "localhost",
          user:"root",
          password:"root",
          port: "3306",
          database:"test"
      
      }) 
      
      function query(sql, value){
          return new Promise((resolve,reject)=>{
              poolSql.query(sql,value, (err,result)=>{
                  if(err){
                      reject(err)
                  }else{
                      resolve(result)
                  }
              })
          })
      }
      
      module.exports = query;
      

      入口页面 index.js 内容

      //1. 引入 koa 
      const Koa = require("koa");
      const Router = require("koa-router");
      const Pool = require("mysql/lib/Pool");
      //引入bd.js 里的模块
      const poopSql = require("./bd.js");
      const cors = require("koa2-cors"); //跨域
      const bodyparser = require("koa-bodyparser");//body 参数
      
      //2. 实例化 koa
      const App = new Koa();
      const router = new Router();
      
      //3. 搭建服务
      // App.use(async ctx=>{
      //     ctx.body = "荆承鹏学习前端";
      // })
      // 使用 koa-router 来启动服务,并且可以指定不同的路径
      
      router.get("/index", async ctx=>{
          ctx.status = 200;
          ctx.body = "荆承鹏学习前端koa-router";
      })
      
      router.get("/query", async ctx=>{
          ctx.status = 200;
          try {
              let _sql = "SELECT * FROM t_user";
              let _data = await poopSql(_sql);
              ctx.body = {
                  errorMessage : "",
                  result:true,
                  data: _data
              }
          } catch (error) {
              ctx.body = {
                  errorMessage : "查询失败",
                  result:false,
                  data: null
              }
          }
      })
      
      //配置路由
      // 调用router.routes()来组装匹配好的路由,返回一个合并好的中间件
      // 调用router.allowedMethods()获得一个中间件,当发送了不符合的请求时,会返回 `405 Method Not Allowed` 或 `501 Not Implemented`
      App.use(router.routes());
      App.use(router.allowedMethods());
      App.use(cors());
      App.use(bodyparser());
      
      
      //4. 监听端口
      App.listen(5000, ()=>{
          console.log("服务器启动成功:5000")
      })
      
    1. 查询,添加,修改,删除数据库字段的写法

      // bd.js
      //1. 引入 koa 
      const Koa = require("koa");
      const bodyparser = require("koa-bodyparser");//body 参数
      const Router = require("koa-router");
      const Pool = require("mysql/lib/Pool");
      //引入bd.js 里的模块
      const poolSql = require("./bd.js");
      const cors = require("koa2-cors"); //跨域
      
      
      //2. 实例化 koa
      const App = new Koa();
      const router = new Router();
      
      //3. 搭建服务
      // App.use(async ctx=>{
      //     ctx.body = "荆承鹏学习前端";
      // })
      // 使用 koa-router 来启动服务,并且可以指定不同的路径
      
      router.get("/index", async ctx => {
          ctx.status = 200;
          ctx.body = "荆承鹏学习前端koa-router";
      })
      
      //查询数据库
      router.get("/query", async ctx => {
          ctx.status = 200;
          try {
              let _sql = "SELECT * FROM t_user";
              let _data = await poolSql(_sql);
              ctx.body = {
                  errorMessage: "",
                  result: true,
                  data: _data
              }
          } catch (error) {
              ctx.body = {
                  errorMessage: "查询失败",
                  result: false,
                  data: null
              }
          }
      })
      //向数据库表中添加信息
      router.post("/add", async ctx => {
          ctx.status = 200;
          let _info = ctx.request.body; //上下文request 里的 body 的内容赋给 _info
      
          //表中username 是必填项,所以先判断一下
          if(!_info.name){
              ctx.body = {
                  errorMessage:"name 是必填项目",
                  result:false,
                  data:null
              }
              return
          }
          try {
              let _sql = "INSERT INTO demo (id,name,number,price) VALUES (?,?,?,?)";
              let _value = [_info.id,_info.name, _info.number, _info.price];
              await poolSql(_sql,_value);
              ctx.body = {
                  errorMessage: "",
                  result: true,
                  data: null
              }
          } catch (error) {
              ctx.body = {
                  errorMessage: "添加失败",
                  result: false,
                  data: null
              }
          }
      })
      //向数据库表中修改信息
      router.put("/put", async ctx=>{
          ctx.status = 200;
          let _info = ctx.request.body;
          if(!_info.id){
              ctx.body = {
                  errorMessage:"id 是必填项目",
                  result:false,
                  data:null
              }
              return
          }else if(!_info.name){
              ctx.body = {
                  errorMessage:"name 是必填项目",
                  result:false,
                  data:null
              }
              return
          }
          try{
              let _sql = "UPDATE demo SET name=?,number=?,price=? WHERE id=?";
              let _value = [_info.name, _info.number, _info.price,_info.id];
              await poolSql(_sql, _value);
              ctx.body = {
                  errorMessage: "",
                  result: true,
                  data: null
              }
          }catch(err){
              ctx.body = {
                  errorMessage: "修改失败",
                  result: false,
                  data: null
              }
          }
      
      })
      //删除数据库中的数据,通过路径传参的方式
      router.delete("/delete/:id", async ctx=>{
          ctx.status = 200;
          console.log(ctx);
          let _info = ctx.params;
          try{
              let _sql = "DELETE FROM demo WHERE id=?";
              let _value = [_info.id];
              await poolSql(_sql,_value);
              ctx.body ={
                  errorMessage: "",
                  result: true,
                  data: null
              }
          }catch(err){
              ctx.body = {
                  errorMessage:"删除错误",
                  result:false,
                  data:null
              }
          }
      })
      
      
      //配置路由
      // 调用router.routes()来组装匹配好的路由,返回一个合并好的中间件
      // 调用router.allowedMethods()获得一个中间件,当发送了不符合的请求时,会返回 `405 Method Not Allowed` 或 `501 Not Implemented`
      App.use(cors()).use(bodyparser()).use(router.routes()).use(router.allowedMethods());
      
      
      
      //4. 监听端口
      App.listen(5000, () => {
          console.log("服务器启动成功:5000")
      })
      
    1. 搭建前端框架

      使用 vue3 + vite 搭建项目

      此步骤以前的都是服务器端的设置,项目里新建文件夹把服务器端的项目文件命名为 server 然后在这个项目里开始搭建前端。

      $ npm create vite@latest // 快速搭建一个项目
      

      Vue3 基础 api

      - defineComponent
      这是对 setup 函数进行封装,返回 options 的对象,主要就是为了服务 ts 而存在的。
      - ref
      接受一个内部值返回一个响应式可变的 ref 对象。 ref 对象具有指向内部值的单个 property.value
      - reactive
      与 ref 类似,不同的是它用来定义更为复杂的数据类型
      - toRefs
      将响应式对象转为普通对象,其中结果对象的每个 property 都指向原始对象对应的 property 的 ref
      - toRaw
      只是对原生数据进行修改,不改变更新 ui 视图
      - setup 函数
      这个函数主要是为了使用组合式 api,使用setup函数时候,有两个参数
      props: 可以从中获取组件的 props 参数,他是响应式的,也就是传入新的 prop 时候,它被更新;
      context: context是一个普通的 JavaScript对象,暴露了其他可能在 setup 中有用的值。这些值就是之前 vue2中 this 上暴露的 property 属性,比如 attrs, slots, emit
      注意:在setup() 中, this 不是该活跃实例的引用。
      

    引用 ant design vue

    npm install ant-design-vue --save
    

    当前端界面完成,开始前端和联调

    使用 axios 封装 api

    axios 是一个基于 promise 的 http 库,可以在浏览器和node.js 中使用。

    它符合现在的 mvvm 浪潮。

    vue笔记

    1. vue 零碎的知识点

    -Vue中有两种数据绑定,v-band 和 v-module
    1. 单向数据绑定 v-band:xxx 简写:xxx; 数据只能从 data 流向页面。
    2. 双向数据绑定 v-model:xxx 简写为 v-model = ""

    • el 和 data 的两种写法
      1. el的两种写法
        (1) new Vue 时候配置el 的属性
        (2)先创建实例子,然后通过$monunt("挂载")
      2. data的两种写法:对象式,函数式
        (1)对象式 data:{
        //写入data 的值,可以直接用在模板中
        }
        (2)函数式写法 data(){
        return {
        //写入data 的值,可以直接用在模板中
        }
        }
        在实际的项目中,主要谢函数式
        上面是这个的变形写法 data:function(){
        return {
        //写入data 的值,可以直接用在模板中
        }
        }
      3. 一个重要的原则:由 Vue 管理的函数一定不要写箭头函数,一旦写了箭头函数 this 的指向就不再是 Vue 了。

    2. mvvm 模型

    MVVM 模型,细说其实是 M-V-VM 模型
    M (model:指的是 data 中的数据)
    V (view) 视图:模板代码,即显示在页面中的内容
    VM (ViewModel) 视图模型,即 Vue 实例所做的事情

    发现:1: data 中所有数据都出现在了 vm 身上;vm身上所有属性,包括从原型链上继承来的都可以直接使用在模板中直接使用。

    3. vue2 数据双向绑定的原理

    Object.defineProperty() 实现数据代理

    1. vue中的数据代理
      通过vm对象来代理data对象中的属性的操作(读/写)
    2. vue中的数据代理的好处
      更加方便的操作data中的数据
    3. 基本原理
      • 通过Object.defineProperty()把data中的对象所有属性添加到vm上。
      • 为每个添加到vm的属性,都指定一个getter/setter.
      • 在getter/setter内部去操作(读/写)data中对应的的属性

    4. 事件处理

    1. 使用v-on:xxx或者@xxx绑定事件,其中xxx是事件名称;
    2. 事件回调需要配置在methods对象中,最终会在vm上;
    3. methods中配置的函数,不要用箭头函数,否则this就不是vm了;
    4. methods中配置的函数,都是被vue所管理的函数,this的指向是vm或者组件实例对象;
    5. @lick="demo"和@lick="demo($event)"效果一致,但是后者可以传参。

    5. 事件修饰符

    描述:就是修饰事件的

    1. prevent:阻止默认事件(常用)
    2. stop:阻止事件冒泡(常用)
    3. once:事件只触发一次(常用)
    4. capture:使用事件的捕获模式
    5. self:只有event.target是当前操作的元素时才触发事件
    6. passive:事件的默认行为立即执行,不用等事件回调执行完毕。
      案例:@click.once="showMe",这个事件只执行一次;@click.prevent="showMe"阻止事件的默认行为,比如在 a 标签上添加此修饰符,在点击a标签以后,执行showMe函数,a标签的跳转行为不执行。
    7. 修饰符可以连续写

    6. 键盘事件

    1. vue中常用的按键别名:

      • 回车 => enter
      • 删除 => delete (捕获删除和退格键)
      • 退出 => esc
      • 空格 => space
      • 换行 => tab
      • 上 => up
      • 下 => down
      • 左 => left
      • 右 => right
    2. vue未提供别名的按键,可以使用按键原始的key值去绑定,但是要注意转换为kebab-case(短横线命名)

    3. 系统修饰键(用法特殊):ctrl, alt, shift, meta

      • 配合keyup使用:按下修饰键的同时,再按其他键释放后触发;
      • 配合keydown使用:正常触发事件。
    4. 也可以使用keycode去指定具体的案件(不推荐)

    5. Vue.config.keycodes.自定义按键名 = 键码,可以去定制按键别名。

    6. 案例:@keyup.enter="showMe" (键盘的按键输入enter键,在按键升起的时候触发)。或者@keydown.enter="showMe" (键盘的按键输入enter键,在按键按下的时候触发)。

    7. 内置指令

    1. v-bind:单向绑定解析表达式,可以简写为:xxx

    2. v-model:双向数据绑定

    3. v-for:遍历数据、对象、字符串

    4. v-on:绑定事件监听,简写为@xxx

    5. v-if:条件渲染(动态控制节点是否存在)

    6. v-show:条件渲染(动态控制节点是否展示)

    7. v-else:条件渲染(动态控制节点是否存在)

    8. v-text:向所在节点中添加渲染文本内容;与插值语法区别:v-text会替换掉节点中的内容,{{xxx}}则不会。

    9. v-html

      • 作用:向指定节点中渲染包含html结构的内容;
      • 与插值语法的区别:v-html会替换掉节点中所有的内容,{{xxx}}不会
      • 严重注意:v-html有安全性问题。在网站上动态渲染任意html是非常危险的,容易导致xss攻击
      • 一定要在可信的内容上使用v-html,永远不要用在用户输入上。
    10. v-once

      • v-once所在节点在初次动态渲染后,就视为静态内容了。
      • 以后数据的改变不会引起v-once所在结构的更新,可以用于优化性能。
    11. v-pre

      • 跳过其所在节点的编译过程
      • 可用它跳过没有使用指令语法,没有使用插值语法的节点,会加快编译
    12. v-cloak: v-cloak(没有值)

    - 本质是一个特殊属性,vue实例创建完毕并接管容器以后会删除v-cloak的属性
    - 使用css配合v-cloak可以解决网速慢时页面展示出插值语法的问题。
    

    8. 自定义指令

    1. 定义语法
      • 局部指令:
    new Vue({
        directives:{指令名称:配置对象}
    })
    或者
    new Vue({
        directives:{指令名:回调函数}
    })
    
    - 全局指令
    
    Vue.directive(指令名,配置对象)或者Vue.directive(指令名,回调函数)
    
    1. 配置对象中的常用的三个回调

      • .bind:指令与元素成功绑定是调用
      • .inserted:指令所在元素被插入页面时调用
      • .updated:指令所在模板结构被重新解析时调用
    2. 备注:

      • 指令定义时不加v-,但是使用时需要加v-
      • 指令名如果是多个单词,要使用连字符链接,不要用驼峰命名

    9. 计算属性

    1. 定义:要用的属性不存在,需要通过已有属性计算而来。
    2. 原理:底层借助了Object.defineProperty()方法提供的getter和setter
    3. get函数什么时候执行?
      • 初次读取的时候会运行一次;
      • 当依赖的数据发生变化时会被再次调用。
    4. 优势:与methods相比,内部有缓存机制(复用),效率更高,测试方便
    5. 备注:计算属性会最终出现在 vm 上,直接读取使用即可;如果计算属性要被修改,那必须写set函数去相应修改,且set中要引起计算时依赖的数据发生改变。

    10. 监视属性 watch

    1. 当被监视的属性发生变化时,回调函数自动调用,进行相关操作。
    2. 监视属性必须存在,才能进行监视
    3. 监视的两种写法:
      • new Vue 时传入 watch 配置
      • 通过vm.$watch("",{})监视

    11.条件渲染

    1. v-in
      • 写法:v-if、v-else-if,v-else
      • 适用于切换频率较低的场景
      • 特点:不展现 dom节点。dom直接被移除
      • 注意:v-if可以和v-else-if,v-else 一起使用,但是要求结构不能被打断。
    2. v-show
      • 写法:v-show
      • 适用于切换场景较高的场景
      • 不展示dom,但是dom被隐藏
    3. 备注:使用v-if时,元素可能无法获取到,而是用v-show的时候时可以获取到的

    12 v-for 指令

    1. 用于展示列表信息
    2. 语法:v-for="(item, index) in xxx" :key="yyy"
    3. 可以遍历:数组,对象,字符串(用的少),指定次数(用的少)

    12. 面试题 react,vue中key的作用(key的内部原理)

    1. 虚拟 dom 中 key 的作用:key是虚拟dom对象的标识,当数据发生变化时,vue会根据新数据生成新的虚拟dom,随后vue进行新虚拟dom与旧虚拟dom的差异比较,比较规则如下:
      • 旧虚拟dom用到了与新dom相同的key:
        (1)若虚拟dom中内容没有变化,直接复用之前的真是dom;
        (2)虚拟dom内容变化了,则生成新的真实dom,随后替换掉页面中旧的真实dom
      • 旧虚拟dom没有找到与新虚拟dom相同的key:创建新的真实dom,然后渲染到页面上;
    2. 用 index 作为key可能会引发的问题
      • 若对数据进行逆序添加,逆序删除等破坏顺序的操作,会产生没有必要的真实dom更新 ---> 页面没有问题,但是效率低。
      • 如果结构中还包含输入类的dom,会产生错误的dom更新 --> 界面会有问题
    3. 开发中如何选择key
      • 最好使用每条数据唯一的标识作为key,比如id,手机号,身份证号等。
      • 如果不存在对数据的逆序添加,逆序删除等破坏顺序的操作,仅用于渲染列表的展示,使用index作为key是没有问题的。

    你可能感兴趣的:(VUE 学习笔记)