11.前端:vue

艾编程架构课程第十九---二十三节笔记未完待续

  • 艾编程前端第一课:实现电商购物车
      • 01 - Vuejs介绍
      • 02 - Vuejs-快速下载和安装
      • 03 - Vuejs实操系列
      • 04 - Vuejs实操系列 - 插值表达式
      • 05- Vue基础篇 - 生命周期钩子
      • 06 - Vue内置指令 - 事件指令-v-on指令-点击事件
      • 07 - Vue内置指令 - 事件指令-v-on指令-事件修饰符
      • 08 - Vue内置指令 - 事件指令-v-on指令-按键修饰符
      • 09- Vue内置指令 - 文本指令-v-text v-html指令
      • 10 - Vue内置指令 - 属性绑定指令 - v-bind-指令
      • 11 - Vue内置指令 - v-bind - 指令操作样式style和class
      • 12 - Vue内置指令 - v-model指令获取form控件值的方式
      • 13 - Vue内置指令 - 循环指令 - v-for指令
      • 14 - Vue内置指令 - 条件指令 - v-if v-else-if v-else 指令
      • 15 - Vue内置指令 - 显示指令 -v-show 指令
      • ==拓展:==16 - Vuejs -Computed 计算属性
      • 17 - Vuejs实操系列 - Vuejs实战应用开发 + 购物车管理
      • 18 - Vuejs实操系列 - 掌握Vuejs中Axios完成异步请求-语法介绍
      • 19 -Vuejs实操系列 - 掌握Vuejs中Axios完成异步请求-参数获取
    • 第四部分:掌握和学习Vuejs组件开发
      • ==拓展:==20 - Vuejs组件 - 定义全局组件
      • ==拓展:==23 - Vuejs组件 - 组件的复用
      • ==拓展:==24 - Vuejs组件 - 局部注册
      • ==拓展:==25 - Vuejs组件 - 组件通信
      • ==拓展:==26 - Vuejs - 过滤器 - Filter
      • ==拓展:==26 - Vuejs - 过滤器 - Filter

艾编程前端第一课:实现电商购物车

01 - Vuejs介绍

官网:https://cn.vuejs.org

入门文档:https://cn.vuejs.org/v2/guide/

目标

什么是vuejs以及如何下载和安装Vuejs。

概述

Vue.js是一个轻巧、高性能、可组件化的MVVM库,同时拥有非常容易上手的API;

Vue.js是一个构建数据驱动的Web界面的库。

Vue.js是一套构建用户界面的 渐进式框架。与其他重量级框架不同的是,Vue 采用自底向上增量开发的设计。Vue 的核心库只关注视图层,并且非常容易学习,非常容易与其它库或已有项目整合。另一方面,Vue 完全有能力驱动采用单文件组件和 Vue 生态系统支持的库开发的复杂单页应用。数据驱动+组件化的前端开发。

简而言之:Vue.js是一个构建数据驱动的 web 界面的渐进式框架。Vue.js 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件。核心是一个响应的数据绑定系统。

尤雨溪,Vue.js 创作者,Vue Technology创始人,致力于Vue的研究开发。vue3.x / vue2.x

关于什么是MVVM模式:

11.前端:vue_第1张图片

基于传统的数据渲染


<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Documenttitle>
head>
<body>


    
    <div id="app">

    div>

    <script src="js/jquery.min.js">script>
    <script>

        // 入口函数调用方法进行初始化
        $(function () {
            // 执行初始化
            IcodingCart.loadData();
        })

        var IcodingCart = {

            loadData:function(){

                // 1:这里数据
                var userData = [{
                    id:"1",
                    name:"zhangsan",
                    age:32
                },{
                    id:"2",
                    name:"lisi",
                    age:32
                }];


                // 2:拼接开始
                var html = "";
                //开始遍历数据
                for(var i=0;i<userData.length;i++){
                    var user = userData[i];
                    html +="  
    \n" + "
  • id:"+user.id+"
  • \n"
    + "
  • name:"+user.name+"
  • \n"
    + "
  • age:"+user.age+"
  • \n"
    + "
"
; } //:3:找到目标元素 $("#app").html(html); } };
script> body> html>

传统模式问题:

1:数据和视图融合在一起。出现的问题:

  • 维护起来麻烦
  • 拼接也麻烦
  • 事件绑定也存在很多的问题

02 - Vuejs-快速下载和安装

1. 下载安装

下载地址:https://github.com/vuejs/vue

可以下载2.6.10版本https://github.com/vuejs/vue/archive/v2.6.10.zip

下载解压,在dist可得到vue.js文件。

2. npm安装(推荐)

在idea的左下角,有个Terminal按钮,点击打开控制台:

安装Vue,输入命令:

# save 的意思是将模块安装到项目目录下,并在package文件的dependencies节点写入依赖
npm install vue
npm install [email protected]

03 - Vuejs实操系列

步骤

1、引入vue.js文件

2、定义Vuejs对象和数据

3、定义dom

4、定义视图渲染数据


小结

1: el:代表vuejs从哪个dom开始进行管辖,一旦被el定义,那么会把当前dom中的视图(dom)中存在的指令或者插值表达式
通通进行数据的渲染。
2: 而数据的来源必须一定要在data中进行定义,也就是告诉只要在el管辖的范围内需要的数据必须要data中定义,否则无效。
注意事项:
1:注意点:el :#app 必须用id,可以用class吗。不推荐
2:注意点:Vue首字母必须是大写。

04 - Vuejs实操系列 - 插值表达式

语法

  • 该表达式支持JS语法,可以调用js内置函数(必须有返回值
  • 表达式必须有返回结果。例如 1 + 1,没有结果的表达式不允许使用,如:var a = 1 + 1;
  • 可以直接获取Vue实例中定义的数据或函数

代码


<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Documenttitle>
head>
<body >


    <div id="app">
        <p>{{username}}p>
        <p> {{age}}p>
        <p>{{password}}p>
        <hr>
        <p>{{price + num}}p>
        <p>{{price - num}}p>
        <p>{{price * num}}p>
        <p>{{price / num}}p>
        <p>{{price % num}}p>
        <hr>
        <p>{{male==0?"女":"男"}}p>
        <hr>
        {{user.id}}
        {{user.name}}
    div>

    <script src="js/vue.min.js">script>
    <script>
        var vue = new Vue({
            el:"#app",
            data:{
                username:"张三",
                age:"2",
                password:"3",
                price:12.1,
                num:11,
                male:0,
                user:{id:1,name:"zhangsan"}
            }
        })

    script>


body>
html>

插值闪烁(了解)

使用{{}}方式在网速较慢时会出现问题。在数据未加载完成时,页面会显示出原始的{{}},加载完毕后才显示正确数据,称为插值闪烁。类似如下的效果(最新vue是几乎没有此问题):或者使用v-cloak结合解决。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-V6vtkFl2-1595410166838)(assets/4-1567578304269.gif)]

05- Vue基础篇 - 生命周期钩子

目标

学习和了解vuejs的生命周期和this上下文对象。

概述

每个 Vue 实例在被创建时都要经过一系列的初始化过程 :创建实例,装载模板,渲染模板等。Vue为生命周期中的每个状态都设置了钩子函数(监听函数)。每当Vue实例处于不同的生命周期时,对应的函数就会被触发调用。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AoEK7nKk-1595410166839)(assets/lifecycle.png)]

例如:created代表在vue实例创建后;

可以在Vue中定义一个created函数,代表这个时期的构造函数:


<html>
<head>
    <meta charset="utf-8" />
    <title>生命周期title>
head>
<body>


<div id="app">{{message}}div>

<script src="js/vue.js">script>

<script>

    //vm
    var vm = new Vue({
        el : "#app",
        data : {
            message : 'hello world'
        },
        beforeCreate : function() {
            console.log(this);
            showData('1:创建vue实例前-beforeCreate', this);
        },
        created : function() {
            // 如果你要想获取数据必须在这里定义你要获取的业务。
            showData('2:创建vue实例后-created', this);
        },
        beforeMount : function() {
            showData('3:挂载到dom前-beforeMount', this);
        },
        mounted : function() {
            //$(function(){})
            showData('4:挂载到dom后-mounted', this);
        },
        beforeUpdate : function() {
            showData('5:数据变化更新前-beforeUpdate', this);
        },
        updated : function() {
            showData('6:数据变化更新后-updated', this);
        },
        beforeDestroy : function() {
            vm.test = "3333";
            showData('7:vue实例销毁前-beforeDestroy', this);
        },
        destroyed : function() {
            showData('8:vue实例销毁后-destroyed', this);
        }
    });

    function realDom() {
        console.log('真实dom结构:' + document.getElementById('app').innerHTML);
    }

    function showData(process, obj) {
        console.log(process);
        console.log('data 数据:' + obj.message)
        console.log('挂载的对象:')
        console.log(obj.$el)
        realDom();
        console.log('------------------')
        console.log('------------------')
    }

    //vm.message = "good...";
    //vm.$destroy();
script>
body>
html>

结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aAlnVaMq-1595410166841)(assets/1556508009196-1567577895029.png)]

生命周期目的:改变视图会改变data数据,改变数据就改变视图。提供的钩子函数可以在这些函数种去初始化一下数据。

指令对照表

https://cn.vuejs.org/v2/api/

指令名称 描述 用法
v-on 事件绑定 v-on:事件 = “事件名”
缩写:@事件 = “事件名”
点击事件:click,dblclick,change,blur
键盘事件:keydown/keyupkeypress
鼠标事件:mousedown,mouseover,mousemove,mouseout
v-text/v-html 文本取值 或者
两者的区别是:v-text不支持标签解析,v-html支持标签解析。
v-bind 属性取值 v-bind:属性 = “属性值”
缩写::属性 = “属性值”
解决在标签的属性上如何获取动态的数据值的问题。
比如: 或者
v-model 获取form控件值 用于form表单控制元素值的相关获取和同步。
v-for 循环迭代 一般用于循环数组,对象和对象数组。c:foreEach
v-show/v-if/v-else 隐藏/显示 v-show:是控制元素display:none/block的切换。v-if:是逻辑判断,控制元素的存在与不存在。 c:
v-pre 原样输出不解析 如果你不想解析插值表达式,原样输入可以使用v-pre
v-once 渲染一次 如果你想渲染一次,后面改变数据不会影响视图的变化,可以使用v-once。
v-cloak 解决网络延迟 往往在真实的场景中,插值表达式渲染会很慢,
而造成插件表达式的外漏,可以借助v-cloak和[v-cloak]{display:none;}来解决这个问题

06 - Vue内置指令 - 事件指令-v-on指令-点击事件

目标

掌握事件指令v-on的语法定义。

语法

事件操作是开发中用的最频繁的操作:vuejs中采用v-on指令+methods的方式来完成事件的定义和绑定。

语法如下:v-on:事件类型=“事件名称” 比如:v-on:click=“fun1”

简写:@事件类型=“事件名称”。比如:@click=“fun1”

代码


<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Documenttitle>
head>
<body>


<div id="app">
    <form action="">
        <p>账号: <input type="text">p>
        <p>密码: <input type="text">p>
        <p><button v-on:click="login">登录button>p>
        <p><button @click="login">@登录button>p>
    form>
div>



<script src="js/vue.min.js">script>

<script>
    // 第三步:初始化vuejs实例对象和数据
    // 重点:事件定义在methods中,以key:value的方式存在
    // 调用事件:v-on:事件类型="methods的key” 简写 @click="事件名"
    var vue = new Vue({//Vm
        el:"#app",
        data:{//---------------------data
            title:"117班所有学生,大家好,艾编程程序"
        },
        methods:{
            login(){
                alert("登录进来了......")
            }
        }

    })
script>

body>
html>

小结:

1: 事件指令:v-on:事件类型=“事件名” ,事件名必须定义在:methods对象,定义事件:执行业务逻辑改变数据data,一旦改变就会立即重新渲染视图(div)

2:如果没有参数,事件名是可以加括号也可以不加

3:如果传递参数的时候,请求括号不要加插值表达式

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kzbstRbw-1595410166843)(assets/1566784870562.png)]

07 - Vue内置指令 - 事件指令-v-on指令-事件修饰符

目标

掌握事件指令v-on事件操作符应用场景

概述

在事件处理程序中调***用 event.preventDefault()event.stopPropagation() 是非常常见的需求。尽管我们可以在方法中轻松实现这点,但更好的方式是:方法只有纯粹的数据逻辑,而不是去处理 DOM 事件细节。

为了解决这个问题,Vue.js 为 v-on 提供了事件修饰符。之前提过,修饰符是由点开头的指令后缀来表示的。

  • .stop :阻止事件冒泡
  • .prevent:阻止默认事件发生
  • .capture:使用事件捕获模式
  • .self:只有元素自身触发事件才执行。(冒泡或捕获的都不执行)
  • .once:只执行一次

语法

.prevent和 .once的用法:


在实际的开发中:button,submit和a连接都有各自默认的行为,比如button和submit会提交form表单,这个时候会造成业务的重复执行,所以可以使用:.prevent来解决这个问题。

08 - Vue内置指令 - 事件指令-v-on指令-按键修饰符

目标

Vue.js通过由点(.)表示的指令后缀来调用修饰符。

语法

Vue 允许为 v-on 在监听键盘事件时添加按键修饰符

全部的按键别名:
	
​	.enter(enter键)
​	.tab (Tab键)
​	.delete (捕获 "删除" 和 "退格" 键)
​	.esc (退出键)
​	.space(空格键)
​	.up (向上)
​	.down(向下)
​	.left(向左)
​	.right(向右)
​	

​	.ctrl
​	.alt
​	.shift
​	.meta

注意:在 Mac 系统键盘上,meta 对应 command 键 (⌘)。在 Windows 系统键盘 meta 对应 Windows 徽标键 (⊞)。在 Sun 操作系统键盘上,meta 对应实心宝石键 (◆)。在其他特定键盘上,尤其在 MIT 和 Lisp 机器的键盘、以及其后继产品,比如 Knight 键盘、space-cadet 键盘,meta 被标记为“META”。在 Symbolics 键盘上,meta 被标记为“META”或者“Meta
”。

代码


小结

获取键盘码代码


<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Documenttitle>
head>
<body>


<div id="app">
    <input type="text" id="getcode">
    <h1>你当前的键码是:<span id="code">span>h1>
div>

<script>

    // ascii表
    document.getElementById("getcode").onkeydown = function(e){
        document.getElementById("code").innerText = e.keyCode
    }

script>

body>
html>

09- Vue内置指令 - 文本指令-v-text v-html指令

目标

了解和掌握文本指令的用法,以及v-text和v-html的区别

小结

v-text和v-html 都是属于文本的值管理范畴,唯独的差别就是:

提示:v-text和插值表达式{{}}不支持标签解析,v-html支持标签解析

代码


小结

1:注意点:在指令上不要写插值表达式{{}}。

2:都可以支持算数运算。

3:v-text和插值表达式{{}}不支持标签解析,v-html支持标签解析

10 - Vue内置指令 - 属性绑定指令 - v-bind-指令

目标

了解和掌握属性动态绑定的v-bind的指令使用规则。

小结

插值语法:{{}} 是不能直接使用在属性上,需要借助v-bind指令来解决此问题!

语法:v-bind:属性=’'data数据key"

简写::属性=“data数据的key”,比如::src=“imgsrc”

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-htHk186C-1595410166845)(assets/1557907358338.png)]

代码


小结

如果想把data中的数据,放入到元素的属性上,那么久必须使用v-bind指令来完成。

11 - Vue内置指令 - v-bind - 指令操作样式style和class

目标

操作元素的 class 列表和内联样式是数据绑定的一个常见需求。因为它们都是属性,所以我们可以用 v-bind 处理它们:只需要通过表达式计算出字符串结果即可。不过,字符串拼接麻烦且易错。因此,在将 v-bind 用于 classstyle 时,Vue.js 做了专门的增强。表达式结果的类型除了字符串之外,还可以是对象或数组。

步骤

对象语法

我们可以传给 v-bind:class 一个对象,以动态地切换 class:

<div v-bind:class="{ active: isActive }">div>

案例如下:

<div
  class="static"
  v-bind:class="{ active: isActive, 'text-danger': hasError }"
>div>

和如下 data:

data: {
  isActive: true,
  hasError: false
}

结果渲染为:

<div class="static active">div>

isActive 或者 hasError 变化时,class 列表将相应地更新。例如,如果 hasError 的值为 true,class 列表将变为 "static active text-danger"

数组语法

我们可以把一个数组传给 v-bind:class,以应用一个 class 列表:

<div v-bind:class="[activeClass, errorClass]">div>
data: {
  activeClass: 'active',
  errorClass: 'text-danger'
}

渲染为:

<div class="active text-danger">div>

如果你也想根据条件切换列表中的 class,可以用三元表达式:

<div v-bind:class="[isActive ? activeClass : '', errorClass]">div>

这样写将始终添加 errorClass,但是只有在 isActive 是 truthy[1] 时才添加 activeClass

不过,当有多个条件 class 时这样写有些繁琐。所以在数组语法中也可以使用对象语法:

<div v-bind:class="[{ active: isActive }, errorClass]">div>

style同理。

真实案例


12 - Vue内置指令 - v-model指令获取form控件值的方式

目标

如何获取form控件元素值。

注意

Form元素是开发中使用最多的控件,如何获取空间元素的值。就必须借助于:v-model指令

代码


<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Documenttitle>
head>
<body>


<div id="app">
    <form action="">
        <p>账号: <input type="text" v-model="account">p>
        <p>密码: <input type="text" v-model="password">p>
        <p><button v-on:click.prevent="login">登录button>p>
        <p><button @click.prevent="login">@登录button>p>

        <hr>
        <p>调试代码p>
        你输入的信息是:{{account}} {{password}}
    form>
div>



<script src="js/vue.min.js">script>

<script>
    // 第三步:初始化vuejs实例对象和数据
    // 重点:事件定义在methods中,以key:value的方式存在
    // 调用事件:v-on:事件类型="methods的key” 简写 @click="事件名"
    var vue = new Vue({//Vm
        el:"#app",
        data:{//---------------------data
            account:"",
            password:"",
            title:"117班所有学生,大家好,艾编程程序"
        },
        methods:{
            login(){
                var account = this.account;
                var password = this.password;
                console.log(account,password)
                //ajax
            }
        }

    })
script>

body>
html>

小结

v-model只能用于form元素才有意义,所谓的双向数据绑定就是指:v-model

13 - Vue内置指令 - 循环指令 - v-for指令

目标

数据往往存在多种形态:对象,数组,对象数组。如果将对象的key和value分别取出来,如何取出数组中的每个元素,是开发中非常常见的操作。vue提供了:v-for指令,可以轻松完成这个事情。

操作数组

html部分

{{index}}:{{value}}

js部分 var app = new Vue({ el:"#app", data:{ title:"Hello world!", names:["zhangsan","lisi","wangwu"] } }) ;

操作对象

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6Xzi3SAV-1595410166846)(assets/1557910291171.png)]

# html 部分

{{key}}:{{value}}

js部分 // 第三步:定义vuejs对象,开始进行视图和数据的渲染 var app = new Vue({ el:"#app", data:{ title:"Hello world!", user:{id:1,username:"徐承飞老师",age:32} } }) ;

操作对象数组


<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Documenttitle>
head>
<body>


<div id="app">
    
    <ul v-for="user in userData">
        <li>id:{{user.id}}li>
        <li>name:{{user.name}}li>
        <li>age:{{user.age}}li>
    ul>
    <hr>
    <ul v-for="(user,index) in userData">
        <li>{{index + 1}}li>
        <li>id:{{user.id}}li>
        <li>name:{{user.name}}li>
        <li>age:{{user.age}}li>
    ul>
    <hr>
    {{friends[0]}}
    {{friends[1]}}
    {{friends[2]}}
    <hr>
    <p v-for="(f,index) in friends">{{f}}=={{friends[index]}}p>


div>

<script src="js/vue.min.js">script>
<script>
    // jsp-servlet---el表达式 +作用域 ${username} ${user.name} 这里的username和user是不必须定义在作用域
    // request.setAttribute session.setAttribute()
    //问题:mvvm是什么?它设计开发的设计理念,目的通过一些方式能够达到类似于mvc架构模式。完整将数据和视图进行分离。
    var vue = new Vue({//----------------------------------vm角色
        el: "#app",
        // 重点:未来所有的数据都要在这里进行定义和存放?mvc model(dao,pojo) view(jsp) controller(servlet)
        data: {//----------------------------model不就我们的作用域吗?
            username: "",
            age: "2",
            password: "3",
            friends:["A","B","C"],
            userData: [{
                id: "1",
                name: "zhangsan",
                age: 32
            }, {
                id: "2",
                name: "lisi",
                age: 32
            }]
        }
    })

script>


body>
html>

小结

索引的获取是定义 v-for=(user,index) in 对象、数组、数组对象都可以.

14 - Vue内置指令 - 条件指令 - v-if v-else-if v-else 指令

目标

掌握v-if/v-else和v-if/v-else-if/v-else标签的使用

需求

用户输入步同年龄阶段,显示这个阶段对应的时期。

代码

v-if/v-else-if/v-else例子


<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Documenttitle>
head>
<body>


<div id="app">
    <ul v-for="(user,index) in userData">
        <li>{{index + 1}}li>
        <li>id:{{user.id}}li>
        <li>name:{{user.name}}li>
        <li>age:{{user.age}}li>
        <li>性别:
            <span v-if="user.male==0">span>
            <span v-if="user.male==1">span>
            <span v-if="user.male==2">保密span>
            :
            <span v-if="user.male==0">span>
            <span v-else-if="user.male==1">span>
            <span v-else>保密span>
        li>
    ul>
div>

<script src="js/vue.min.js">script>
<script>
    // jsp-servlet---el表达式 +作用域 ${username} ${user.name} 这里的username和user是不必须定义在作用域
    // request.setAttribute session.setAttribute()
    //问题:mvvm是什么?它设计开发的设计理念,目的通过一些方式能够达到类似于mvc架构模式。完整将数据和视图进行分离。
    var vue = new Vue({//----------------------------------vm角色
        el: "#app",
        // 重点:未来所有的数据都要在这里进行定义和存放?mvc model(dao,pojo) view(jsp) controller(servlet)
        data: {//----------------------------model不就我们的作用域吗?
            userData: [{
                id: "1",
                male:2,
                name: "zhangsan",
                age: 32
            }, {
                id: "2",
                male:1,
                name: "lisi",
                age: 32
            },{
                id: "3",
                male:0,
                name: "zhangsan",
                age: 32
            }]
        }
    })

script>


body>
html>

小结

注意点,v-if/elseif/else 指令和指令之间加标签会造成断层,否则无效。如果仅仅是文本就忽略文本。正常执行。

15 - Vue内置指令 - 显示指令 -v-show 指令

目标

掌握和学习v-show的使用方式,以及v-show和v-if的区别

代码


<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Documenttitle>
head>
<body>


<div id="app">
    <div v-show="flag">v-show显示div>
    <div v-show="!flag">v-hidediv>
    <div v-if="flag">v-if显示div>
div>

<script src="js/vue.min.js">script>
<script>
    // jsp-servlet---el表达式 +作用域 ${username} ${user.name} 这里的username和user是不必须定义在作用域
    // request.setAttribute session.setAttribute()
    //问题:mvvm是什么?它设计开发的设计理念,目的通过一些方式能够达到类似于mvc架构模式。完整将数据和视图进行分离。
    var vue = new Vue({//----------------------------------vm角色
        el: "#app",
        // 重点:未来所有的数据都要在这里进行定义和存放?mvc model(dao,pojo) view(jsp) controller(servlet)
        data: {//----------------------------model不就我们的作用域吗?
            flag:true
        }
    })

script>


body>
html>

小结

v-if是根据表达式的值来决定是否渲染元素

v-show是根据表达式的值来切换元素的display css属性

==拓展:==16 - Vuejs -Computed 计算属性

使用vuejs计算属性完成

17 - Vuejs实操系列 - Vuejs实战应用开发 + 购物车管理

案例需求

完成用户的查询与修改操作,

步骤

1:新建springboot工程

2:添加相关依赖配置整合sm


<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-freemarkerartifactId>
dependency>


<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-webartifactId>
dependency>


<dependency>
    <groupId>org.projectlombokgroupId>
    <artifactId>lombokartifactId>
    <optional>trueoptional>
dependency>


<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-testartifactId>
    <scope>testscope>
dependency>


<dependency>
    <groupId>com.baomidougroupId>
    <artifactId>mybatis-plus-boot-starterartifactId>
    <version>3.3.0version>
dependency>


<dependency>
    <groupId>mysqlgroupId>
    <artifactId>mysql-connector-javaartifactId>
    <scope>runtimescope>
    <version>5.1.10version>
dependency>


<dependency>
    <groupId>com.alibabagroupId>
    <artifactId>druid-spring-boot-starterartifactId>
    <version>1.1.18version>
dependency>

定义一个pojo

3:整合mybatis-plus

package com.icoding.core;

import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;

//Spring boot方式
@EnableTransactionManagement
@Configuration
// 把mapper交给springioc容器管理和初始化
@MapperScan("com.icoding.mapper")
public class MybatisPlusConfig {

    @Bean
    public PaginationInterceptor paginationInterceptor() {
        PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
        // 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求  默认false
        // paginationInterceptor.setOverflow(false);
        // 设置最大单页限制数量,默认 500 条,-1 不受限制
        // paginationInterceptor.setLimit(500);
        return paginationInterceptor;
    }
}

3:编写一个mapper继承通用BaseMapper

package com.icoding.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.icoding.pojo.BuyCart;

/**
 * 
 * todo:购物车管理数据层
 * BuyCartMapper
* 创建人:David老师
* 时间:2019年12月25日 22:52:04
* @version 1.0.0
* */
public interface BuyCartMapper extends BaseMapper<BuyCart> { }

4:建立pojo通过主键@TableName和表建立关系

package com.icoding.pojo;

import java.util.Date;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
/**
*
* todo:购物车管理实体
* BuyCart
* 创建人:David老师
* 时间:2019年12月25日 22:52:04
* @version 1.0.0
* */
@Data @AllArgsConstructor @NoArgsConstructor @ToString @Builder @ApiModel("购物车管理") @TableName("im_buycart") public class BuyCart implements java.io.Serializable{ @ApiModelProperty("") @TableId(type = IdType.AUTO) private Integer id; // 登录用户id @ApiModelProperty("登录用户id") private String customerId; // 未登录cookie id private String buyId; // 登录状态0-未登录,1-登录 @ApiModelProperty("登录状态0-未登录,1-登录") private Integer loginStatus; // 产品ID @ApiModelProperty("产品ID") private String productId; // 产品唯一编码 @ApiModelProperty("产品唯一编码") private String spu; // 产品原价 @ApiModelProperty("产品原价") private Float originalPrice; // 售价 @ApiModelProperty("售价") private Float salePrice; // 购买数量 @ApiModelProperty("购买数量") private Integer saleQty; // 小计 @ApiModelProperty("小计") private Float saleTotalPrice; // 规格ID @ApiModelProperty("规格ID") private Integer variantsId; // 规格名称 @ApiModelProperty("规格名称") private String variantsTitle; // 规格的唯一编码 @ApiModelProperty("规格的唯一编码") private String sku; // 属性图片src路径 @ApiModelProperty("属性图片src路径") private String imageSrc; // 规格的重量 @ApiModelProperty("规格的重量") private Integer variantsWeight; // 产品链接 @ApiModelProperty("产品链接") private String productHandle; // 产品名称 @ApiModelProperty("产品名称") private String productTitle; // 分类ID @ApiModelProperty("分类ID") private String collectionId; // 添加时间 @ApiModelProperty("添加时间") private Date createTime; // 修改时间 @ApiModelProperty("修改时间") private Date updateTime; }

5:配置数据库信息

applicaiton-dev.properties

#druid
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/aicodingdb?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource

applicaiton.properties

server.port=8088
# springboot profile机制
spring.profiles.active=dev

6:编写测试用例,检验mapper是否能够执行查询数据库的操作

package com.icoding;

import com.icoding.mapper.BuyCartMapper;
import com.icoding.pojo.BuyCart;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class SpringbootIcodingTmallproApplicationTests {


    @Autowired
    private BuyCartMapper buyCartMapper;

    @Test
    void contextLoads() {

        BuyCart buyCart = buyCartMapper.selectById(1);
        System.out.println(buyCart);

    }

}

6:测试数据接口

package com.icoding;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.icoding.mapper.BuyCartMapper;
import com.icoding.pojo.BuyCart;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

@SpringBootTest
class SpringbootIcodingTmallproApplicationTests {


    @Autowired
    private BuyCartMapper buyCartMapper;

    @Test
    void contextLoads() {

        /*BuyCart buyCart = buyCartMapper.selectById(1);
        System.out.println(buyCart);*/

        //查询条件
        //QueryWrapper queryWrapper = new QueryWrapper<>();
       /* List buyCarts = buyCartMapper.selectList(null);
        for (BuyCart buyCart : buyCarts) {
            System.out.println(buyCart);
        }*/

        Page<BuyCart> page = new Page<>(2,10);
        //QueryWrapper queryWrapper = new QueryWrapper<>();
        IPage<BuyCart> buyCartIPage = buyCartMapper.selectPage(page,null);
        List<BuyCart> records   = buyCartIPage.getRecords();
        for (BuyCart buyCart : records) {
            System.out.println(buyCart);
        }
    }

}

7:使用vuejs完成列表查询和购物车查询

18 - Vuejs实操系列 - 掌握Vuejs中Axios完成异步请求-语法介绍

**目标:**掌握和学习异步处理组件axios.

概述

Vuejs 并没有直接处理ajax的组件,但可以使用axios或vue-resource组件实现对异步请求的操作。

vue-resource

vue-resource是Vue.js的插件提供了使用XMLHttpRequest或JSONP进行Web请求和处理响应的服务。 当vue更新
到2.0之后,作者就宣告不再对vue-resource更新,而是推荐axios。

vue-resource的github: https://github.com/pagekit/vue-resource

axios简介

Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中

new

axios的github:https://github.com/axios/axios

# 如果使用npm则可以如下安装
npm install axios
或者
npm i axios

或者也可以直接使用公共的CDN(内容分发网络)服务:


<script src="https://unpkg.com/axios/dist/axios.min.js">script>

6.3.1 方法说明

axios可以使用的方法有:

  • axios(config)
  • axios.get(url[, config]).
  • axios.delete(url[, config])
  • axios.head(url[, config])
  • axios.post(url[, data[, config]])
  • axios.put(url[, data[, config]])
  • axios.patch(url[, data[, config]])

config请求配置

这些是创建请求时可以用的配置选项。只有 url 是必需的。如果没有指定 method,请求将默认使用 get 方法。

{
  // `url` 是用于请求的服务器 URL
  url: '/user',

  // `method` 是创建请求时使用的方法
  method: 'get', // 默认是 get

  // `baseURL` 将自动加在 `url` 前面,除非 `url` 是一个绝对 URL。
  // 它可以通过设置一个 `baseURL` 便于为 axios 实例的方法传递相对 URL
  baseURL: 'https://some-domain.com/api/',

  // `transformRequest` 允许在向服务器发送前,修改请求数据
  // 只能用在 'PUT', 'POST' 和 'PATCH' 这几个请求方法
  // 后面数组中的函数必须返回一个字符串,或 ArrayBuffer,或 Stream
  transformRequest: [function (data) {
    // 对 data 进行任意转换处理

    return data;
  }],

  // `transformResponse` 在传递给 then/catch 前,允许修改响应数据
  transformResponse: [function (data) {
    // 对 data 进行任意转换处理

    return data;
  }],

  // `headers` 是即将被发送的自定义请求头
  headers: {
      'X-Requested-With': 'XMLHttpRequest',
      'Content-Type': 'application/json'
  },

  // `params` 是即将与请求一起发送的 URL 参数
  // 必须是一个无格式对象(plain object)或 URLSearchParams 对象
  params: {
    ID: 12345
  },

  // `data` 是作为请求主体被发送的数据
  // 只适用于这些请求方法 'PUT', 'POST', 和 'PATCH'
  // 在没有设置 `transformRequest` 时,必须是以下类型之一:
  // - string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams
  // - 浏览器专属:FormData, File, Blob
  // - Node 专属: Stream
  data: {
    firstName: 'Fred'
  },

  // `timeout` 指定请求超时的毫秒数(0 表示无超时时间)
  // 如果请求话费了超过 `timeout` 的时间,请求将被中断
  timeout: 1000,

  // `withCredentials` 表示跨域请求时是否需要使用凭证
  withCredentials: false, // 默认的

  // `responseType` 表示服务器响应的数据类型,可以是 'arraybuffer', 'blob', 'document', 'json', 'text', 'stream'
  responseType: 'json', // 默认的

  // `maxContentLength` 定义允许的响应内容的最大尺寸
  maxContentLength: 2000,

  // `validateStatus` 定义对于给定的HTTP 响应状态码是 resolve 或 reject  promise 。如果 `validateStatus` 返回 `true` (或者设置为 `null` 或 `undefined`),promise 将被 resolve; 否则,promise 将被 rejecte
  validateStatus: function (status) {
    return status >= 200 && status < 300; // 默认的
  },

  // `maxRedirects` 定义在 node.js 中 follow 的最大重定向数目
  // 如果设置为0,将不会 follow 任何重定向
  maxRedirects: 5 // 默认的

}

响应结构

{
  // `data` 由服务器提供的响应
  data: {},

  // `status` 来自服务器响应的 HTTP 状态码
  status: 200,

  // `statusText` 来自服务器响应的 HTTP 状态信息
  statusText: 'OK',

  // `headers` 服务器响应的头
  headers: {},

  // `config` 是为请求提供的配置信息
  config: {}
}

使用 then 时,你将接收下面这样的响应:

axios.get('/user/12345')
  .then(function(response) {
    console.log(response.data);
    console.log(response.status);
    console.log(response.statusText);
    console.log(response.headers);
    console.log(response.config);
  });

在使用 catch 时,或传递 rejection callback 作为 then 的第二个参数时,响应可以通过 error 对象可被使用。

axios方法示例

可以通过向 axios 传递相关配置来创建请求

axios(config)


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vuejs测试title>
    <script src="js/vue-2.6.10.js">script>
    <script src="js/axios.min.js">script>
head>
<body>
<div id="app">
    <ul>
        <li v-for="(user,index) in users" :key="index">
            {{index}}--{{user.name}}--{{user.age}}--{{user.gender}}
        li>
    ul>
div>
<script>
    var app = new Vue({
        el:"#app",
        data: {
            users:[]
        },
        created(){
            //加载数据
            axios({
                method:"get",
                url: "data.json"
            }).then((res)=>{
                console.log(res);
                //将获取数据设置到users属性
                this.users = res.data;
            }).catch(error=>{
                alert(error);
            });
        }
    });
script>

body>
html>

get方法示例

将上述示例中的axios操作部分修改为如下:

axios.get("data.json")
    .then( res => {
    console.log(res);
    //将获取数据设置到users属性
    this.users = res.data;
}).catch(error =>{
    console.log(error)
});

post方法示例

将示例中的axios操作部分修改为如下:

axios.post("data.json")
    .then( res => {
    console.log(res);
    //将获取数据设置到users属性
    this.users = res.data;
}).catch(error =>{
    console.log(error)
});
}

config请求配置

这些是创建请求时可以用的配置选项。只有 url 是必需的。如果没有指定 method,请求将默认使用 get 方法。

{
  // `url` 是用于请求的服务器 URL
  url: '/user',

  // `method` 是创建请求时使用的方法
  method: 'get', // 默认是 get

  // `baseURL` 将自动加在 `url` 前面,除非 `url` 是一个绝对 URL。
  // 它可以通过设置一个 `baseURL` 便于为 axios 实例的方法传递相对 URL
  baseURL: 'https://some-domain.com/api/',

  // `transformRequest` 允许在向服务器发送前,修改请求数据
  // 只能用在 'PUT', 'POST' 和 'PATCH' 这几个请求方法
  // 后面数组中的函数必须返回一个字符串,或 ArrayBuffer,或 Stream
  transformRequest: [function (data) {
    // 对 data 进行任意转换处理

    return data;
  }],

  // `transformResponse` 在传递给 then/catch 前,允许修改响应数据
  transformResponse: [function (data) {
    // 对 data 进行任意转换处理

    return data;
  }],

  // `headers` 是即将被发送的自定义请求头
  headers: {
      'X-Requested-With': 'XMLHttpRequest',
      'Content-Type': 'application/json'
  },

  // `params` 是即将与请求一起发送的 URL 参数
  // 必须是一个无格式对象(plain object)或 URLSearchParams 对象
  params: {
    ID: 12345
  },

  // `data` 是作为请求主体被发送的数据
  // 只适用于这些请求方法 'PUT', 'POST', 和 'PATCH'
  // 在没有设置 `transformRequest` 时,必须是以下类型之一:
  // - string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams
  // - 浏览器专属:FormData, File, Blob
  // - Node 专属: Stream
  data: {
    firstName: 'Fred'
  },

  // `timeout` 指定请求超时的毫秒数(0 表示无超时时间)
  // 如果请求话费了超过 `timeout` 的时间,请求将被中断
  timeout: 1000,

  // `withCredentials` 表示跨域请求时是否需要使用凭证
  withCredentials: false, // 默认的

  // `responseType` 表示服务器响应的数据类型,可以是 'arraybuffer', 'blob', 'document', 'json', 'text', 'stream'
  responseType: 'json', // 默认的

  // `maxContentLength` 定义允许的响应内容的最大尺寸
  maxContentLength: 2000,

  // `validateStatus` 定义对于给定的HTTP 响应状态码是 resolve 或 reject  promise 。如果 `validateStatus` 返回 `true` (或者设置为 `null` 或 `undefined`),promise 将被 resolve; 否则,promise 将被 rejecte
  validateStatus: function (status) {
    return status >= 200 && status < 300; // 默认的
  },

  // `maxRedirects` 定义在 node.js 中 follow 的最大重定向数目
  // 如果设置为0,将不会 follow 任何重定向
  maxRedirects: 5 // 默认的

}

响应结构

{
  // `data` 由服务器提供的响应
  data: {},

  // `status` 来自服务器响应的 HTTP 状态码
  status: 200,

  // `statusText` 来自服务器响应的 HTTP 状态信息
  statusText: 'OK',

  // `headers` 服务器响应的头
  headers: {},

  // `config` 是为请求提供的配置信息
  config: {}
}

19 -Vuejs实操系列 - 掌握Vuejs中Axios完成异步请求-参数获取

目标

实操axios调用后台数据,实现数据的CURD。

步骤

导入axios的js

 <script src="js/axios-0.18.0.js"></script>

get请求+传参 第一种方式

 axios.get("http://localhost:8080/vuessm-user/get?id="+id).then(function(response){
     console.log(response);
     if(response.status==200){
         that.$data.user = response.data;
         $("#myModal").modal("show");//让模态框弹出来
     }
 });

get请求+传参 第二种方式

var opid = 1;
axios.get("http://localhost:8080/vuessm-user/get/",{
                params:{
                    id:opid
                }
            }).then(function(response){
               console.log(response);
                if(response.status==200){
                    that.$data.user = response.data;
                    $("#myModal").modal("show");//让模态框弹出来
                }
           });

post请求+传参 第一种方式

axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'; 
或
headers:{'Content-Type':'application/x-www-form-urlencoded'}

注意后台springmvc必须设置:@RequestBody 才可以获取到值,并且只支持对象和Map

 axios.post(url,_this.user).then(function (res) {
     //成功之后直接刷新页面
     _this.findAll();
 }).catch(function (err) {
     console.log(err)
 });

后台代码

@PostMapping("save")
public String save(@RequestBody User user){}


@PostMapping("save")
public String save(@RequestBody Map map){}

post请求+传参 第二种方式

post请求后台参数是单个并且使用@RequestParam的时候使用如下

@PostMapping("save")
public String save(String username,String pwd){}

下面代码可以把参数注入到username和password中。

let param = new URLSearchParams()
param.append('username', 'admin')
param.append('pwd', 'admin')
axios.post('/api/lockServer/search',param);

axios.post('/api/lockServer/search',"userName='admin'&pwd='admin'");

参考文档:https://www.cnblogs.com/yiyi17/p/9409249.html

var person = {id:1,name:“zhangsan”};

person .id

person .name

person [“id”

]

第四部分:掌握和学习Vuejs组件开发

在大型应用开发的时候,页面可以划分成很多部分。往往不同的页面,也会有相同的部分。例如可能会有相同的头部导航。

但是如果每个页面都独自开发,这无疑增加了开发的成本。所以会把页面的不同部分拆分成独立的组件,然后在不同页面就可以共享这些组件,避免重复开发。

==拓展:==20 - Vuejs组件 - 定义全局组件

**目标:**掌握和学习vuejs组件的定义

步骤:

通过Vue的component方法来定义一个全局组件。


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vuejs测试title>
head>
<body>
<div id="app">
    
    <counter>counter>
div>
<script src="node_modules/vue/dist/vue.js">script>
<script>
    //定义组件
    const counter = {
        template: "",
        data(){
            return {num: 0}
        }
    };

    //全局注册组件;参数1:组件名称,参数2:组件
    Vue.component("counter", counter);

    var app = new Vue({
        el:"#app"
    });

script>

body>
html>
  • 组件其实也是一个Vue实例,因此它在定义时也会接收:data、methods、生命周期函数等
  • 不同的是组件不会与页面的元素绑定,否则就无法复用了,因此没有el属性。
  • 但是组件渲染需要html模板,所以增加了template属性,值就是HTML模板
  • 全局组件定义完毕,任何vue实例都可以直接在HTML中通过组件名称来使用组件了。
  • data的定义方式比较特殊,必须是一个函数。

效果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ayc6a9tI-1595410166848)(assets/component-01-1567580815767.gif)]

==拓展:==23 - Vuejs组件 - 组件的复用

**目标:**组件的调用和data数据的定义注意事项

操作

定义好的组件,可以任意复用多次:

<div id="app">
    
    <counter>counter>
    <counter>counter>
    <counter>counter>
div>

效果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mh42KBX8-1595410166848)(assets/1556534115827-1567580815767.png)]

你会发现每个组件互不干扰,都有自己的num值。怎么实现的?

组件的data属性必须是函数

当定义这个 组件时,它的data 并不是像这样直接提供一个对象:

data: {
  num: 0
}

取而代之的是,一个组件的 data 选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立的拷贝:

data: function () {
  return {
    num: 0
  }
}

如果 Vue 没有这条规则,点击一个按钮就会影响到其它所有实例!

==拓展:==24 - Vuejs组件 - 局部注册

目标

一旦全局注册,就意味着即便以后你不再使用这个组件,它依然会随着Vue的加载而加载。

因此,对于一些并不频繁使用的组件,会采用局部注册。

先在外部定义一个对象,结构与创建组件时传递的第二个参数一致:

然后在Vue中使用它:


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vuejs测试title>
head>
<body>
<div id="app">
    
    <counter>counter>
    <counter>counter>
    <counter>counter>
div>
<script src="node_modules/vue/dist/vue.js">script>
<script>
    //定义组件
    const counter = {
        template: "",
        data(){
            return {num: 0}
        }
    };

    //全局注册组件;参数1:组件名称,参数2:组件
    //Vue.component("counter", counter);

    var app = new Vue({
        el:"#app",
        //局部注册组件
        components:{
            counter: counter
        }
    });

script>

body>
html>
  • components就是当前vue对象子组件集合。
    • 其key就是子组件名称
    • 其值就是组件对象的属性
  • 效果与刚才的全局注册是类似的,不同的是,这个counter组件只能在当前的Vue实例中使用

==拓展:==25 - Vuejs组件 - 组件通信

目标: 使用vuejs完成父子组件间的通讯

通常一个单页应用会以一棵嵌套的组件树的形式来组织:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MKmOdjNY-1595410166849)(assets/1525855149491-1567580815767.png)] 

  • 页面首先分成了顶部导航、左侧内容区、右侧边栏三部分
  • 左侧内容区又分为上下两个组件
  • 右侧边栏中又包含了3个子组件

各个组件之间以嵌套的关系组合在一起,那么这个时候不可避免的会有组件间通信的需求。

** 父向子传递props**

比如有一个子组件:

Vue.component("introduce",{
    // 直接使用props接收到的属性来渲染页面
    template:'

{{title}}

'
, props:[title] // 通过props来接收一个父组件传递的属性 })
  • 这个子组件中要使用title属性渲染页面,但是自己并没有title属性
  • 通过props来接收父组件属性,名为title

父组件使用子组件,同时传递title属性:


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vuejs测试title>
head>
<body>
<div id="app">
    
    <introduce :title="msg">introduce>
div>
<script src="node_modules/vue/dist/vue.js">script>
<script>
    //定义组件
    const introduce = {
        //使用props属性title的值渲染模版
        template: "

{{title}}

"
, //定义接收来自父组件的属性 props:["title"] }; //全局注册组件;参数1:组件名称,参数2:组件 Vue.component("introduce", introduce); var app = new Vue({ el:"#app", data:{ msg: "父组件中的msg属性的内容" } });
script> body> html>

效果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0FhgJrj7-1595410166850)(assets/06-2-1567580815767.gif)]

传递复杂数据

定义一个子组件:

const myList = {
    template:'\
        
    \
  • {{item.id}} : {{item.name}}
  • \
\ '
, props:{ // 通过props来接收父组件传递来的属性 items:{// 这里定义items属性 type:Array,// 要求必须是Array类型 default:[] // 如果父组件没有传,那么给定默认值是[] } } }
  • 这个子组件可以对 items 进行迭代,并输出到页面。
  • 但是组件中并未定义items属性。
  • 通过props来定义需要从父组件中接收的属性
    • items:是要接收的属性名称
      • type:限定父组件传递来的必须是数组,否则报错
      • default:默认值

页面内容:


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vuejs测试title>
head>
<body>
<div id="app">
    <h2>艾编程开设的课程有:h2>
    
    <my-list :items="lessons">my-list>
div>
<script src="node_modules/vue/dist/vue.js">script>
<script>
    //定义组件
    const myList = {
        //可以使用双引号、单引号或者如下使用的 ` 飘号
        template: `
            
  • {{item.id}}--{{item.name}}
`
, //定义接收来自父组件的属性 props: { //定义模版中使用的属性 items: { //必须为数组类型 type: Array, //默认为空数组 default: [] } } }; var app = new Vue({ el: "#app", data: { msg: "父组件中的msg属性的内容", lessons:[ {"id":1, "name":"Java"}, {"id":2, "name":"PHP"}, {"id":3, "name":"前端"} ] }, //注册组件 components: { //如果组件key和value一致可以简写如下 myList } });
script> body> html>

子向父的通信

来看这样的一个案例:


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vuejs测试title>
head>
<body>
<div id="app">
    <h2>num = {{num}}h2>
    
    <counter :snum="num">counter>
div>
<script src="node_modules/vue/dist/vue.js">script>
<script>
    //定义组件
    const counter = {
        //组件只能是一个元素里面包裹其他元素;如下面,一个div包含两个按钮
        template: `
            
`
, props:["snum"] }; //全局注册组件;参数1:组件名称,参数2:组件 Vue.component("counter", counter); var app = new Vue({ el:"#app", data:{ num:0 } });
script> body> html>
  • 子组件接收父组件的num属性
  • 子组件定义点击按钮,点击后对num进行加或减操作

尝试运行,好像没问题,点击按钮试试:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iKb4uD56-1595410166851)(assets/1556547969267-1567580815767.png)]

子组件接收到父组件属性后,默认是不允许修改的。怎么办?

既然只有父组件能修改,那么加和减的操作一定是放在父组件:

    var app = new Vue({
        el:"#app",
        data:{
            num:0
        },
        methods:{
            //父组件中定义操作num的方法
            numPlus(){
                this.num++;
            },
            numReduce(){
                this.num--;
            }
        }
    });

但是,点击按钮是在子组件中,那就是说需要子组件来调用父组件的函数,怎么做?

可以通过v-on指令将父组件的函数绑定到子组件上:

<div id="app">
    <h2>num = {{num}}h2>
    
    <counter @plus="numPlus" @reduce="numReduce" :snum="num">counter>
div>

然后,当子组件中按钮被点击时,调用绑定的函数:

    //定义组件
    const counter = {
        //组件只能是一个元素里面包裹其他元素;如下面,一个div包含两个按钮
        template: `
            
`
, props:["snum"], methods: { //点击模板中使用的方法 incrNum(){ return this.$emit("plus"); }, decrNum(){ return this.$emit("reduce"); } } };

完成页面如下:


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vuejs测试title>
head>
<body>
<div id="app">
    <h2>num = {{num}}h2>
    
    <counter @plus="numPlus" @reduce="numReduce" :snum="num">counter>
div>
<script src="node_modules/vue/dist/vue.js">script>
<script>
    //定义组件
    const counter = {
        //组件只能是一个元素里面包裹其他元素;如下面,一个div包含两个按钮
        template: `
            
`
, props:["snum"], methods: { //点击模板中使用的方法 incrNum(){ return this.$emit("plus"); }, decrNum(){ return this.$emit("reduce"); } } }; //全局注册组件;参数1:组件名称,参数2:组件 Vue.component("counter", counter); var app = new Vue({ el:"#app", data:{ num:0 }, methods:{ //父组件中定义操作num的方法 numPlus(){ this.num++; }, numReduce(){ this.num--; } } });
script> body> html>
  • vue提供了一个内置的this.$emit函数,用来调用父组件绑定的函数

效果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eE3RXQM6-1595410166851)(assets/06-3-1567580815767.gif)]

子组件不能直接修改父组件传递参数的引用或者基本类型参数值。

==拓展:==26 - Vuejs - 过滤器 - Filter

目标

学习和掌握vuejs的过滤器的使用,实现案例人民币符号添加、和日期格式化.

过滤器案例一:人民币符号的前缀添加


<html>
	<head>
		<meta charset="utf-8" />
		<title>title>
	head>
	<body>
		<div id="app">
			{{title}}==={{totalPrice | money}}=={{addMoeny(totalPrice)}}
		div>
		<script src="js/vue.min.js">script>
		<script type="text/javascript">
			
			//自定义过滤器
			Vue.filter("money",function(value,prefix){
				return prefix||"¥" + value;
			});
			
			
			//实例化对象
			var vue = new Vue({
				el:"#app",
				data:{title:"你好"},
				// 计算属性
				computed:{
					totalPrice:function(){
						return 100;
					}
				},
				// 事件列表
				methods:{
					addMoeny:function(value,prefix){
						return prefix||"¥" + value;
					},
					parentClick:function(opid){
						console.log("parent click",opid);
					}
				},
				//入口函数
				created:function(){
					
				}
			});
			
		script>
	body>
html>

过滤器案例二:–日期格式化


<html>
	<head>
		<meta charset="UTF-8">
		<title>title>
	head>
	<body>
		
		<div id="app">
			{{date | dateFmt('yyyy-MM-dd hh:mm:ss')}}
		div>
		
		<script src="js/vue.min.js">script>
		<script>
			
			Date.prototype.format = function (format) {  
			    var args = {  
			        "M+": this.getMonth() + 1,  
			        "d+": this.getDate(),  
			        "h+": this.getHours(),  
			        "m+": this.getMinutes(),  
			        "s+": this.getSeconds(),  
			    };  
			    if (/(y+)/.test(format))  
			        format = format.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));  
			    for (var i in args) {  
			        var n = args[i];  
			        if (new RegExp("(" + i + ")").test(format))  
			            format = format.replace(RegExp.$1, RegExp.$1.length == 1 ? n : ("00" + n).substr(("" + n).length));  
			    }  
			    return format;  
			};  
			
			Vue.filter("dateFmt",function(value,fmt){
				return value.format(fmt || "yyyy-MM-dd");
			})
			
			var vue = new Vue({
				el:"#app",
				data:{
					date:new Date()
				}
			});
			
			
			
		script>
	body>
html>

er);

var app = new Vue({
    el:"#app",
    data:{
        num:0
    },
    methods:{
        //父组件中定义操作num的方法
        numPlus(){
            this.num++;
        },
        numReduce(){
            this.num--;
        }
    }
});
```
  • vue提供了一个内置的this.$emit函数,用来调用父组件绑定的函数

效果:

[外链图片转存中…(img-eE3RXQM6-1595410166851)]

子组件不能直接修改父组件传递参数的引用或者基本类型参数值。

==拓展:==26 - Vuejs - 过滤器 - Filter

目标

学习和掌握vuejs的过滤器的使用,实现案例人民币符号添加、和日期格式化.

过滤器案例一:人民币符号的前缀添加


<html>
	<head>
		<meta charset="utf-8" />
		<title>title>
	head>
	<body>
		<div id="app">
			{{title}}==={{totalPrice | money}}=={{addMoeny(totalPrice)}}
		div>
		<script src="js/vue.min.js">script>
		<script type="text/javascript">
			
			//自定义过滤器
			Vue.filter("money",function(value,prefix){
				return prefix||"¥" + value;
			});
			
			
			//实例化对象
			var vue = new Vue({
				el:"#app",
				data:{title:"你好"},
				// 计算属性
				computed:{
					totalPrice:function(){
						return 100;
					}
				},
				// 事件列表
				methods:{
					addMoeny:function(value,prefix){
						return prefix||"¥" + value;
					},
					parentClick:function(opid){
						console.log("parent click",opid);
					}
				},
				//入口函数
				created:function(){
					
				}
			});
			
		script>
	body>
html>

过滤器案例二:–日期格式化


<html>
	<head>
		<meta charset="UTF-8">
		<title>title>
	head>
	<body>
		
		<div id="app">
			{{date | dateFmt('yyyy-MM-dd hh:mm:ss')}}
		div>
		
		<script src="js/vue.min.js">script>
		<script>
			
			Date.prototype.format = function (format) {  
			    var args = {  
			        "M+": this.getMonth() + 1,  
			        "d+": this.getDate(),  
			        "h+": this.getHours(),  
			        "m+": this.getMinutes(),  
			        "s+": this.getSeconds(),  
			    };  
			    if (/(y+)/.test(format))  
			        format = format.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));  
			    for (var i in args) {  
			        var n = args[i];  
			        if (new RegExp("(" + i + ")").test(format))  
			            format = format.replace(RegExp.$1, RegExp.$1.length == 1 ? n : ("00" + n).substr(("" + n).length));  
			    }  
			    return format;  
			};  
			
			Vue.filter("dateFmt",function(value,fmt){
				return value.format(fmt || "yyyy-MM-dd");
			})
			
			var vue = new Vue({
				el:"#app",
				data:{
					date:new Date()
				}
			});
			
			
			
		script>
	body>
html>

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