VUE 学习笔记

vue 学习

1. 组件基础

1.1 什么是组件

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

//定义组件
//使用Vue.component来定义组件
Vue.component("my-component-li",{
    template: "<li>这是一个名为my-component-li的组件</li>"
})

//组件定义好了,引用组件
<div>
    <ul>
        <my-component-li v-for="item in items" v-bind:item="item"></my-component-li> //1
    </ul>
</div>
//但是上面的方法只是把li 显示出来,一般li 是需要做列表渲染的,也就是要把数据传进去的,所以需要做一些改动
//1.要把data数据里的数组渲染到 li 里,先给 li 组件绑定 v-for 循环。
//2.然后把 item替换到li里
<script>
    //定义组件
    Vue.component("my-component-li",{
        props:["item"],//这里是把 template 里的 item 关联上了,为了把item 跟<my-component-li v-for="item in items"></my-component-li> 这里的 item 关联,需要用到 v-bind:item 方法
        template:"<li>{{item}}</li>"//2
    })
    var app = new Vue({
        //挂载元素 
        el:"#app",
        data:{
         items:['卫青','霍去病','张骞']
    }
       
    })
</script>

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

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

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

3 vue 从零开始一个项目

3.1 安装 vue

安装 vue 的方法有四种

  • 在页面上以 CDN 引入

    <script src="https://unpkg.com/vue@next"></script>
    
  • 下载 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是没有问题的。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,968评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,601评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,220评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,416评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,425评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,144评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,432评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,088评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,586评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,028评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,137评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,783评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,343评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,333评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,559评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,595评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,901评论 2 345

推荐阅读更多精彩内容