Vue学习笔记-第二弹

101 阅读6分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第16天,点击查看活动详情

🍁 作者:知识浅谈,CSDN签约讲师,CSDN博客专家,华为云云享专家,阿里云专家博主
📌 擅长领域:全栈工程师、爬虫、ACM算法
💒 公众号:知识浅谈
🔥 联系方式vx:zsqtcc

🤞Vue学习笔记-第二弹🤞

5.v-show v-if v-bind

5.1 v-show

v-show:用来控制页面的某个元素是否展示 底层控制是标签display的属性

<div id="divapp">
    <span v-show="show">v-show 的测试,对应的值为false的时候就隐藏案例</span>
    <input type="button" value="展示按钮" @click="showedit"/>
</div>

<!--引入vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
    const app = new Vue({
        //如果使用类选择器,则  el:".类名"
        el:"#divapp", //el代表的是element元素用来给vue定义一个作用的范围 ,代表的是作用域页面中的哪一个元素
        data:{
            show:false,
        },//用来给vue定义一些简单的数据
        methods:{
            showedit(){
                this.show=true;
                this.show = !this.show;  //这样可以来回取反值
            },
        },
    });
</script>

v-show中使用boolean表达式控制标签的展示和隐藏

<div id="divapp">
    <h1 v-show="age>=23">年龄大于23的时候就显示出来</h1>
    <input type="button" value="年龄增加" @click="addage">
</div>
<!--引入vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
    const app = new Vue({
        //如果使用类选择器,则  el:".类名"
        el:"#divapp", //el代表的是element元素用来给vue定义一个作用的范围 ,代表的是作用域页面中的哪一个元素
        data:{
            age:20,
            show:false,
        },//用来给vue定义一些简单的数据
        methods:{
            addage(){
              this.age++;
            },
            showedit(){
                this.show=true;
                this.show = !this.show;  //这样可以来回取反值
            },
        },
    });
</script>
# 总结
	1.在使用v-show时可以直接书写 boolean值控制元素展示,也可以通过变量控制标签展示和隐藏
	2.在v-show中可以通过boo1ean表达式控制标签的展示和隐藏

知识点插入:关于html标签中有两个对页面元素显示操作的命令

隐藏元素 - display:none或visibility:hidden

隐藏一个元素可以通过把display属性设置为"none",或把visibility属性设置为"hidden"。但是请注意,这两种方法会产生不同的结果。

visibility:hidden可以隐藏某个元素,但隐藏的元素仍需占用与未隐藏之前一样的空间。也就是说,该元素虽然被隐藏了,但仍然会影响布局。

5.2 v-if

v-if: 用来控制页面元素是否展示 底层控制是DOM元素 操作DOM

用力控制页面中标签元素是否展示 底层和v-show不太一样,通过对dom树节点进行添加和删除来控制展示和隐藏的

<div id="divapp">
    <h1 v-if="show">v-if测试案例</h1>
</div>
<!--引入vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
    const app = new Vue({
        //如果使用类选择器,则  el:".类名"
        el:"#divapp", //el代表的是element元素用来给vue定义一个作用的范围 ,代表的是作用域页面中的哪一个元素
        data:{
            show:true,
        },//用来给vue定义一些简单的数据
    });
</script>

5.3 v-bind

v-bind:用来给标签绑定相应的属性

<head>
    <meta charset="UTF-8">
    <title>The First One Example</title>

    <style>
        .aa{
            border: 2px red solid;
        }
    </style>
</head>
<body>

<div id="divapp">
    <h1 v-if="show">v-if测试案例</h1>
    <img width="300" v-bind:title="msg" v-bind:class="show?css1:''" src="C:/Users/93676/Desktop/img-master/img/html%E9%A1%B5%E9%9D%A2%E7%BB%93%E6%9E%84.jpg" />
    <!--下边的i熬过和上边的一样-->
    <img width="300" v-bind:title="msg" v-bind:class="{aa:show}" v-bind:src="src" />
    <input type="button" value="动态控制样式" @click="addcss">
    <input type="button" value="改变图片" @click="changeimg">
</div>
<!--引入vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
    const app = new Vue({
        //如果使用类选择器,则  el:".类名"
        el:"#divapp", //el代表的是element元素用来给vue定义一个作用的范围 ,代表的是作用域页面中的哪一个元素
        data:{
            msg:"测试",
            show:true,
            css1:"aa",
            src:"C:/Users/93676/Desktop/img-master/img/html%E9%A1%B5%E9%9D%A2%E7%BB%93%E6%9E%84.jpg",
        },//用来给vue定义一些简单的数据
        methods:{   //动态的控制样式
            addcss(){
                this.show=!this.show;
            },
            changeimg(){
                this.src="https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=167741595,2706197548&fm=26&gp=0.jpg";
            },
        }
    });
</script>

5.4 v-bind简化写法

vue为了方便我们日后绑定标签所以由vue-bind: 变成了 :减少了代码量

<div id="divapp">
    <h1 v-if="show">v-if测试案例</h1>
    <img width="300" :title="msg" :class="show?css1:''" src="C:/Users/93676/Desktop/img-master/img/html%E9%A1%B5%E9%9D%A2%E7%BB%93%E6%9E%84.jpg" />
    <!--下边的i熬过和上边的一样-->
    <img width="300" :title="msg" :class="{aa:show}" :src="src" />
    <input type="button" value="动态控制样式" @click="addcss">
    <input type="button" value="改变图片" @click="changeimg">
</div>
上边代码由v-bind: 变成了:

6.v-for的使用

v-for:用来对对象进项遍历(数组也是对象的一中)

<div id="app">
<!--通过v-for便利-->
    <span v-for="u in user">
<!--        <span v-text="u"></span> <br>-->
        {{ u }}  <br> <!--或者使用插值表达式直接去除对应的值,而没有去除对应的key-->
    </span>
    <span v-for="(value,key,index) in user">
        {{ key }} : {{ value }}  <br>
    </span>

    <br>
    <ul>
        <li v-for="(u,index) in arr">
            {{ u }}  {{ index }}
        </li>
    </ul>
    <!--
        通过v-for遍历数组中对象
        :key  便于vue内部做重用和排序
    -->
    <ul>
        <li v-for="(user1,index) in users">
            {{ index+1 }}==={{ user1.name }}==={{ user1.age }}
        </li>
    </ul>

</div>
<!--引入vue 生产环境版本,优化了尺寸和速度 -->
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
    const app = new Vue({
        el: "#app",
        data: {
            user:{name:"cyl",age:23},
            arr:["aasd", "bzxc","cqwe"],
            users:[{name:"cyl",age:23},
                   {name:"cyl",age:23},],
        },
        methods: {}
    });
</script>
# 总结
	1.在使用v-for的时候一定要注意加如 :key 用来给内部提供重用和排序的唯一的key

7.v-model双向绑定

v-model:作用用来绑定标签元素的值与wue实例对象中data数据保持一致,从而实现双向的数据绑定机制。

<div id="app">

    <!--数据的双向绑定-->
    <input type="text" v-model="msg"/>
    {{ msg }}
    <hr>
    <input type="button" value="改变Data中的值" @click="change"/>


</div>
<!--引入vue 生产环境版本,优化了尺寸和速度 -->
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
    const app = new Vue({
        el: "#app",
        data: {
            msg:"asdasdasdas",
        },
        methods: {
            change(){
                this.msg="zxczxc";
            }
        },
    });
</script>
# 总结
	1.使用v-model指令可以是啊先数据的双向绑定
	2.所谓的双向绑定 表单中的数据变化导致vue中data数据的变化,vue实例中data数据的变化导致表单中数据的变化,称之为双向绑定。
	
#MVVM架构  双向绑定机制
Model:数据   vue实例中绑定的数据

VM: ViewModel   监听器(监听model和view的变化)

View:页面     页面展示的数据

8 记事本综合案例

<div id="app">
    <input type="text" v-model="msg" /> <input type="button" value="添加到记事本" @click="addcontent">
    <br>

    <!--:key  便于vue内部做重用和排序-->
    <ul>
        <li v-for="(u,index) in lists" :key="index">
            {{ index+1}}:{{ u }} <a href="javascript:;" @click="deleteOne(index)">删除</a>
        </li>
    </ul>
    总数量{{ lists.length }}条  <input type="button" value="删除所有" v-show="lists.length!=0" @click="deleteAll"/>

</div>
<!--引入vue 生产环境版本,优化了尺寸和速度 -->
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
    const app = new Vue({
        el: "#app",
        data: {
            msg:"",
            lists:["asd","zcx","qwe"], //用于存储记事的记录
        },
        methods: {
            addcontent(){
                // this.lists.push(this.msg);
                this.lists[this.lists.length]=this.msg;
                this.msg="";
            },
            deleteOne(index){
                //使用下边的这个方法能够自动更新view中的数组进行渲染
                this.lists.splice(index,1);  //这个表示的是从index这个下标开始删除,第二参数代表的是从这个位置开始删除几个
                // let len=this.lists.length;
                // for (let i=index+1;i<len;i++){ //这样不是删除只是把最后一个置为空,其他的向前覆盖一个而且还不会更新们需要在文本狂里边输入值的时候才重新渲染前台页面,这样写像是没有双向绑定
                //     this.lists[i-1]=this.lists[i];
                // }
                // this.lists[len-1]="";
            },
            deleteAll(){
                this.lists=[]; //直接赋值为空
            }
        }
    });
</script>

9.Vue中的事件修饰符

修饰符作用:用来和时间连用,用来决定事件的触发条件或者是组织事件的触发机制

# 1.常用的事件修饰符
	.stop
	.prevent
	.capture
	.self
	.once
	.passive

9.1 .stop事件修饰符

用来阻止事件冒泡,因为原本在元素嵌套的过程中,内层被触发之后,外层会接着被触发

<div id="app">
    <div class="aa" @click="divclick">
        <!--这个.stop的含义就是不再向上冒泡触发-->
        <input type="button" value="按钮" @click.stop="btnClick">
    </div>
</div>
<!--引入vue 生产环境版本,优化了尺寸和速度 -->
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
    const app = new Vue({
        el: "#app",
        data: {},
        methods: {
            btnClick(){
                alert("按钮被点击");
            },
            divclick(){
                alert('div被触发');
            }
        },
    });
</script>

9.2 prevent修饰符

用来阻止标签的默认行为

<!--用来阻止事件的默认行为-->
<a href="http://www.baidu.com/" @click.prevent="aclick">跳转</a>

9.3 self 事件修饰符

用来针对当前标签的事件的触发===》只触发自己标签上的事件 只关心自己标签上触发的事件,

<div class="aa" @click.self="divclick">
    <!--这个.stop的含义就是不再向上冒泡触发-->
    <input type="button" value="按钮" @click.stop="btnClick"> <br>
    <input type="button" value="按钮2" @click="btnClick1">
</div>

9.4 once事件修饰符

指定的事件只触发一次

<!--.prevent 用来阻止事件的默认行为-->
<!--.once表示对应的事件只执行一次,所以下边的事件是只阻止一次事件的默认行为,第二次点击就会跳转-->
<a href="http://www.baidu.com/" @click.prevent.once="aclick">跳转</a>

9.5 slot和slot-scope

slot也就是插槽,由于插槽是一块模板,所以,对于任何一个组件,从模板种类的角度来分,其实都可以分为非插槽模板插槽模板两大类。 非插槽模板指的是html模板,指的是‘div、span、ul、table’这些,非插槽模板的显示与隐藏以及怎样显示由插件自身控制;插槽模板是slot,它是一个空壳子,因为它显示与隐藏以及最后用什么样的html模板显示由父组件控制。但是插槽显示的位置确由子组件自身决定,slot写在组件template的哪块,父组件传过来的模板将来就显示在哪块

单个插槽|默认插槽 | 匿名插槽

首先是单个插槽,单个插槽是vue的官方叫法,但是其实也可以叫它默认插槽,或者与具名插槽相对,我们可以叫它匿名插槽。因为它不用设置name属性。

单个插槽可以放置在组件的任意位置,但是就像它的名字一样,一个组件中只能有一个该类插槽。相对应的,具名插槽就可以有很多个,只要名字(name属性)不同就可以了。

  • eg:

    父组件

    <template>
        <div class="father">
            <h3>这里是父组件</h3>
            <child>
                <div class="tmpl">
                  <span>菜单1</span>
                  <span>菜单2</span>
                  <span>菜单3</span>
                  <span>菜单4</span>
                  <span>菜单5</span>
                  <span>菜单6</span>
                </div>
            </child>
        </div>
    </template>
    

    子组件

    <template>
        <div class="child">
            <h3>这里是子组件</h3>
            <slot></slot>
        </div>
    </template>
    

    在这个例子里,因为父组件在里面写了html模板,那么子组件的匿名插槽这块模板就是下面这样。也就是说,子组件的匿名插槽被使用了,是被下面这块模板使用了。

    <div class="tmpl">
      <span>菜单1</span>
      <span>菜单2</span>
      <span>菜单3</span>
      <span>菜单4</span>
      <span>菜单5</span>
      <span>菜单6</span>
    </div>
    

    最终的渲染结果如图所示:

    image-20210328103522550

具名插槽

匿名插槽没有name属性,所以是匿名插槽,那么,插槽加了name属性,就变成了具名插槽。具名插槽可以在一个组件中出现N次。出现在不同的位置。下面的例子,就是一个有两个具名插槽单个插槽的组件,这三个插槽被父组件用同一套css样式显示了出来,不同的是内容上略有区别。

父组件:

<template>
  <div class="father">
    <h3>这里是父组件</h3>
    <child>
      <div class="tmpl" slot="up">
        <span>菜单1</span>
        <span>菜单2</span>
        <span>菜单3</span>
        <span>菜单4</span>
        <span>菜单5</span>
        <span>菜单6</span>
      </div>
      <div class="tmpl" slot="down">
        <span>菜单-1</span>
        <span>菜单-2</span>
        <span>菜单-3</span>
        <span>菜单-4</span>
        <span>菜单-5</span>
        <span>菜单-6</span>
      </div>
      <div class="tmpl">
        <span>菜单->1</span>
        <span>菜单->2</span>
        <span>菜单->3</span>
        <span>菜单->4</span>
        <span>菜单->5</span>
        <span>菜单->6</span>
      </div>
    </child>
  </div>
</template>

子组件:

<template>
  <div class="child">
    // 具名插槽
    <slot name="up"></slot>
    <h3>这里是子组件</h3>
    // 具名插槽
    <slot name="down"></slot>
    // 匿名插槽
    <slot></slot>
  </div>
</template>

显示结果如图:

image-20210328103713483

可以看到,父组件通过html模板上的slot属性关联具名插槽。没有slot属性的html模板默认关联匿名插槽。

作用域插槽 | 带数据的插槽

最后,就是我们的作用域插槽。这个稍微难理解一点。官方叫它作用域插槽,实际上,对比前面两种插槽,我们可以叫它带数据的插槽。什么意思呢,就是前面两种,都是在组件的template里面写

匿名插槽
<slot></slot>
具名插槽
<slot name="up"></slot>

但是作用域插槽要求,在slot上面绑定数据。也就是你得写成大概下面这个样子。

<slot name="up" :data="data"></slot>
 export default {
    data: function(){
      return {
        data: ['zhangsan','lisi','wanwu','zhaoliu','tianqi','xiaoba']
      }
    },
}

父组件:

<template>
  <div class="father">
    <h3>这里是父组件</h3>
    <!--第一次使用:用flex展示数据-->
    <child>
      <template slot-scope="user">
        <div class="tmpl">
          <span v-for="item in user.data">{{item}}</span>
        </div>
      </template>

    </child>

    <!--第二次使用:用列表展示数据-->
    <child>
      <template slot-scope="user">
        <ul>
          <li v-for="item in user.data">{{item}}</li>
        </ul>
      </template>

    </child>

    <!--第三次使用:直接显示数据-->
    <child>
      <template slot-scope="user">
       {{user.data}}
      </template>

    </child>

    <!--第四次使用:不使用其提供的数据, 作用域插槽退变成匿名插槽-->
    <child>
      我就是模板
    </child>
  </div>
</template>

子组件:

<template>
  <div class="child">

    <h3>这里是子组件</h3>
    // 作用域插槽
    <slot  :data="data"></slot>
  </div>
</template>

 export default {
    data: function(){
      return {
        data: ['zhangsan','lisi','wanwu','zhaoliu','tianqi','xiaoba']
      }
    }
}

结果如图所示:

image-20210328104512870