Vue 1.0


# 概述

Vue 属于单页面应用 (SPA),指令后边都可以写 js 内容
单页面只需加载一次就把整个项目加载完了

# 如何开始一个 Vue 项目

做 Vue 开发的模式都是属于 node 项目开发模式。由于 Vue 框架本身非常复杂,需要各种工具包,需要搭建一个 Vue 的开发环境。对于新手来说,手动搭建一个 Vue 的开发环境非常难,但是官方提供了一个非常不错的脚手架 (命令行工具 CLI)

  • 安装脚手架工具 CLI,在命令行执行 npm i -g @vue/cli 全局脚手架工具 (在桌面就可以) vue --version 查看版本号
  • 利用脚手架工具搭建 vue 项目
    • 直接使用命令搭建 执行 vue create xxx(名字) 创建项目,选择默认预设即可
    • 使用图形化界面搭建 (只有 脚手架工具 3.X 以上才可以使用),在对应位置打开命令行工具,执行 vue ui 命令,会在浏览器中弹出图形化界面,可以创建项目了
    • 运行已经创建好的项目,其实就是执行项目下的 package.json 文件内的, scrip t 字段下的 serve 命令,这个命令执行完毕之后,默认的就会将 vue 的项目启动在本机 (localhost) 服务器下的 8080 端口,有冲突的话顺延。

# vue 项目默认的目录结构

  • node_modules (环境以及项目所需要的包),以后通过 npm 下载的所有的包也会放在这里
  • README.md 项目介绍文件
  • package.json (node 项目的标志性文件)
  • package-lock.json 项目安装的所有包的记录
  • babel.config.js (babel 的配置文件) babel: 转义 js 的
  • .gitignore 如果该项目是 git 仓库,那么 .gitignore 内声明的文件以及文件夹就不会上传到 git。该文件就是 git 仓库忽略上传的文件
  • public 文件夹 里面放的是单页面应用的 html 模板
  • src 文件夹 (vue 项目源代码)
    • assets 文件夹 (静态资源文件夹)
    • components 文件夹 (存组件的文件夹)
    • App.vue
    • main.js (项目的入口文件)(引入全局 css 在这里) 例如: import "./assets/global.css"; 这里的.css 不可以省略

# 组件

App.vue 组件是项目最大的组件,因为只有 App 组件会被渲染到页面的 #app 中

vue 组件的构成

  • template 标签
  • script 标签 (可以省略)
  • style 标签 (可以省略)

template 标签基本和以前的 html 非常像。一个 template 标签内只能有一个子级
style 标签给组件写样式
script 标签,一般必须默认导出一个对象,对象下有一个 name 属性属性值和组件名一样

# 组件的嵌套

  • App.vue 可以看成是 body

  • 父组件导入需要展示的子组件

  • 在父组件中 script 标签内的导出对象下,使用 components 属性,进行子组件注册

  • 简答操作 (案例简单排版,可不看)

    • App.vue 文件

      <template>
        <div id="app">
          <!-- vue 的 template 内开始标签和结束标签之间如果没有内容,请将标签写成单闭合 -->
          <header />
        </div>
      </template>
      
      <script>
        import Header from "./components/Header";
        export default {
          name: "App",
          components: {
            // 名:组件的值 (名其实就是一个自定义标签)
            // 上边Header导入的是值(import),这里值和名一样,上边的标签(<Header />)是名
            Header,
          },
        };
      </script>
    • Header.vue 文件

      <template>
        <header>
          <h2>我是头部</h2>
        </header>
      </template>
      
      <script>
        export default {
          name: "Header", //写成大写的
        };
      </script>

# 模板语法

其实就是 如何在 template 中使用 js

  • 在开始和结束标签之间使用,需要使用双花括号语法 {{ }}
  • 当作属性的属性值使用,需要使用 vue 的指令 v-bind (可以简写为 : (冒号))

# prop

将整个对象下的 所有属性一次性全部传递 v-bind="todo" (todo 是 prop 数据) 接收的时候 props:['id','text'] , 这些都是 todo 中的属性

父组件提供子组件需要展示的内容
用来实现简单的组件复用,子组件在父组件出现的时候,需要展示的内容可以让父组件提供

实现 prop 的

  • 1. 在父组件内传递相应的数据给子组件,直接在组件的标签上当作属性传递数据,属性名可以自定义,属性值是传递的真正数据

    • 案例一:父组件文件

      <template>
        <div class="right">
          <div class="top">
            <Box
              imgTitle="pic1"
              imgSrc="https://www.samsungmobilepress.com/asset/asset/8578e85c-4f8b-4652-8565-580aab3f8fc3/306x240.jpg"
            />
          </div>
        </div>
      </template>
    • 案例二:父组件文件

      <template>
        <div class="left">
          <!-- Content 时候可能展示p,有时候是h,有时候是a -->
          <!-- 将需要展示的不同 html 结构写在组件的开始标签和结束标签之间 -->
          <content>
            <p>展示的内容</p>
          </content>
          <content>
            <h2>展示的内容</h2>
          </content>
          <!-- 上面这种传递 prop 的方式称为 slot(插槽) -->
        </div>
      </template>
      
      <script>
        import Content from "./Content";
        export default {
          name: "Left",
          components: {
            Content,
          },
        };
      </script>
  • 2. 子组件获取父组件传递的数据展示,需要在子组件内使用 props 属性接收。

    • 案例一:使用数组方式接收

      子组件文件

      <template>
        <div class="box">
          <!-- <img v-bind:src="imgSrc" alt /> -->
          <img :src="imgSrc" alt />
          <p>{{imgTitle}}</p>
        </div>
      </template>
      
      <script>
        export default {
          name: "Box",
          // 这个数据可以认为是一个该组件内的全局变量随意使用。
          props: ["imgTitle", "imgSrc"],
          // prop 数据的使用
          // 1. 在 template 中直接用,需要遵循vue的模板语法
          // 2. 在 script 中需要使用 this.xxx
        };
      </script>
    • 案例二:使用插槽

      <template>
        <div class="content">
          <!-- 父组件传递的 slot  prop直接使用 slot 标签接收 -->
          <slot />
        </div>
      </template>
      
      <script>
        export default {
          name: "Content",
        };
      </script>
  • 3. 轮播图小案例

    • 父文件

      <template>
        <div id="app">
          <div v-if="arr.length" class="news_list">
            <div v-for="news in arr" :key="news.id">
              <img :src="news.imgSrc" alt />
              <div class="info">
                <span>{{news.date}}</span>
                <h3>{{news.title}}</h3>
                <p>
                  <!-- 关键字 -->
                  <!-- <span v-for="(word,index) in news.keyWords" :key="index">#{{word}}</span> -->
                  <keyword
                    v-for="(word,index) in news.keyWords"
                    :key="index"
                    :word="word"
                  />
                </p>
              </div>
            </div>
          </div>
        </div>
      </template>
      
      <script>
        import keyword from "./components/Keyword";
        export default {
          name: "App",
          components: {
            keyword,
          },
          data() {
            return {
              arr: [
                {
                  id: 1,
                  title: "Samsung Internet 14.0 Beta is Now Available",
                  imgSrc:
                    "https://www.samsungmobilepress.com/asset/asset/cd35c15e-bf6d-4683-a774-986b517d4837/306x240.jpg",
                  date: "March 09, 2021",
                  keyWords: [
                    "Samsung Internet",
                    "Samsung Internet 14.0",
                    "Update",
                    "Privacy",
                    "Multi-tasking",
                  ],
                },
              ],
            };
          },
        };
      </script>
    • 子文件

      <template>
        <span class="key_word">#{{word}}</span>
      </template>
      
      <script>
        export default {
          name: "Keyword",
          props: ["word"],
        };
      </script>

# data 组件的数据

<template>
  <header>
    <h2>我是头部</h2>
    <span>{{count}}</span>
  </header>
</template>
<script>
  // 数据改变引起视图改变
  // 1. 创建 data
  // 2. 将 data 展示到 视图上
  // 3. 修改 data
  export default {
    name: "Header",
    // data 必须是一个函数,并且返回一个对象,对象下的属性就是 data 数据
    // data 的使用和 prop 基本一样
    data() {
      return {
        count: 1000,
      };
    },
  };
</script>

# this 在 data prop methods …… 的使用

this 就是 vue 实例(组件本身)

  • template 直接使用,只需要遵循模板语法即可 (属性中 使用 : 绑定,标签间用 {{ }} )
  • script 标签中 使用 this.xxx xxx 表示对应的名字

# 事件处理

在 vue 里面的 methods 定义方法的时候,如果方法内需要使用 this 那么必须将该方法定义成普通函数

  • 定义事件

  • 绑定事件

    <template>
      <header>
        <span>{{count}}</span>
        <button v-on:click="add()">+</button>
        <button @click="remove()">-</button>
      </header>
    </template>
    
    <script>
      export default {
        name: "Header",
        data() {
          return {
            count: 1000,
          };
        },
        methods: {
          add() {
            this.count = this.count + 1;
          },
          remove() {
            // this.add(); //这里调用加法
            if (this.count > 1) {
              this.count = this.count - 1;
            }
          },
        },
      };
    </script>
  • 事件传参

    <template>
      <div>
        <h2>轮播图</h2>
        <div class="banner">
          <ul class="pagination">
            <!-- num 是从 1 开始的,所以这里要减1 -->
            <!-- 事件函数内获取事件对象 -->
            <!-- 如果绑定函数的时候没有传递额外的参数,那么事件的第一个参数默认就会是事件对象直接使用 event参数即可 -->
            <!-- 如果绑定函数的时候传递了参数,那么事件内想要使用事件对象的话,绑定的时候使用 $event 当作实参传递使用-->
            <li
              v-for="num in imgArr.length"
              :key="num.id"
              @click="changeActiveIndex(num - 1,$event)"
              :class="{ active: activeIndex === num - 1 }"
            ></li>
          </ul>
        </div>
      </div>
    </template>
    
    <script>
      export default {
        name: "SwiperDemo",
        data() {
          return {
            imgArr: [
              {
                id: 1,
                src:
                  "https://imgcps.jd.com/ling4/295Yi4/5ruhNTHlh481MA/p-5bd8/5001404a/cr/s/q.jpg",
              },
              {
                id: 2,
                src:
                  "https://imgcps.jd.com/ling4/491816LSn/6YMei1oDE/p-5bf7/7ba1c/cr/s/q.jpg",
              },
            ],
            activeIndex: 0,
          };
        },
        methods: {
          changeActiveIndex(index, e) {
            console.log(e);
            this.activeIndex = index;
          },
        },
      };
    </script>

# class 与 style 的绑定

# 样式的控制

  • class 的绑定

    • 直接使用 js 语法实现 比如三目运算符 v-bind

      <template>
        <header>
          <!-- 样式  结构 -->
          <button @click="changeShow">切换出现和显示</button>
          <!-- 将 show 和 box 的 class 挂钩 -->
          <div :class="show ? 'box':'box hide'"></div>
      
          <!--  对象语法 -->
          <!-- 普通的 js 语法实现 -->
          <div :class="{box:true,hide:!show}"></div>
      
          <!-- 数组语法实现 -->
          <div :class="['box',show?'':'hide']"></div>
        </header>
      </template>
      
      <script>
        export default {
          name: "Header",
          data() {
            return {
              show: true,
            };
          },
          methods: {
            changeShow() {
              this.show = !this.show;
            },
          },
        };
      </script>
    • 数组语法嵌套对象语法

  • style 的绑定

    • 直接使用 js 语法实现 比如三目运算符 v-bind

      <template>
        <header>
          <button @click="changeShow">切换出现和显示</button>
          <!-- vue 中的事件绑定可以直接写在标签上,不一定需要写在 methods 内定义 -->
          <!-- 直接写的话一般只写 修改 data 的操作 -->
          <button @click="active=!active">切换背景色</button>
          <!-- 普通的 js 语法实现 -->
          <div
            class="'box'"
            :style="`background-color:${active?'red':'#00b3d4'}`"
          ></div>
      
          <!-- 对象语法 -->
          <div
            class="box"
            :style="{backgroundColor:active?'red':'#00b3d4'}"
          ></div>
        </header>
      </template>
      
      <script>
        export default {
          name: "Header",
          data() {
            return {
              show: true,
              active: false,
            };
          },
          methods: {
            changeShow() {
              this.show = !this.show;
            },
          },
        };
      </script>
    • 数组语法就是可以使用多个对象语法 [对象语法 1,对象语法 2]

  • 指令 v-show 实现:只是可以实现出现或消失 none 和 block 的切换

    <template>
      <header>
        <div class="box" v-show="show"></div>
      </header>
    </template>
    
    <script>
      export default {
        name: "Header",
        data() {
          return {
            show: true,
          };
        },
        methods: {
          changeShow() {
            this.show = !this.show;
          },
        },
      };
    </script>

# 结构的添加和删除

  • 使用指令 v-if v-else v-else-if (v-if 和 v-else 必须是同级,且中间不能有东西)

    <template>
      <header>
        <div class="box" v-if="show"></div>
        <p v-else>box 消失了 我出现了</p>
        <!-- <p v-else-if="true">box 消失了 我出现了</p> -->
        <!-- 如果 v-if 成立,v-else-if和v-else就不看了 -->
      </header>
    </template>
    
    <script>
      export default {
        name: "Header",
        data() {
          return {
            show: true,
          };
        },
        methods: {
          changeShow() {
            this.show = !this.show;
          },
        },
      };
    </script>

# 条件渲染

  • v-show( 标签还在 ) 需要 比较频繁的操作 使用 v-show ( 不管初始条件是什么 ,元素都会被渲染)
  • v-if( 标签没了 ) 如果 运行时条件很少改变 ,使用 v-if (如果初始条件为假则不渲染,直到 条件第一次为真时,会开始渲染 )

# 列表渲染

  • v-for

    <template>
      <div class="right">
        <div class="keywords">
          <!-- 要根据数据渲染多个div -->
          <!-- 使用 v-for 的时候,必须使用 :key属性,而且 key 属性的属性值必须是在兄弟之间唯一的-->
          <div class="keyword" v-for="(word,index) in keyWords" :key="index">
            <span>{{`0${index+1}`}}</span>
            <h4>{{word}}</h4>
          </div>
        </div>
        <!-- 特殊的 v-for -->
        <div v-for="num in 4" :key="num">{{num}}</div>
        <!-- 1 2 3 4 -->
        <div v-for="(str,index) in 'hello'" :key="index">{{str}}</div>
        <!-- h e l l o -->
      </div>
    </template>
    
    <script>
      export default {
        name: "Right",
        data: () => ({
          keyWords: ["iphone 7", "iphone 8", "iphone 9", "iphone 10"],
        }),
      };
    </script>
  • 在 template 标签上使用 v-for

    <template>
      <div class="right">
        <!-- 在 template 标签上使用 v-for,可以渲染包含多个元素的内容 -->
        <!-- key 是不可以加在 template 标签上的,要加在里面元素内,而且最外层的每一个都要添加,还要唯一 -->
        <!-- 这里的template其实就是个空标签,啥也不是(空的) -->
        <ul>
          <template v-for="item in list">
            <li :key="item.id">{{item.id}}</li>
            <li :key="item.text">{{item.text}}</li>
          </template>
        </ul>
      </div>
    </template>
    
    <script>
      export default {
        name: "Right",
        data: () => ({
          list: [
            { id: 1, text: "zxcv" },
            { id: 2, text: "qwer" },
            { id: 3, text: "asdf" },
          ],
        }),
      };
    </script>
  • v-if 往往和 v-for 一起使用

    <template>
      <div class="right">
        <div v-if="keyWords.length" class="keywords">
          <div class="keyword" v-for="(word,index) in keyWords" :key="index">
            <span>{{`0${index+1}`}}</span>
            <h4>{{word}}</h4>
          </div>
        </div>
        <div v-else>暂时没有数据</div>
      </div>
    </template>
    
    <script>
      export default {
        name: "Right",
        data: () => ({
          keyWords: ["iphone 7", "iphone 8", "iphone 9", "iphone 10"],
        }),
      };
    </script>

# vue 组件的生命周期钩子 (函数)

从组件开始渲染 --> 销毁。不同的生命周期阶段对应着组件内不同的生命周期函数,在对应阶段所对应的函数会自动触发。所有的生命周期都是同步函数 (同步阻塞,异步非阻塞) 只有当前边的函数执行完之后,才能执行后边的函数

  • 初始渲染阶段

    • beforeCreate() 创建前,检查一遍有哪些 data,prop, 事件……(飞机起飞之前的检查)
    • created() 创建后,说明 data,prop, 事件…… 都已处理完毕,可以往页面上渲染了 在这里 可以修改 data 了,异步 请求修改数据 可以在此生命周期执行 (检查完毕可以起飞了)
    • beforeMount() 挂载 (渲染) 之前,组件的 render(渲染) 函数首次执行
    • mounted() 组件渲染完毕,组件就出现在了页面中,可以 获取真实的 dom 节点 ,也可以进行异步请求,但一般在 created () 中请求
  • 数据更新渲染阶段(data,prop,slot…… 发生改变)

    • beforeUpdate() 更新之前 (数据更新时),数据更新时,没更新完毕
    • updated() 数据更新完毕 (页面更新也完毕了),可以 获取更新之后的 data 以及 真实 dom 节点 (由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子)
  • 销毁

    • beforeDestroy() 组件销毁前,实例仍然可以使用 一般用于清除定时器,清除 window 的滚动条事件
    • destroyed() 组件销毁后 所有的指令,事件,监听…… 都没了 ( 跟组件相关的没了,跟组件没关系的还在 )
  • 自动轮播图案例

    <template>
      <div>
        <h2>轮播图</h2>
        <div class="banner" @mouseenter="onMouseEnter" @mouseleave="onMouseLeave">
          <div class="img-wrap">
            <img
              :class="{ active: activeIndex === index }"
              v-for="(img, index) in imgArr"
              :src="img.src"
              :key="img.id"
              alt
            />
          </div>
          <div class="left-arrow" @click="leftArrow"><</div>
          <div class="right-arrow" @click="rightArrow">></div>
          <ul class="pagination">
            <li
              @click="changeActiveIndex($event,num - 1)"
              :class="{ active: activeIndex === num - 1 }"
              v-for="num in imgArr.length"
              :key="num.id"
            ></li>
          </ul>
        </div>
      </div>
    </template>
    
    <script>
      export default {
        name: "SwiperDemo",
        data() {
          return {
            imgArr: [
              {
                id: 1,
                src:
                  "https://imgcps.jd.com/ling4/2922989/5o5Yi4/5ruh1A/p-51d8/5001404a/cr/s/q.jpg",
              },
              {
                id: 2,
                src:
                  "https://imgcps.jd.com/ling4/4918116/576O51Sn/6YOo51DE/p-5bd1f7/7c1c/cr/s/q.jpg",
              },
            ],
            activeIndex: 0,
          };
        },
        methods: {
          changeActiveIndex(e, index) {
            this.activeIndex = index;
          },
          leftArrow() {
            const { activeIndex, imgArr } = this;
            if (activeIndex > 0) {
              this.activeIndex--;
            } else {
              this.activeIndex = imgArr.length - 1;
            }
          },
          rightArrow() {
            const { activeIndex, imgArr } = this;
            if (activeIndex === imgArr.length - 1) {
              this.activeIndex = 0;
            } else {
              this.activeIndex++;
            }
          },
          onMouseEnter() {
            clearInterval(this.run);
          },
          onMouseLeave() {
            this.run = setInterval(() => {
              this.rightArrow(); // 重点
            }, 1000);
          },
        },
        created() {
          // 在组件的 script 标签内,嵌套的函数内想要使用 this(组件本身) 需要将函数定义为箭头函数
          this.run = setInterval(() => {
            console.log("执行");
            this.rightArrow();
          }, 1000);
          // 这里建议使用this为组件添加方法
          // 想要定义一个组件内的全局变量,又不想弄成 data,可以直接使用 this.xxx 定义
        },
        beforeDestroy() {
          // 组件销毁之前调用。在这一步,组件仍然完全可用
          // 清除定时器,清除 window 的滚动条事件
          clearInterval(this.run);
        },
      };
    </script>

# 组件之间的交互

  • 父子组件之间

    • 父组件想要修改子组件的 data,将子组件的 data 定义到父组件中,然后将其当作 prop 传递给子组件,如果子组件想要修改的话,可以在父组件定义修改的方法,将该方法传递给子组件执行, 切莫直接修改 prop

      • 父文件

        <template>
          <div id="app">
            <button @click="open">open a dialog</button>
            <!-- 父组件传递给子组件的prop如果是一个函数的话 -->
            <!-- 可以将这种传递方式换成自定义事件的传递 -->
            <dialog :visibility="visibility" :close="close" />
          </div>
        </template>
        
        <script>
          import Dialog from "./components/DialogDemo/Dialog";
          export default {
            name: "App",
            components: {
              Dialog,
            },
            data() {
              return {
                visibility: false,
              };
            },
            methods: {
              open() {
                this.visibility = true;
              },
              close() {
                this.visibility = false;
              },
            },
          };
        </script>
      • 子文件

        <template>
          <div v-show="visibility" class="dialog-wrap">
            <!-- 遮罩 -->
            <div class="mask"></div>
            <!-- 弹窗 -->
            <div class="dialog">
              <button @click="close">取消</button>
            </div>
          </div>
        </template>
        
        <script>
          export default {
            name: "Dialog",
            // prop 的验证,类型检查
            // 接收 prop 的时候需要使用对象形式
            props: {
              visibility: {
                type: Boolean, // 值的类型,非必须的
                default: false, // 默认值是对象类的时候必须使用函数返回该对象,非必须的
                // required: true // 必须传递(加上就是必须传visibility),非必须的
                // validator 自定义验证函数 非必须
                /* validator: (value) => {
                  // return true; //通过
                  // value 指的就是传递过来的值,满足条件就是通过,不满足条件就是出错
                  return [1, 2].includes(value); //必须是1和2中的一个
                }, */
              },
              close: Function, // 类型校验简单版
            },
          };
        </script>
  • 案例

    将兄弟组件的状态共享到父组件中,当作 props 传递

    • TodoWrap.vue 文件 (父组件)

      <template>
        <div class="todo-wrap">
          <h1>todos</h1>
          <TodoForm />
          <TodoList :todos="todos" :delTodo="delTodo" />
          <!-- 第二个delTodo是和method中的delTodo对, 
          :delTodo和TodoList文件中的delTodo对,
          TodoList中的@delTodo和TodoItem文件中的对 -->
        </div>
      </template>
      
      <script>
        import TodoForm from "./TodoForm";
        import TodoList from "./TodoList";
        export default {
          name: "TodoWrap",
          components: { TodoForm, TodoList },
          data() {
            return {
              todos: [
                { id: "7t7t7d", text: "666", isCompleted: true },
                { id: "f898dsf", text: "给力", isCompleted: false },
              ],
            };
          },
          methods: {
            delTodo(id) {
              const delIndex = this.todos.findIndex((todo) => todo.id === id);
              if (delIndex > -1) {
                this.todos.splice(delIndex, 1);
              }
            },
          },
        };
      </script>
    • TodoForm.vue 文件和 TodoList.vue 文件是兄弟文件 TodoForm 要修改 TodoList

      <template>
        <div class="todo-form">
          <span>图标</span>
          <input type="text" />
        </div>
      </template>
      
      <script>
        export default {
          name: "TodoForm",
        };
      </script>
    • TodoItem.vue 文件

      <template>
        <div class="todo-item">
          <div class="checkbox">
            <input type="checkbox" :checked="todo.isCompleted" :id="todo.id" />
            <label :for="todo.id"></label>
          </div>
          <span class="todo-text">{{todo.text}}</span>
          <span class="del" @click="$emit('delTodo',todo.id)">X</span>
        </div>
      </template>
      
      <script>
        export default {
          name: "TodoItem",
          props: ["todo"],
        };
      </script>

# 自定义事件

自定义事件只能往下传递一次,不能传递两次 , 解决方案是 上边的案例 (TodoWrap,TodoList,TodoItem)
父组件用 prop 传递给子组件,子组件用 props 接收到之后,使用自定义事件(@)传递给孙子组件

父组件有函数想传给子组件使用

  • 父文件

    <template>
      <div id="app">
        <button @click="open">open a dialog</button>
        <!-- 父组件传递给子组件的prop如果是一个函数的话,我们可以将这种传递方式换成自定义事件的传递 -->
        <!-- 用法:传递的时候 @事件名='对应的事件函数' @close="close" 
        接收的时候 不使用 prop 接收,直接使用$emit('事件名',事件参数) 
        template中直接使用 script中需要使用 this.$emit('事件名',事件参数)
        $emit('close')是直接执行传递过来的函数 -->
        <dialog :visibility="visibility" @close="close" />
      </div>
    </template>
    
    <script>
      import Dialog from "./components/DialogDemo/Dialog";
      export default {
        name: "App",
        components: {
          Dialog,
        },
        data() {
          return {
            visibility: false,
          };
        },
        methods: {
          open() {
            this.visibility = true;
          },
          close() {
            this.visibility = false;
          },
        },
      };
    </script>
  • 子文件

    <template>
      <div v-show="visibility" class="dialog-wrap">
        <div class="mask"></div>
        <!-- 弹窗 -->
        <div class="dialog">
          <!-- <button @click="$emit('close')">取消</button> -->
          <!-- 这两句效果一样,props中不需要接收close函数 -->
          <button @click="cancle">取消</button>
        </div>
      </div>
    </template>
    
    <script>
      export default {
        name: "Dialog",
        props: {
          visibility: {
            type: Boolean,
            default: false,
          },
          // close: Function,
        },
        methods: {
          cancle() {
            this.$emit("close");
          },
        },
      };
    </script>

文章作者: Mrr-cxh
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Mrr-cxh !
赏
 上一篇
Vue 2.0 Vue 2.0
Vue 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。
2021-04-30
下一篇 
TypeScript TypeScript
TypeScript是微软开发的一个开源的编程语言,通过在JavaScript的基础上添加静态类型定义构建而成。TypeScript通过TypeScript编译器或Babel转译为JavaScript代码,可运行在任何浏览器,任何操作系统。
2021-04-15
  目录