IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> Vue教学+实战(更新中) -> 正文阅读

[JavaScript知识库]Vue教学+实战(更新中)

声明

本文没有细讲,是为了帮助工作需要的朋友们快速入门Vue写的,或者是复习用的文章,所以不要说:啊!这里也不说因为啥,就这么写
别杠,杠就是你对,出门左转谢谢,求你给我写一篇细节点的好吗,我必给你点赞
此文会一直更到实战项目完事,附带代码,有错误欢迎指出,有问题留言,期间我会不断补充,细节一下文章内容的,大家一起加油吧

总览

在这里插入图片描述

在这里插入图片描述

Vue起步

Hello World

在官网下载vue.js(百度Vue进入官网)
我们先用原生来写一段代码

<body>
  <div id="app"></div>
  <script>
    var dom = document.getElementById('app')
    dom.innerHTML = 'hello world'
  </script>
</body>

现在我们要用vue来写了,我们要引入vue.js,然后创建vue实例
Vue.js在官网可以下载,我也会直接给大家

<body>
  <div id="app">{{ content }}</div>
  <script>
    var app = new Vue({
      el: '#app',
      data: {
        content: 'hello world'
      }
    })
  </script>
</body>

el配置项:实例负责管理的区域
我们如果要延迟两秒显示内容的话需要用setTimeout

<body>
  <div id="app">{{ content }}</div>
  <script>
    var app = new Vue({
      el: '#app',
      data: {
        content: 'hello world'
      }
    })
    setTimeout(function () {
      app.$data.content = 'bye world'
    }, 2000)
  </script>
</body>

这里$data理解为data的别名

我们用原生和Vue追重要的区别是,我们不需要DOM操作了

使用Vue.js实现TodoList(例子)

<body>
  <div id="app">
    <input type="text">
    <button>提交</button>
    <ul>
      <li>第一课的内容</li>
      <li>第二课的内容</li>
    </ul>
  </div>
</body>

现在我有个需求,输入框输入内容,提交后呈现在li
我们现在,要利用vue.js不再让我们的数据是死数据
具体代码如下

<body>
  <div id="app">
    <input type="text">
    <button>提交</button>
    <ul>
      <li v-for="item in list">{{item}}</li>
    </ul>
  </div>
  <script>
    var app = new Vue({
      el: '#app',
      data: {
        list: ['第一课的内容', '第二课的内容']
      }
    })
  </script>
</body>

效果和原生是一样的
v-for指令:类似于for,就是用来遍历渲染的
v-on:绑定事件
v-model:数据的双向绑定

<body>
  <div id="app">
    <input type="text" v-model="inputValue">
    <button v-on:click="handleBtnClick">提交</button>
    <ul>
      <li v-for="item in list">{{item}}</li>
    </ul>
  </div>
  <script>
    var app = new Vue({
      el: '#app',
      data: {
        list: ['第一课的内容', '第二课的内容'],
        inputValue: ''
      },
      methods: {
        handleBtnClick: function () {
        }
      },
    })
  </script>
</body>

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这就是双向的数据绑定

<body>
  <div id="app">
    <input type="text" v-model="inputValue">
    <button v-on:click="handleBtnClick">提交</button>
    <ul>
      <li v-for="item in list">{{item}}</li>
    </ul>
  </div>
  <script>
    var app = new Vue({
      el: '#app',
      data: {
        list: [],
        inputValue: ''
      },
      methods: {
        handleBtnClick: function () {
          this.list.push(this.inputValue)
          this.inputValue = ''
        }
      },
    })
  </script>
</body>

MVVM模式

在MVVM模式之前,前端采用的是MVP的模式
在这里插入图片描述

<body>
  <div>
    <input type="text">
    <button id="btn">提交</button>
    <ul></ul>
  </div>
  <script>
    function Page() { }
    $.extend(Page.prototype, {
      init: function () {
        this.bindEvents()
      },
      bindEvents: function () {
        var btn = $('#btn')
        btn.on('click', $.proxy(this.handleBtnClick,
          this))//proxy是jquery的一个方法,可以改变this指向
      },
      handleBtnClick: function () {
        alert('123')
      }
    })
    var page = new Page()
    page.init()
  </script>
</body>

这是一段基础的代码

<body>
  <div>
    <input id="input" type="text">
    <button id="btn">提交</button>
    <ul id="ul"></ul>
  </div>
  <script>
    function Page() { }
    $.extend(Page.prototype, {
      init: function () {
        this.bindEvents()
      },
      bindEvents: function () {
        var btn = $('#btn')
        btn.on('click', $.proxy(this.handleBtnClick,
          this))
      },
      handleBtnClick: function () {
        var inputValue = $("#input").val()
        var ulElem = $("#ul")
        ulElem.append('<li>' + inputValue + '</li>')
        $("#input").val('')
      }
    })
    var page = new Page()
    page.init()
  </script>
</body>

这是我们的效果代码
可以达到跟vue一样的效果
M:模型,在这个代码里不涉及Ajax,所以不涉及M层
V:视图
P:控制器

MVVM呢
在这里插入图片描述
注意,我们需要关注的是view和model层
VM层不需要我们去操作,它是Vue自动操作的

  1. M层:就是我们写的数据
  2. V层:就是视图
  3. VM层:就是我们数据变,视图就跟着变,这个不需要我们操作

在这里插入图片描述
在这里插入图片描述

前端组件化

每个组件就是每个页面上的一个区域,类似于原生里面,我们不也是用各个div盒子来进行分区吗
我们在Vue里,不同的区域我们会有对应的组件

使用组件化思想修改TodoList

<!DOCTYPE html>
<html lang="en">


<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="./vue.min.js"></script>
</head>


<body>
  <div id="app">
    <input type="text" v-model="inputValue">
    <button v-on:click="handleBtnClick">提交</button>
    <ul>
      <!-- <li v-for="item in list">{{item}}</li> -->
      <todo-item v-bind:content="item" v-for="item in list"></todo-item>
    </ul>
  </div>
  <script>
    //Vue.component用来注册全局组件
    Vue.component("TodoItem", {
      props: ['content'],
      template: "<li>{{content}}</li>"
    })
    var app = new Vue({
      el: '#app',
      data: {
        list: [],
        inputValue: ''
      },
      methods: {
        handleBtnClick: function () {
          this.list.push(this.inputValue)
          this.inputValue = ''
        }
      },
    })
  </script>
</body>


</html>

以上的是定义了一个全局组件,现在我们想定义一个局部组件呢
最主要的区别就是,我们需要去注册组件,用components去注册

<!DOCTYPE html>
<html lang="en">


<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="./vue.min.js"></script>
</head>


<body>
  <div id="app">
    <input type="text" v-model="inputValue">
    <button v-on:click="handleBtnClick">提交</button>
    <ul>
      <!-- <li v-for="item in list">{{item}}</li> -->
      <todo-item v-bind:content="item" v-for="item in list"></todo-item>
    </ul>
  </div>
  <script>
    //Vue.component用来注册全局组件
    // Vue.component("TodoItem", {
    //   props: ['content'],
    //   template: "<li>{{content}}</li>"
    // })
    // 注册局部组件
    var TodoItem = {
      props: ['content'],
      template: "<li>{{content}}</li>"
    }
    var app = new Vue({
      el: '#app',
      components: {
        TodoItem: TodoItem
      },
      data: {
        list: [],
        inputValue: ''
      },
      methods: {
        handleBtnClick: function () {
          this.list.push(this.inputValue)
          this.inputValue = ''
        }
      },
    })
  </script>
</body>


</html>

简单的组件间传值

<!DOCTYPE html>
<html lang="en">


<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="./vue.min.js"></script>
</head>


<body>
  <div id="app">
    <input type="text" v-model="inputValue">
    <button v-on:click="handleBtnClick">提交</button>
    <ul>
      <!-- <li v-for="item in list">{{item}}</li> -->
      <todo-item v-bind:content="item"
       v-bind:index="index"
        v-for="(item,index) in list" 
        @delete="handleItemDelete">
      </todo-item>
    </ul>
  </div>
  <script>
    //Vue.component用来注册全局组件
    // Vue.component("TodoItem", {
    //   props: ['content'],
    //   template: "<li>{{content}}</li>"
    // })
    // 注册局部组件
    var TodoItem = {
      props: ['content', 'index'],
      template: "<li @click='handleItemClick'>{{content}}</li>",
      methods: {
        handleItemClick: function () {
          this.$emit("delete", this.index)
        }
      }
    }
    var app = new Vue({
      el: '#app',
      components: {
        TodoItem: TodoItem
      },
      data: {
        list: [],
        inputValue: ''
      },
      methods: {
        handleBtnClick: function () {
          this.list.push(this.inputValue)
          this.inputValue = ''
        },
        handleItemDelete: function (index) {
          this.list.splice(index, 1)
        }
      },
    })
  </script>
</body>


</html>

Vue基础

Vue实例

Vue 的每个组件实际上都是一个Vue的实例,我们官方用vm

Vue2生命周期

生命周期函数就是Vue实例在某一个时间点会自动执行的函数,通过不同的时间点,可以做不同的时间,比较常用的是created和mounted,可以用来发axios和操作DOM
在这里插入图片描述

计算属性,方法与侦听器

<body>
  <div id="app">
    {{first + " " + last}}
  </div>
  <script>
    //创建了一个Vue实例
    var vm = new Vue({
      el: '#app',
      data: {
        first: "Jin",
        last: "Lin"
      }
    })
  </script>
</body>

我想让页面上显示Jin Lin,我在插值中是这个写法,可以发现,他成语句了,也就是有逻辑了,但是我们不想在模版的插值中去写逻辑,怎么办
我们引出一个概念:计算属性

<body>
  <div id="app">
    {{full}}
  </div>
  <script>
    //创建了一个Vue实例
    var vm = new Vue({
      el: '#app',
      data: {
        first: "Jin",
        last: "Lin"
      },
      computed: {
        full: function () {
          console.log('计算了');
          return this.first + " " + this.last
        }
      }
    })
  </script>
</body>

计算属性和别的最重要的区别就是:它还是属性,它和data里的属性最大的区别就是,它是通过计算得来的
计算属性有一个缓存的机制:就是计算属性依赖的值不发生改变,计算属性就不会发生计算

在这里插入图片描述
除了计算属性,我们还可以通过方法来达到相同的效果

<body>
  <div id="app">
    {{full()}}
  </div>
  <script>
    //创建了一个Vue实例
    var vm = new Vue({
      el: '#app',
      data: {
        first: "Jin",
        last: "Lin"
      },
      methods: {
        full: function () {
          return this.first + " " + this.last
        }
      },
    })
  </script>
</body>

只不过我们需要用()调用一下
但是这种方法,是没有计算属性有效的,为什么这么说呢
在这里插入图片描述
除了以上的两种,还有一种,叫做侦听

<body>
  <div id="app">
    {{full}}
    {{age}}
  </div>
  <script>
    //创建了一个Vue实例
    var vm = new Vue({
      el: '#app',
      data: {
        first: "Jin",
        last: "Lin",
        full: "Jin Lin",
        age: "18"
      },
      watch: {
        first: function () {
          console.log('计算了一次');
          this.full = this.first + "" + this.last
        },
        last: function () {
          console.log('计算了一次');
          this.full = this.first + "" + this.last
        }
      }
    })
  </script>
</body

在这里插入图片描述

watch也有缓存

在这里插入图片描述
那么,watch和computed都具有缓存的机制,推荐使用哪个呢
computed呗,因为简单呗

watch和computed区别:
watch可以开启异步任务,computed不可以开启异步,因为它依靠返回值
computed可以完成的功能,watch都可以完成

计算属性的getter和setter

<body>
  <div id="app">
    {{full}}
  </div>
  <script>
    //创建了一个Vue实例
    var vm = new Vue({
      el: '#app',
      data: {
        first: "Jin",
        last: "Lin",
      },
      computed: {
        full: {
          get: function () {
            return this.first + " " + this.last
          },
          set: function (value) {
            var arr = value.split(" ")
            this.first = arr[0]
            this.last = arr[1]
          }
        }
      }
    })
  </script>
</body>

Vue的样式绑定

<body>
  <div id="app">
    <div @click="hand" :class="{activated:isActivated}">
      hello world
    </div>
  </div>
  <script>
    //创建了一个Vue实例
    var vm = new Vue({
      el: '#app',
      data: {
        isActivated: false
      },
      methods: {
        hand: function () {
          this.isActivated = true
        }
      },
    })
  </script>
</body>

通过这个,我们就可以实现,点击变颜色了

<!DOCTYPE html>
<html lang="en">


<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="./vue.min.js"></script>
  <style>
    .activated {
      color: red;
    }
  </style>
</head>
<body>
  <div id="app">
    <div @click="hand" :class="{activated}">
      hello world
    </div>
  </div>
  <script>
    //创建了一个Vue实例
    var vm = new Vue({
      el: '#app',
      data: {
        activated: ""
      },
      methods: {
        hand: function () {
          this.activated = "activated"
        }
      },
    })
  </script>
</body>
</html>

我们想再点击变黑,互相切换呢

        hand: function () {
          this.activated = this.activated === "activated" ? "" : "activated"
        }

可以用if else,但是三元表达式不是更简便,看着更牛b嘛,嘿嘿
那么,如果我们直接绑定style呢,两种写法:对象形式,数组形式
对象:

<body>
  <div id="app">
    <div :style="styleObj">
      hello world
    </div>
  </div>
  <script>
    //创建了一个Vue实例
    var vm = new Vue({
      el: '#app',
      data: {
        styleObj: {
          color: "red"
        }
      },
      methods: {
      },
    })
  </script>
</body>

变色的

<body>
  <div id="app">
    <div :style="styleObj" @click="hand">
      hello world
    </div>
  </div>
  <script>
    var vm = new Vue({
      el: '#app',
      data: {
        styleObj: {
          color: "red"
        }
      },
      methods: {
        hand: function () {
          this.styleObj.color = this.styleObj.color === "red" ? "black" : "red"
        }
      },
    })
  </script>
</body>

数组模式

<body>
  <div id="app">
    <div :style="[styleObj,{fontSize:'20px'}]" @click="hand">
      hello world
    </div>
  </div>
  <script>
    var vm = new Vue({
      el: '#app',
      data: {
        styleObj: {
          color: "red"
        }
      },
      methods: {
        hand: function () {
          this.styleObj.color = this.styleObj.color === "red" ? "black" : "red"
        }
      },
    })
  </script>
</body>

字符串写法:适用于样式的类名不确定,需要动态指令
数组写法:要绑定的样式个数不确定,名字也不确定
对象写法:要绑定的样式个数不确定,名字也不确定,但要动态决定用不用

Vue中的条件渲染

<body>
  <div id="app">
    <div v-if="show">{{message}}
    </div>
  </div>
  <script>
    var vm = new Vue({
      el: '#app',
      data: {
        show: false,
        message: "Jin ? Lin"
      }
    })
  </script>
</body>


这是v-if,同时还有一个指令v-show

<body>
  <div id="app">
    <div v-if="show">{{message}}</div>
    <div v-show="show">{{message}}</div>
  </div>
  <script>
    var vm = new Vue({
      el: '#app',
      data: {
        show: false,
        message: "Jin ? Lin"
      }
    })
  </script>
</body>

在这里插入图片描述

注意这里的区别,v-if是直接没有,而v-show是用了display:none,也就是说,这两者在根本上就不同
显然,我们v-show的性能更高一些,因为它不用频繁地销毁和生产DOM
但是,v-if能和v-else配合使用,当然也可以和v-else-if使用,需要注意的是,中间不能被打断
还有一点需要注意的:v-show不能和template配合使用

Vue列表渲染

<body>
  <div id="app">
    <div v-for="item of list">
      {{item}}
    </div>
  </div>
  <script>
    var vm = new Vue({
      el: '#app',
      data: {
        list: [
          "Jin",
          "Lin"
        ]
      }
    })
  </script>
</body>

item of list中的of可以改成in

<body>
  <div id="app">
    <div v-for="(item,index) of list">
      {{item}}
    </div>
  </div>
  <script>
    var vm = new Vue({
      el: '#app',
      data: {
        list: [
          "Jin",
          "Lin"
        ]
      }
    })
  </script>
</body>

index是索引下标
在这里插入图片描述
为了提高性能,我们会给循环加一个key值(体现在虚拟DOM上)
这里不推荐用index,正常开发后端都会有一个id,或者是什么别的东西

<body>
  <div id="app">
    <div v-for="(item,index) of list" :key="item.id">
      {{item}} ---- {{index}}
    </div>
  </div>
  <script>
    var vm = new Vue({
      el: '#app',
      data: {
        list: [
          {
            id: '001',
            name: 'Jin'
          },
          {
            id: '002',
            name: 'Lin'
          }
        ]
      }
    })
  </script>
</body>

现在页面是这个效果
在这里插入图片描述
我们需要进行一下改进
在这里插入图片描述
我们还可以遍历对象

<body>
  <div id="app">
    <div v-for="item of userInfo">
      {{item}}
    </div>
  </div>
  <script>
    var vm = new Vue({
      el: '#app',
      data: {
        userInfo: {
          name: "shaka",
          age: 18,
          gender: "男"
        }
      }
    })
  </script>
</body>

我们可以加一个key

<body>
  <div id="app">
    <div v-for="(item,key) of userInfo">
      {{item}}----{{key}}
    </div>
  </div>
  <script>
    var vm = new Vue({
      el: '#app',
      data: {
        userInfo: {
          name: "shaka",
          age: 18,
          gender: "男"
        }
      }
    })
  </script>
</body>

在这里插入图片描述
我们可以发现这个key就是键名,那么item就是键值
当然,我们还可以加index
在这里插入图片描述

Vue中的set方法

在这里插入图片描述
这是对象的set方法
我们要是操作数组对象的话
我们可以用push、pop、shift等数组的api,这里也可以用set
首先,如果我们直接改的话

<body>
  <div id="app">
    <div v-for="(item,index) of userInfo">
      {{item}}
    </div>
  </div>
  <script>
    var vm = new Vue({
      el: '#app',
      data: {
        userInfo: [1, 2, 3, 4]
      }
    })
  </script>
</body>

在这里插入图片描述
在这里插入图片描述

Vue中的事件绑定

<body>
  <div id="app">
    <button @click="hand">Button</button>
  </div>
  <script>
    var vm = new Vue({
      el: '#app',
      methods: {
        hand: function (e) {
          console.log(e);
        }
      },
    })
  </script>
</body>

在这里插入图片描述
这是我们正常的写法
在这里插入图片描述
在这里插入图片描述
那么我们应该怎么办呢
在这里插入图片描述
这种写法有什么好处呢
在这里插入图片描述
它可以让我们传递一些额外的参数
这就是绑定事件的两种写法
看下面的带代码

<body>
  <div id="app">
    <form action="/abc" @click="hand">
      <input type="submit">
    </form>
  </div>
  <script>
    var vm = new Vue({
      el: '#app',
      methods: {
        hand: function (e) {
          console.log(e);
        }
      },
    })
  </script>
</body>

在这里插入图片描述
在这里插入图片描述
那么,我们想阻止表单提交的默认行为,怎么去做
在这里插入图片描述
这么写未免麻烦,简写形式呢
在这里插入图片描述
这个prevent叫做事件修饰符,同样的修饰符还有好几个
在这里插入图片描述
在这里插入图片描述

<body>
  <div id="app">
    <input @keydown="hand">
  </div>
  <script>
    var vm = new Vue({
      el: '#app',
      methods: {
        hand: function (e) {
          console.log(e.target.value);
        }
      },
    })
  </script>
</body>

在这里插入图片描述
我们想输入回车的时候再输出到控制台,这个时候就需要按键修饰符了
在这里插入图片描述
还有系统修饰符需要注意,比如ctrl,它代表你必须一边按住ctrl一边输入才行
还有监测鼠标右键:@click.right 就可以了

<body>
  <div id="app">
    <div @click.right="hand">click</div>
  </div>
  <script>
    var vm = new Vue({
      el: '#app',
      methods: {
        hand: function (e) {
          console.log("right");
        }
      },
    })
  </script>
</body>

Vue中的表单绑定

核心就是v-model指令,之前介绍双向绑定的时候已经给大家介绍过了,这里是想说,不止可以应用在input框中,还可以应用在别的地方
textarea,checkbox都可以应用

<body>
  <div id="app">
    <select v-model="value">
      <option disabled>--请选择--</option>
      <option>A</option>
      <option>B</option>
      <option>C</option>
    </select>
    {{value}}
  </div>
  <script>
    var vm = new Vue({
      el: '#app',
      data: {
        value: ""
      }
    })
  </script>
</body>

需要注意的是,我们给option加value呢
在这里插入图片描述
这样页面会优先显示value的值,如果没有value才会显示text的内容
当然,v-model也有修饰符,比如lazy(失去焦点发生反应),number
就是input框有一个问题,就是我们不管输入字符串还是数字,它都会返给我们一个字符串

<body>
  <div id="app">
    <input type="text" v-model="value">
    {{value}}
  </div>
  <script>
    var vm = new Vue({
      el: '#app',
      data: {
        value: ""
      },
      watch: {
        value: function () {
          console.log(typeof this.value);
        }
      }
    })
  </script>
</body>

在这里插入图片描述
在这里插入图片描述
还有一个trim,就是去空格,这个就不多说了

Vue组件

Vue组件的细节点

在这里插入图片描述
这是我们正常去写一个表格
那我们想用组件去写呢

<body>
  <div id="app">
    <table>
      <tbody>
        <row></row>
        <row></row>
        <row></row>
      </tbody>
    </table>
  </div>
  <script>
    Vue.component('row', {
      template: '<tr><td>this is row</td></tr>'
    })
    var vm = new Vue({
      el: '#app'
    })
  </script>
</body>

但是会出bug,违背了我们h5的规范
在这里插入图片描述
那么我们就会用is来解决这个问题

<body>
  <div id="app">
    <table>
      <tbody>
        <tr is="row"></tr>
        <tr is="row"></tr>
        <tr is="row"></tr>
      </tbody>
    </table>
  </div>
  <script>
    Vue.component('row', {
      template: '<tr><td>this is row</td></tr>'
    })
    var vm = new Vue({
      el: '#app'
    })
  </script>

用is属性,不会出bug
既能保证tr里是我们的组件,又能保证它符合h5的编码规范,不会出bug

在这里插入图片描述
同理,ul,li也是这个道理
我现在想对代码进行改进
在这里插入图片描述
这样可以吗
在这里插入图片描述
答案是不可以的,这是为什么
这里要说的是,我们虽然在vm(根组件)里面的data可以写成对象形式,但是在非根组件(也就是子组件)中是不可以的,我们要求必须是个函数
在这里插入图片描述
这样写就不会发生问题了
这里就要说,为什么要是个函数了

ref:用来操作DOM

<body>
  <div id="app">
    <div ref="hello" @click="hand">hello world</div>
  </div>
  <script>
    var vm = new Vue({
      el: '#app',
      methods: {
        hand: function () {
          console.log(this.$refs.hello);
        }
      },
    })
  </script>
</body>

在这里插入图片描述

父子组件的数据传递

首先,我们先注册局部组件

<body>
  <div id="app">
    <counter></counter>
    <counter></counter>
  </div>
  <script>
    //局部组件
    var counter = {
      template: '<div>0</div>'
    }
    var vm = new Vue({
      el: '#app',
      components: {
        counter: counter
      }
    })
  </script>
</body>

父组件通过属性的形式向子组件传递数据

<body>
  <div id="app">
    <counter :count="0"></counter>
    <counter :count="1"></counter>
  </div>
  <script>
    //局部组件
    var counter = {
      props: ['count'],
      template: '<div>{{count}}</div>'
    }
    var vm = new Vue({
      el: '#app',
      components: {
        counter: counter
      }
    })
  </script>
</body>

在这里插入图片描述
我现在想做这么一个效果,就是点击后自加1

<body>
  <div id="app">
    <counter :count="0"></counter>
    <counter :count="1"></counter>
  </div>
  <script>
    //局部组件
    var counter = {
      props: ['count'],
      template: '<div @click="hand">{{count}}</div>',
      methods: {
        hand: function () {
          this.count++
        }
      },
    }
    var vm = new Vue({
      el: '#app',
      components: {
        counter: counter
      }
    })
  </script>
</body>

这样可以实现,但是这样是不被允许的
这是一个在Vue里面被称作单项数据流的东西,就是,我们只能用父组件传递过来的值,而不能去修改它
在这里插入图片描述

所以我们采用这种方式,组件中的this,永远指向自身。即便是父组件传递过来的数据,vue底层也帮你都转到自组件的属性上去了。
那我们,子组件向父组件传值呢:自定义事件

<body>
  <div id="app">
    <counter :count="3" @inc="handleIncrease"></counter>
    <counter :count="2" @inc="handleIncrease"></counter>
    <div>{{total}}</div>
  </div>
  <script>
    //局部组件
    var counter = {
      props: ['count'],
      data() {
        return {
          number: this.count
        }
      },
      template: '<div @click="hand">{{number}}</div>',
      methods: {
        hand: function () {
          this.number = this.number + 2
          this.$emit('inc', 2)//可以传递参数
        }
      },
    }
    var vm = new Vue({
      el: '#app',
      data: {
        total: 5
      },
      components: {
        counter: counter
      },
      methods: {
        handleIncrease: function (step) {//step就是接受inc的参数
          // alert(step)
          this.total += step
        }
      }
    })
  </script>
</body>

组件参数校验与非props特性

<body>
  <div id="app">
    <child content="hello world"></child>
  </div>
  <script>
    Vue.component('child', {
      props: ['content'],
      template: '<div>{{content}}</div>'
    })
    var vm = new Vue({
      el: '#app',
    })
  </script>
</body>


这是一段正常的父传值给子的代码,我们现在有一个需求,子在接受父的数据的时候,我们想对其进行约束,我们应该怎么去做呢
比如,我们只接受字符串
在这里插入图片描述
那我们的需求是,字符串或者数字呢
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
那么什么是非props特性,就是子组件没人接收数据
在这里插入图片描述

给组件绑定原生事件

<body>
  <div id="app">
    <child @click="hand"></child>
  </div>
  <script>
    Vue.component('child', {
      template: '<div>Child</div>'
    })
    var vm = new Vue({
      el: '#app',
      methods: {
        hand: function () {
          alert('Jin?Lin')
        }
      },
    })
  </script>
</body>

我们发现它是无法生效的
在这里插入图片描述
这样才属于我们绑定了原生的事件,可以触发
在这里插入图片描述
那如果我想要触发自定义的事件呢
在这里插入图片描述
那如果我们不想这么写,我们可以用一个native修饰符

<body>
  <div id="app">
    <child @click.native="hand"></child>
  </div>
  <script>
    Vue.component('child', {
      template: '<div>Child</div>',
    })
    var vm = new Vue({
      el: '#app',
      methods: {
        hand: function () {
          alert('Jin?Lin')
        }
      },
    })
  </script>
</body>

也可以达到效果

非父子组件间的传值

我们知道组件的拆分,积类似于原生的div

在这里插入图片描述
我们知道了父子组件之间的传递,但是如果我们不是父子之间的传递呢,比如兄弟之间的传值,隔辈之间的传值呢
我们的确可以通过父子传值的方式,一直反复下去,可以达到效果,但是这样太费劲了
那么怎么做到简单的方式呢?

vuex和总线的机制(发布订阅模式、观察者模式)

vuex在后面单说,这里先介绍总线

<body>
  <div id="app">
    <child content="Jin"></child>
    <child content="Lin"></child>
  </div>
  <script>
    Vue.prototype.bus = new Vue()
    Vue.component('child', {
      props: {
        content: String
      },
      template: '<div @click="hand">{{content}}</div>',
      methods: {
        hand: function () {
          this.bus.$emit('change', this.content)
        }
      },
      mounted: function () {
        var this_ = this
        this.bus.$on('change', function (msg) {
          this_.content = msg
        })
      }
    })
    var vm = new Vue({
      el: '#app',
    })
  </script>
</body>

但是我们之前说过了,我们Vue有单向数据流,不能直接修改根组件传过来的值
所以要进行改进
在这里插入图片描述
这样就没问题了

在Vue中使用插槽

<body>
  <div id="app">
    <child></child>
  </div>
  <script>
    Vue.component('child', {
      template: '<div><p>hello</p></div>',
    })
    var vm = new Vue({
      el: '#app',
    })
  </script>
</body>

这是一段正常的代码,相信大家到这里,是没什么问题了
页面显示如下
在这里插入图片描述
现在,我们对代码进行更改
在这里插入图片描述
在这里插入图片描述
我们发现页面出现了一些问题,我们发现父组件传过来的p标签被转义了,那么我们不想让它转义怎么办
我们进行如下的改进就可以了
在这里插入图片描述
在这里插入图片描述
所以,显然这么写是有问题的
同时,如果用这种方法传的值过多的话,代码就不好看了
这样,我们就需要一个新概念了:插槽(这里是默认插槽)

<body>
  <div id="app">
    <child>
      <p>Lin</p>
    </child>
  </div>
  <script>
    Vue.component('child', {
      props: ['content'],
      template: `<div>
                     <p>Jin</p>
                    <slot></slot>
                </div>`,
    })
    var vm = new Vue({
      el: '#app',
    })
  </script>
</body>

也就是说,通过插槽,我们可以更方便地向自组件传递DOM元素
同时,slot还可以设置默认值
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
我们现在看这段代码
在这里插入图片描述

这是它的页面效果
那么,我现在不想要这个效果呢,想一一对应着来呢
这就需要具名插槽了

<body>
  <div id="app">
    <child>
      <div class="header" slot="header">header</div>
      <div class="footer" slot="footer">footer</div>
    </child>
  </div>
  <script>
    Vue.component('child', {
      template: `<div>
                    <slot name="header"></slot>
                    <slot name="footer"></slot>
                </div>`,
    })
    var vm = new Vue({
      el: '#app',
    })
  </script>
</body>

在这里插入图片描述

这样就OK了
这样的好处是,如果我们插入多个DOM结构
具名插槽也可以有默认值,这里不演示了

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-07-21 21:27:19  更:2022-07-21 21:27:47 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 -2025/1/11 12:29:10-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码