Vue2 基础语法

学习视频 bilibili 动力节点
老杜Vue视频教程,Vue2 Vue3实战精讲,一套通关vue【动力节点】

Vue2学习笔记

  • Vue程序初体验
  • 1 实例与容器只能是一对一的关系
  • 2 插值语法
  • 3 指令语法
    • 3.1 v-once 只渲染元素和组件一次
    • 3.2 条件渲染
      • 3.2.1 v-if 表达式的值决定标签是否渲染到浏览器
        • 3.2.1.1 template 标签使用v-if
      • 3.2.2 v-show 控制标签是否可见属性
      • 3.2.3 v-if和v-show该如何选择
      • 3.2.4 v-for 列表渲染
      • 3.2.5 列表过滤(使用计算属性)filter筛选 sort 排序 与 :key的作用
    • 3.3 v-bind 动态修改标签原有属性的值
    • 3.4 v-model 双向绑定表单value属性值
    • 3.5 v-on 事件绑定
      • 3.5.1 事件修饰符
      • 3.5.2 按键点击事件
      • 3.5.3 事件回调函数中的this
    • 3.6 v-text、v-html
    • 3.7 v-cloak、v-pre
  • 4 Vue实例可以访问哪些属性
    • 4.1 Vue的实例对象如何访问data对象中的值
      • 4.1.1 Object.defineProperty方法,给实例对象增加属性
      • 4.1.2 数据代理
  • 5 computed:计算属性
  • 6 watch:侦听属性
    • 6.1 深度监听
    • 6.2 深度监听方式的不同,获得的值不同
    • 6.2 后期添加监视
  • 7 Vue中的this
  • 8 class、style绑定
    • 8.1 class绑定
    • 8.2 style绑定
  • 9 创建表单数据
  • 10 directives:自定义指令
  • 11 组件的使用
    • 11.1 组件的嵌套
  • 12 $nextTick:页面渲染完成后执行
  • 13 js中的函数reduce

Vue程序初体验

  • 下载Vue.js文件
    并在页面中引入:<script src="../js/vue.js"></script>

  • VScode资源管理器 文件夹折叠
    第3步中对话框内容 Explorer:Compact Folders

在这里插入图片描述

  • 配置用户代码片段
    在这里插入图片描述
    找到要配置的语言在这里插入图片描述
	"Print to console": {       //提示信息
		"prefix": "log",        //缩写
		"body": [
			"console.log('$1');", //$1是光标停留的位置
			"$2"                  //$2是点击Tab键后光标会转移到这里
		], 
		"description": "Log output to console"   //描述信息,可以删除
	},
  • Vscode 更改默认字符编码
    在这里插入图片描述

  • 使用开发版本的Vue时,控制台会提示以下信息
    在这里插入图片描述
    关闭提示的方法:

    1. 可以通过设置 Vue.config中的productionTip来开启/阻止 vue 在启动时生成生产提示。Vue.config.productionTip = false
    2. 修改vue.js文件中的代码
      在这里插入图片描述
  • 控制台中提示安装DevTools
    在这里插入图片描述
    在Edge中安装DevTools,在扩展中搜索DevTools安装后设置,在允许访问文件URL前打勾在这里插入图片描述

  • DevTools作用:调试工具
    在这里插入图片描述

  • VsCode快捷键

1 实例与容器只能是一对一的关系

示例:

<body>
    <div class="app">
        第一个容器:{{name }}
    </div>
    <div class="app">
       第二个容器:{{name}}
    </div>
    <script>
        new Vue({
            el : '.app',
            data : {
                name : 'lili'
            }
        })
    </script>
</body>

上述代码to中class=app有两个{{name}}容器,对应同一个实例,运行结果显示只能对应第一个出现的实例
运行结果:第一个容器:lili 第二个容器:{{name}}

  • 反之仅有一个容器,而出现两个实例,则只对应第一个出现的实例

2 插值语法

  • 在{{表达式}}中,表达式可以写什么?
    <h1>1.data中声明的变量和函数</h1>
    <h1>{{msg}}</h1> 
    <h1>{{sayHello()}}</h1><br>
    
    <h1>2. 常量</h1>
    <h1>{{'字符串常量'}}</h1>
    <h1>{{10000}}</h1><br>
    
    <h1>3. 合法的JavaScript表达式</h1>
    <h1>{{1 + 1}}</h1>
    <h1>{{'msg' + '字符串'}}</h1>
    <h1>{{msg + '字符串'}}</h1>
    <h1>{{gender ? '男' : '女'}}</h1><br>
    
    <h1>4. 访问全局变量,例如:Math、Data</h1>
    <h1>{{Math.ceil(3.14)}}</h1>
    <h1>{{Date.now()}}</h1>
    

3 指令语法

  • 指令:让HTML标签的某个属性的值产生动态的效果

  • 指令语法:
    1. 以“v-”开始
    2. 指令写在标签的属性位置

  • 格式:<HTML标签 指令 : 参数 = ’表达式‘

    1. 不需要参数,不需要表达式。例如:v-once
    2. 需要参数,不需要表达式。例如:v-if=’表达式‘
    3. 需要参数,需要表达式。例如:v-bind:参数=’表达式‘
  • 表达式:和插值语法中{{表达式}}中的表达式是一样的

3.1 v-once 只渲染元素和组件一次

 <h1 v-once>{{msg}}</h1>

3.2 条件渲染

3.2.1 v-if 表达式的值决定标签是否渲染到浏览器

  • 当if条件判断为false时,该标签不会渲染到浏览器,并不是隐藏
<h1 v-if="a > b">{{ifmsg}}</h1>
  • 当v-if、v-else-if、v-else的标签是一个组合时,必须是紧挨在一起,两个标签中间不能有任何标签,否则会报错
    <div id="app">
        <div>{{bt}}</div>
        <button @click="bt++">点我</button><br>
        <!-- 当v-if、v-else-if、v-else的标签是一个组合时,必须是紧挨在一起,两个标签中间不能有任何标签,否则会报错 -->
        <span v-if="bt % 3 === 0">除以3余数为0</span>
        <span v-else-if = "bt % 3 ==1 ">除以3余数为1</span>
        <span v-else>除以3余数为2</span>
    </div>
    <script>
        const vm = new Vue({
            el : '#app',
            data : {
                bt : 0,
            }
        })
    </script>
3.2.1.1 template 标签使用v-if
  • 作用:避免了在多个标签中使用相同的条件语句,增加开销
  • 为什么要用它:
    template只是一个占位符,template标签本身不会被渲染到页面
<template v-if="bt % 5 == 0">
    <div>template只是一个占位符</div>
    <div>template不会被渲染到页面</div>
    <div>避免了在多个标签中使用相同的条件语句,增加开销</div>
</template>

3.2.2 v-show 控制标签是否可见属性

  • 使用:v-show = 'true' 或者v-show=’false‘
  • 作用:控制标签的属性display,当v-show=’false‘时,style="display: none“隐藏该标签;
    <div id="app">
        <span v-show="false">v-show条件渲染</span>
    </div>
    <script>
        const vm = new Vue({
            el : '#app',
        })

3.2.3 v-if和v-show该如何选择

如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if 较好。

3.2.4 v-for 列表渲染

  • v-for可遍历数组,对象,字符串,可指定遍历的次数
  • v-for 指令需要使用 item in items 形式的特殊语法,其中 items 是源数据数组,而 item 则是被迭代的数组元素的别名。
items : [
	item1,item2,item3
	]
  • 数据源是数组,第二个参数是下标,v-for=’(item,index)‘ in items
object:{
	key1 : value1,
	key2 : value2,
	}
  • 数据原是对象,第二个参数是key,第三个参数是下标index,v-for=’(value,key,index) in Object‘

  • 示例

    <div id="app">
        <!-- 以列表方式展示 -->
        <ul >
            <li>ID</li>
            <li>姓名</li>
            <li>年龄</li>
            <li>选择</li>
        </ul>
        <ul v-for="(vip,index) in vips">
            <li>{{index+1}}</li>
            <li>{{vip.name}}</li>
            <li>{{vip.age}}</li>
            <li><input type="checkbox"></li>
        </ul>

        <!-- 以表格方式展示 -->
        <table>
            <tr>
                <th>ID</th>    
                <th>姓名</th>
                <th>年龄</th>
                <th>选择</th>
            </tr>
            <tr v-for="(vip,index) in vips">
                <td>{{index+1}}</td>
                <td>{{vip.name}}</td>
                <td>{{vip.age}}</td>
                <td><input type="checkbox"></td>
            </tr>
        </table>

    </div>
    <script>
        const vm = new Vue({
            el : '#app',
            data : {
                vips : [
                    {
                        'id':'1',
                        'name':'jack',
                        'age':'20'
                    },
                    {
                        'id':'2',
                        'name':'lili',
                        'age':'30'
                    },
                    {
                        'id':'3',
                        'name':'mali',
                        'age':'40'
                    },
                ],
            }
        }) 
    </script>

3.2.5 列表过滤(使用计算属性)filter筛选 sort 排序 与 :key的作用

JS 数组中的 filter 方法
关于数组方法Array.prototype.filter()方法中 在回调函数体中是否需要使用return的超详细解析

  • :key的作用:当数据发生改变时,在内存中对两个相同的key来比较内容,如果不同则会更新有差异的dom中的内容,相同的内容则不更新,以减少开销
  • :key的值通常使用数据库中的主键。
  • indexOf():字符串.indexOf('字符')返回字符在字符串中的位置下标
    示例:"abdcddd".indexOf("")空字符在任何字符串中位置下标返回0
  • filter和箭头函数
    可遍历的对象.filter(对象中的元素 => 表达式)表达式为ture的元素会重新组合一个对象
  • 下面这个方法为什么要加return?使用filter筛选对象,需要表达式返回一个boolean结果,当箭头函数只有一条语句时,不需要加{},会自动返回表达式的计算结果,但是当有{}时,需要使用return来返回{}中表达式的计算结果
this.heros.filter(hero => {
	return hero.name.indexOf(this.keyWord)>=0)
}
  • sort()排序:可遍历的对象.sort((a,b) => a.要比较的数据部分 - b.要比较的数据部分)

    1. sort方法会改变原数据的结构
    2. a - b :升序
    3. b - a : 降序
  • 示例:

    <div id="app">
        <h1>输入要搜索的内容</h1>
        <input type="text" placeholder="请输入关键字" v-model="keyWord">
                <!-- placeholder属性:在对话框中显示指定内容 -->
        <input type="text" placeholder="输入搜索的关键字" v-model="keyWord">
        <h1>排序</h1>
        <!-- 可以在@click中直接对vue属性进行操作 -->
        <button @click="selectSort = 1">升序</button>
        <button @click="selectSort = 2">降序</button>
        <button @click="selectSort = 0">原序</button>
        <table >
            <tr>
                <th>ID</th>
                <th>姓名</th>
                <th>能量</th>
                <th>选项</th>
            </tr>
            <!-- :key属性的作用:当数据发生改变时,在内存中通过对比相同的key来比较内容,如果不同则会更新dom
                :key默认是数据的index,但是当插入的元素位于最上面是,会引起很大的开销,并且会出很大的错误(参考视频p44)
                所以通常使用数据库中的主键作为key的值
            -->
            <tr v-for="hero in newHeros" :key="hero.id">
                <td>{{hero.id}}</td>
                <td>{{hero.name}}</td>
                <td>{{hero.power}}</td>
                <td><input type="checkbox"></td>
            </tr>
        </table>
    </div>
    <script>
        const vm = new Vue({
            el : '#app',
            data : {
                keyWord : '',
                selectSort : 0,
                heros : [
                    {'id': '001','name':'达尔文','power':'10000'},
                    {'id': '002','name':'达文西','power':'12000'},
                    {'id': '003','name':'古尔丹','power':'11000'},
                    {'id': '004','name':'萨尔','power':'15000'},
                ],
            },
            computed : {
                newHeros (){                
                    let newHeros =  this.heros.filter(hero => hero.name.indexOf(this.keyWord) >= 0)                
                    if(this.selectSort === 1){
                        // 排序:可遍历的对象.sort((a,b) => a.要比较的数据部分 - b.要比较的数据部分)
                        // sort方法会改变原数据的结构
                        // a - b :升序  b - a : 降序
                        newHeros.sort((a,b)=>a.power - b.power)
                    }else if(this.selectSort === 2){
                        newHeros.sort((a,b)=>b.power - a.power)
                    }
                    return newHeros   
                    },      
            }        
        })
        
    </script>

3.3 v-bind 动态修改标签原有属性的值

<HTML标签 v-bind:参数 = '表达式'> 
  • 参数在大部分情况下是该标签支持的属性名
  • 重要:标签的冒号前后不能有空格
编译前:
    <HTML标签 v-bind:参数 = '表达式'> 
编译后:
    <HTML标签 属性=‘表达式的执行结果’>
例如:
    <a v-bind:href ='address'>网址链接</a>
编译后:
    <a href = "https://www.baidu.com">网址链接</a>
  • v-bind标签比较常用,可简化为:
    <a v-bind:href ='address'>网址链接</a>
    <a :href ='address'>网址链接</a>
    

3.4 v-model 双向绑定表单value属性值

  • 原型:
<input type="text" v-model:value="msg">
  • 只能用于获取<input><select><textarea>标签的value属性,所以可以省略value,简写为:
	<input type="text" v-model="msg">
  • 表单内容与组件双向绑定,当表单内容有变化时,v-model绑定的data中的属性的数据也会发生改变
  1. v-model.number修饰符number,可以让vue接收到的数据为数字,而不是字符串
  2. v-model.trim修饰符trim,去除字符串开始和结尾的空格
  3. v-model.lazy修饰符lazy,懒加载,用于文本域,作用:当焦点从文本域离开后,用户输入的文字vue才会接收到。如果不加lazy,则是用户输入一个字,vue就接收一个字

3.5 v-on 事件绑定

  • 重点:
    1. 鼠标点击,键盘等事件绑定缩写
    2. “事件”参数 的传递
<!-- 
    v-on:click 简写为 		@click
    v-on:keydown 简写为 		@keydown
    v-on:mouseover 简写为 	@mouseover
    						@wheel 鼠标滚轮滚动事件
 -->
<body>
    <div id="app">
        <!-- 1. js代码实现事件绑定 -->
        <button onclick="hello1()">hello1</button>
        <!-- 2. vue实现事件绑定 -->
        <button v-on:click="hello2()">hello2</button>
        <!-- 3. v-on可缩写为@,并且“()"也可以省略。 -->
        <button @click="hello3">hello3</button>
        <!-- 4. 默认会将点击事件作为参数传递到实例中,如果只传递“事件”这一个参数,则不能加() -->
        <button @click="hello4">hello4</button>
        <!-- 5.如果需要传递多个参数,使用$event占位符来传递“事件”这个参数, -->
        <button @click="hello5($event ,'jack')">hello5</button>
    </div>
    <script>
        function hello1(){
            console.log('hello1');
        } 

        const vm = new Vue({
            el : '#app',
            data : {
                msg : 'hello2',
            },
            methods : {
                hello2 : function(){
                    console.log('hello2');
                },
                // :function可不写
                hello3 (){
                    console.log('hello3');
                },
                hello4 (e){
                    console.log(e);
                },
                hello5 (e,name){
                    console.log(e , name);
                },
            }
        })
    </script>
</body>

3.5.1 事件修饰符

  • 事件修饰符的示例使用了下面的实例
        const vm = new Vue({
            el : '#app',
            data : {
                msg : '事件修饰符',
            },
            methods : {
                san (){
                    console.log('最外层div');  
                },
                er (){
                    console.log('中间的div');  
                },
                yi (){
                    console.log('里面的button');  
                },
                stopEvent(){
                    alert("阻止了a标签的默认行为(跳转到百度)")
                },
                testPssive(){
                    for(let i = 0;i < 100000; i ++){
                        console.log(this.msg);
                    }
                }
            }
  • 默认情况下,事件发生时以冒泡形式传递,冒泡是从最内层到最外层
        <div @click="san">
            <div @click="er">
                <button @click="yi">默认事件冒泡</button>
            </div>
        </div><br>
        <!-- 结果:
                    里面的button
                    中间的div
                    最外层div
        -->
  • .stop 停止事件冒泡,事件不再向后传递
        <div @click="san">
            <div @click.stop="er">
                <button @click="yi">停止事件冒泡</button>
            </div>
        </div><br>
        <!-- 
            结果:
                    里面的button
                    最外层div

         -->
  • .capture 事件捕获模式,捕获是从外层到内层
    <!-- 事件捕获模式,示例1 -->
        <div @click.capture="san">
            <div @click.capture="er">
                <button @click.capture="yi">事件捕获模式1</button>
            </div>
        </div><br>
        <!-- 
            结果:
                    最外层div
                    中间的div
                    里面的button
         -->
         
    <!-- 事件捕获模式,示例2,中间层先捕获了动作,然后是内层,冒泡到最外层 -->
        <div @click="san">
            <div @click.capture="er">
                <button @click="yi">事件捕获模式2</button>
            </div>
        </div><br>
        <!-- 
            结果:
                    中间的div                                        
                    里面的button
                    最外层div
         -->

    <!-- 事件捕获模式,示例3,最外层先捕获了动作,然后是中间层,最后轮到内层 -->
         <div @click.capture="san">
            <div @click.capture="er">
                <button @click="yi">事件捕获模式3</button>
            </div>
        </div><br>
        <!-- 
            结果:
                    最外层div
                    中间的div
                    里面的button
         -->


  • .self 如果是“我自己元素”上发生事件就执行对应的程序,如果是别的元素传递过来的则不执行
        <div @click="san">
            <div @click.self="er">
                <button @click="yi">.self只执行自己发生的事件</button>
            </div>
        </div><br>
        <!-- 
            结果:
                    里面的button
                    最外层div

         -->
  • .once 事件只执行一次
<!-- .once 事件只执行一次 -->
         <div @click="san">
            <div @click.once="er">
                <button @click="yi">.once事件只执行一次</button>
            </div>
        </div><br>
        <!-- 
            连续点击两次button按钮,结果:
                    里面的button
                    中间的div
                    最外层div
                    里面的button
                    最外层div
         -->
  • .prevent 阻止事件的默认行为发生
<!-- .prevent 阻止事件的默认行为 -->
        <a href="http://www.baidu.com" @click.prevent="stopEvent">prevent阻止事件的默认行为</a><br><br><br>
  • .passive 立即执行事件的默认行为 @wheel滚动事件
	    <style>
	        .divList{
	            width: 300px;
	            height: 200px;
	            background-color: aqua;
	            overflow: auto;
	        }
	        .item{
	            width: 300px;
	            height: 200px;
	        }
	    </style>
	    
	    // 滚动时运行的函数
         testPssive(){
            for(let i = 0;i < 100000; i ++){
                   console.log(this.msg);
            }
         }
         
         <div class="divList" @wheel.passive="testPssive">
            <div class="item">div1</div>
            <div class="item">div2</div>
            <div class="item">div3</div>
         </div>

         <!-- 结果:
                @wheel滚动事件触发后,在滚动鼠标滚轮时,会产生卡顿,控制台一直输出
                当@wheel带有事件修饰符.passive时,滚动鼠标滚轮图片会立即更新,无卡顿
        -->

3.5.2 按键点击事件

链接

知识点:
event.key触发事件的按键
event.target触发事件的标签
event.target.value如果触发事件的标签是input则返回input文本框中的内容
使用v-modle也能获取到input文本框中的内容

  1. 按键点击事件
    1.1 @keyup按键抬起时执行函数
    1.2 @keydown按键被按下时执行函数
    1.3 event.key 获得按键的值
    示例:
<label>输入:<input type="text" @keyup="getInfo" v-modle="value"></label>
methods : {
   getInfo(event){                 
   this.result = event.key
	}
}
  1. 按键修饰符
  • ctrl、alt、shift、meta组合键的使用方法
  • tab键只能在keydown事件触发
        <label>回车键:<input type="text" @keyup.enter="getInfo"></label><br>
        <label>回退键:<input type="text" @keyup.backspace ="getInfo"></label><br>
        <label>删除键:<input type="text" @keyup.delete="getInfo"></label><br>
        <!-- tab键只能触发keydown事件 -->
        <label>tab键:<input type="text" @keydown.tab="getInfo"></label><br>
        <!-- 四个特殊的按键
            ctrl、alt、shift、meta
            keydown事件:只要按下ctrl键,keydown事件就会触发
            keyup事件:按下ctrl键,同时按下其他组合键,松开组合键之后,keyup事件才能触发
        -->
        <label>ctrl与c的组合键keydown:<input type="text" @keydown.ctrl="getInfo"></label><br>  
        <label>ctrl与c的组合键keyup:<input type="text" @keyup.ctrl.c="getInfo"></label><br> 

3.5.3 事件回调函数中的this

  • 重点:
    1. vue实例的方法中使用的this指的就是vue实例的对象自己
    2. 方法如果使用的是箭头函数 ,this指向的时window
  • 示例
    <div id="app">
            <h1 >{{count}}</h1>
            <button @click="count++">不调用函数</button>
            <button @click="add">调用函数</button>
        </div>
        <script>
            const vm = new Vue({
                el : '#app',
                data : {
                    count : 0,
                },
                methods :{
                    add(){
                        this.count ++;
                        // this.$data.count ++;
                        // this._data.count ++;
                    }
                }
            })
        </script>
     // 结果
     两个按钮都能实现<h1>标签内的数字加1
    

3.6 v-text、v-html

  1. v-text等同于标签属性innerText
  2. v-html等同于标签属性innerHtml
  3. 两个标签都会覆盖标签内原有的内容
  • 示例:
        <div v-text="msg">原有的内容</div>
        <div v-html="msg">原有的内容</div>

		msg  : '<h1>新的内容</h1>'
<-- 结果:
<h1>新的内容</h1>
新的内容
-->

3.7 v-cloak、v-pre

  1. v-cloak:当vue.js文件或者vue实例没有加载完成前,页面会显示{{msg}},使用v-cloak指令后,在没有完成加载前页面上什么都不会显示
  2. v-pre:不涉及vue的内容,就不会经过vue的渲染,直接显示在页面上,节省开销
    <div id="app">
        <!-- 当vue.js文件或者vue实例没有加载完成前,页面会显示{{msg}},
            使用v-cloak指令后,在没有完成加载前页面上什么都不会显示 -->
        <div v-cloak>{{msg}}</div>

        <div v-pre>不涉及vue的内容,就不会经过vue的渲染,直接显示在页面上,节省开销</div>
    </div>
    <script>
        setTimeout(()=>{
            const vm = new Vue({
            el : '#app',
            data : {
                msg  : '延迟3秒加载',
            }
        })
        },3000)
    </script>

4 Vue实例可以访问哪些属性

在这里插入图片描述

  • 以$开头的属性,可以看作是公开的属性,是给程序员使用的
  • 以_开头的属性,可以看作是私有的属性,一般程序员很少用
  • 通过vue的实例对象也可以访问原型对象的属性
    在这里插入图片描述

4.1 Vue的实例对象如何访问data对象中的值

4.1.1 Object.defineProperty方法,给实例对象增加属性

  1. 作用:给某一个对象新增属性
 Object.defineProperty(实例对象,'给实例新增的属性名称', 
 {
 	value : '属性的值',
	wriitable :boolean //true:属性值可修改,false:不可修改
})
  1. 示例
	 <script>
        let person = {}
        Object.defineProperty(person,'name',{
            value : 'zhangsan',
            writable : true
        })
     </script>
// 结果
person.name
'zhangsan'
person.name = 'lisi'
'lisi'
person.name
'lisi'
  1. get与set方法

使用get和set方法时,不能使用配置属性value和writable

        let person = {}
        //临时变量    
        let temp
        Object.defineProperty(person,'name',{
            // value : 'zhangsan',
            // writable : true,

            
            get : function(){
                console.log('@@ get方法执行了 @@');
                return temp;
            },
            //set方法中val参数用来接收用户的赋值
            set :function(val){
                console.log('@@  set方法执行了 @@');
                temp= val;
            },
            //该属性是否可遍历(可枚举、可迭代),默认:false
            enumerable: true,
            //该属性是否可以被删除,默认:false
            configurable: true   
        })

在遍历person对象的属性时可以看到,在没有进行get或者set操作前,是无法获得到person对象的那么属性的
在这里插入图片描述
验证configurable配置项
在这里插入图片描述

4.1.2 数据代理

  • Vue为什么要做数据代理? 通过Vue的实例直接访问data中的数据

  • 通过代理对象proxy访问或修改目标对象target中的name属性

        //目标对象
        let target = {
            name : 'zhangsan'
        }
        //代理对象
        let proxy = {}
        //代理对象新增的属性名,必须与目标对象的属性名相同
        Object.defineProperty(proxy,'name',{
            get : function(){
                return target.name
            },
            set : function(val){
                target.name = val
            }      
        })
    //结果
    target.name
    'zhangsan'
    proxy.name
    'zhangsan'
    proxy.name = 'lisi'
    'lisi'
    target.name
    'lisi'
    

5 computed:计算属性

链接

  • 概念:基于现有的属性,计算出一个新的属性,依据属性的变化,自动更新。

  • 作用:减少重复计算,增加代码运行效率。
    如使用method中的方法来计算,当程序多次用到同一个方法的计算结果时,会调用多次方法。

  • 使用方法:配置computed,B属性名(){有关A属性的代码},在HTML中使用B属性

  • computed中属性的两种调用机制:

    1. 在第一次调用计算属性中的属性时
    2. 计算属性中关联的Vue中其他属性发生改变时
  • computed的属性的set方法很少用,有简写形式

  • computed中属性的简写形式很像methods中的方法,所以很容易和methods中的方法在调用的时候弄混,关键就是有没有括号

    1. computed中属性的使用方法:{{computed的属性名}}
    2. methods中的方法使用:{{methods的方法()}}
  • 示例:

      <div id="app">
          <label>输入字符串:<input type="text" v-model="info"></label><br>
          <label>反转字符串:{{reversal}}</label><br>
          <label>反转字符串:{{reversal}}</label><br>
          <label>反转字符串:{{reversal}}</label><br>
          <label>反转字符串:{{reversal}}</label><br>
          <label>反转字符串:{{reversal}}</label><br>
    
          <h1>computed简写形式</h1>
          <label>反转字符串:{{reversal_1}}</label><br>
          <label>反转字符串:{{reversal_1}}</label><br>
          <label>反转字符串:{{reversal_1}}</label><br>
          <label>反转字符串:{{reversal_1}}</label><br>
          <label>反转字符串:{{reversal_1}}</label><br>
      </div>
      <script>
          const vm = new Vue({
              el : '#app',
              data : {
                  info : 'abc',
              },
              computed : {
                  reversal: {
                      get(){
                          console.log('执行计算属性的get方法');                        
                          return this.info.split('').reverse().join('')
                      },
                      set(val){
                          console.log(val);
                          
                      }
                   },
                   // 计算属性的set方法很少用,计算属性的简写:
                  reversal_1(){
                      return this.info.split('').reverse().join('')
                  }
              },
          })        
      </script>
      //结果:
      在程序中5次调用reversal方法,但是只会在第1次运行reversal方法或者info属性值发生改变时调用reversal方法,其余4次都时从缓存中读取,提升了程序的运行效率
    

6 watch:侦听属性

链接

  • 作用: 某一个属性值变化后,可获得变化前后的值
  • 监听哪个属性,就将该属性名作为监听的属性名
  • handler的写法是固定的,里面两个参数,第一个参数是属性现在的值,第二个参数是属性原来的值
  • immediate的值默认是false,在第一次进入页面页面时,如果没有发生数据变化watch并不会立即监听只有发生数据改变,hander才会有操作,但是如果将immediate设置为true,在第一次进入页面时就会绑定值.
    <div id="app">
        <label>输入:<input type="text" v-model="num"></label><br>
    </div>
    <script>
        const vm = new Vue({
            el : '#app',
            data : {
                num : '',
            },
            watch : {
                // 监视哪个属性,就用属性名作为监视属性的名
                num : {
                    // immediate为true:第一次加载组件就开始监听,为false,加载完成后,以后有变化再监听
                    immediate : true,
                    // handler方法是固定写法,里面两个参数,第一个参数是属性现在的值,第二个参数是属性原来的值
                    handler(newValue, oldValue){
                        console.log('原来的值'+oldValue+'        '+'现在的值'+newValue);
                    }
                },
                
                // 如果没有设置项可以用简写形式
                num(newValue, oldValue){
                    console.log('原来的值'+oldValue+'        '+'现在的值'+newValue);
                }
            }
        })
    </script>

6.1 深度监听

  1. 深度监听:deep : true
  2. 使用深度监听时不能使用简写形式
    <div id="app">
        <label>深度监听:<input type="text" v-model="a.b.c"></label>
    </div>
    <script>
        const vm = new Vue({
            el : '#app',
            data : {
                a : {
                    b : {
                        c : ''
                    }
                },
            },
            watch : {
                // 监听最内层c,注意要加单引号
                'a.b.c'(){
                    // console.log('c的值有变化');
                },
                // 深度监听:不能使用简写形式
                a : {
                    deep : true,
                    handler(){                    
                        console.log('深度监听');
                    }                    
                }
            }
        })
    </script>

6.2 深度监听方式的不同,获得的值不同

下面是data中属性的结构

            data : {
                a : {
                    b : {
                        c : ''
                    }
                },
  1. 当使用下面这种配置deep时
        vm.$watch('a',{
            deep : true,
            handler (newA,oldA){
                console.log(oldA.b.c,newA.b.c);
            }
        })
        //结果:
        旧的c的值与新的c的值相同都为新c的值
        这是因为handler中的两个参数传递的都是a这个对象,而a中只有地址
  1. 当使用a.b.c来监听c的值时
        vm.$watch('a.b.c',{
            deep : true,
            handler (newC,oldC){
                console.log(oldC,newC);
            }
        })
        //结果
        旧c的值与新c的值不同
        handler中的两个参数就是c的新值和旧值

6.2 后期添加监视

语法:vm.$watch('监视属性的名',{ 配置项,handle(新值,旧值){执行语句}})

  • 示例见1.6.1的内容

7 Vue中的this

Vue中的this

8 class、style绑定

8.1 class绑定

  • 数组绑定是最常用的绑定方式,适用于名字不确定,数量也不确定的情况
  • 对象绑定适用于,名字和数量都确定,但不确实是否使用
  • 重要,所有class的属性名在vue中最好都加单引号
    <style>
        .static {
            width : 100px;
            height: 100px;
            border: 1px;
        }
        .active{
            background-color: aquamarine;
        }
        .text-danger{
            color: red;
        }
    </style>

    <div id="app">
        <div class="static active text-danger">{{msg}}</div><br>
        <!--  数组绑定是最常用的绑定方式,适用于名字不确定,数量也不确定的情况 -->
        <div class="static" :class="classArray">{{msg}}数组绑定</div><br>
        <!-- 对象绑定适用于,名字和数量都确定,但不确实是否使用 -->
        <div class="static" :class="classObj">{{msg}}对象绑定</div><br>
    </div>
    <script>
        const vm = new Vue({
            el : '#app',
            data : {
                msg : 'class绑定之',
                classArray : ['active', 'text-danger'],
                classObj : {
                    'active' : true,
                    'text-danger' : true,
                }
            }
        })
    </script>

8.2 style绑定

  • 注意vue中无论是数组还是对象形式,属性和值最好都加引号
    <style>
        .static{
            border: 1px solid black ;
            height: 100px;
            width: 100px;
        }
    </style>
</head>

<body>
    <div id="app">
         <!-- 静态写法 -->
        <div class="static" style="background-color: aquamarine;color: #000;">基本写法</div><br>
        <!-- 字符串形式 -->
        <div class="static" :style="styleString">style绑定字符串形式</div><br>
        <!-- 对象形式 ,无论是key还是value都需要加引号-->
        <div class="static" :style="styleObject">style绑定对象形式</div><br>
        <!-- 数组形式,数组中的style样式是以对象形式存在的 -->
        <div class="static" :style="styleArray">style绑定数组形式</div><br>
    </div>
    <script>
        const vm = new Vue({
            el : '#app',
            data : {
                msg : 'style绑定',
                styleString : 'background-color: aquamarine;color: #000;',
                styleObject : {
                    'background-color' : 'aquamarine',
                    'color' : '#000'
                },
                styleArray : [
                    {'background-color' : 'aquamarine'},
                    {'color' : '#000'}
                ]                               
            }
        })
    </script>

9 创建表单数据

知识点:

  1. v-model.number修饰符number,可以让vue接收到的数据为数字,而不是字符串

  2. v-model.trim修饰符trim,去除字符串开始和结尾的空格

  3. v-model.lazy修饰符lazy,懒加载,用于文本域,作用:当焦点从文本域离开后,用户输入的文字vue才会接收到。如果不加lazy,则是用户输入一个字,vue就接收一个字

  4. 阻止表单的提交:
    4.1第一种方法:<button @click.prevent="send">注册</button>阻止button点击的默认行为发生,调用vue中的相关方法
    4.2第二种方法:<form @submit.prevent="send">阻止表单的submit事件,执行vue中的相关方法

  5. JSON.stringify(this.user):将数据对象json化

<body>
    <div id="app">
        <!-- 阻止表单提交,第二种方法,阻止表单的submit事件,执行vue的send方法 -->
        <form @submit.prevent="send">
            <h1>{{msg}}</h1>
            <!-- `v-model.number`修饰符number,可以让vue接收到的数据为数字,而不是字符串 -->
            <label>用户名:<input type="text" v-model.trim="user.username"></label><br>
            <label>密码: <input type="password" v-model="user.password" /></label><br>
            <!--  `v-model.trim`修饰符trim,去除字符串开始和结尾的空格 -->
            <label>年龄:<input type="number" v-model.number="user.age"></label><br>
            <label>
                性别:<input type="radio" name="gender" value="1" v-model="user.gender"><input type="radio" name="gender" value="0"v-model="user.gender"></label><br>
            <label>爱好:
                <!-- checkbox作为复选框时,需指定每个选项的value值,v-model的结果是一个数组 -->
                <input type="checkbox"  value="travel"v-model="user.hobby">运动
                <input type="checkbox"  value="sport"v-model="user.hobby">旅游
                <input type="checkbox"  value="sing"v-model="user.hobby">唱歌
            </label><br>
            <label>
                学历:
                <select v-model="user.education">
                    <option value="">请选择学历</option>
                    <option value="zk">大专</option>
                    <option value="bk">本科</option>
                    <option value="ss">硕士</option>
                </select>
            </label><br><br>

            <label>简介:
                <textarea  cols="30" rows="10" v-model.lazy="user.introduce"></textarea>
            </label><br>

            <label></label>
                <!-- checkbox作为单选框时不需要指定value的值,选中则value为true,没有选中则value为false -->
                <input type="checkbox"  v-model="user.agreement">阅读并接收协议</label><br>
                <!-- 表单的提交:第一种方法,阻止button点击的默认行为发生,调用vue中的send方法 -->
            <!-- <label><button @click.prevent="send">注册</button></label><br> -->
            <label><button >注册</button></label><br>
        </form>
    </div>
    <script>
        const vm = new Vue({
            el : '#app',
            data : {
                msg : '收集表单数据',
                user : {
                    username : '',
                    password : '',
                    age : '',
                    gender : 1,
                    hobby : [],
                    education : '',
                    introduce : '',
                    agreement : '',
                },
            },
            methods :{
                    send(){
                        console.log(JSON.stringify(this.user));                        
                    }
                }
        })        
    </script>

10 directives:自定义指令

  1. 自定义指令分为全局指令和局部指令,定义时的代码位置不同。全局指令写在vue实例的外部
  2. 自定义指令可以使用函数式和对象式,两者区别在于函数式指令在dom与指令初次绑定时和模板重新解析时调用,共调用两次。对象式定义的指令在元素被渲染到页面后还会调用一次,一共3次。
  3. 函数式和对象式在什么情况下使用?函数式定义的指令针对操作dom自身属性时使用,对象式指令适用于操作dom的父、子、兄弟等其他节点时使用
  4. 自定义指令的参数:第一个参数ele就是dom本身,第二个参数binding(绑定关系),包含了几乎除dom外其他有关的所有数据,例如:指令名(v-bind-color),表达式(username),表达式的值(123),方法名('bind-color')等
  5. 自定义指令的this,都指向window
  6. 局部指令的配置项:directives,方法名就是标签内定义的名字,去了v-后,记得加括号。例如:标签内的属性名v-bind-color1那么方法名就是bind-color1
  7. 全局指令使用directive,没有s
    <div id="app">
        <!-- 分别由局部指令的函数式和对象式完成 -->
        <div>
            <div v-bind-color="username"></div>
        </div>
        <div>
            <input type="text" v-model-color="username">
        </div>
        <!-- 分别由全局指令的函数式和对象式完成 -->
        <div>
            <div v-bind-color1="username"></div>
        </div>
        <div>
            <input type="text" v-model-color1="username">
        </div>
    </div>
    <script>
         // 全局指令,函数式
        Vue.directive('bind-color1', function (ele, binding) {
            ele.innerText = binding.value;
            ele.style.color = 'red'
        })
       // 全局指令,对象式
        Vue.directive('model-color1', {
            // 当使用该指令时,将调用该函数
            bind(el, binding) {
                el.value = binding.value;
            },
            // 元素已经被插入页面后调用
            inserted(ele, binding) {
                ele.parentNode.style.backgroundColor = 'blue';
            },
            // 模板中心解析后,将调用该函数
            update(el, binding) {
                el.value = binding.value;
            }
        })
        const vm = new Vue({
            el: '#app',
            data: {
                username: "123",
            },
            directives: {
                // 函数式自定义指令,缺点:在代码执行阶段还没有渲染页面,所以无法找到除自己外的其他元素
                // 参数ele就是dom标签元素本身
                // 参数binding是绑定关系的一个对象,对象里面包含指令名(v-bind-color),表达式(username),表达式的值(123),方法名('bind-color')等
                'bind-color'(ele, binding) {
                    console.log(binding);
                    
                    ele.innerText = binding.value;
                    ele.style.color = 'red'
                },
                // 对象式自定义指令
                'model-color': {
                    // 当使用该指令时,将调用该函数
                    bind(el, binding) {
                        el.value = binding.value;
                    },
                    // 元素已经被插入页面后调用
                    inserted(ele, binding) {
                        ele.parentNode.style.backgroundColor = 'blue';
                    },
                    // 模板重新解析后,将调用该函数
                    update(el, binding) {
                        el.value = binding.value;
                    }
                }
            }
        });
    </script>

11 组件的使用

组件的使用分三步:

  1. 创建组件。重要提示:
    • template中只能包含一个根元素。如果有多个元素,使用v-if、v-else-if将他们连起来
    • data必须使用函数,不能使用对象的形式
const vc = Vew.extend({
   template : `
       //Html 部分
   `,
   data : function(){
       return {
           // 这里的内容与vue的data中内容相同
       }
   },
})
  1. 注册组件
    2.1 局部注册,在vue实例中增加配置项
components :{
          组件的名字 : vc
}
  2.2 全局注册`Vue.component("组件的名字",vc)`,示例:`Vue.component(vc,vc)`
  1. 使用组件

    在标签中引用<组件的名字></组件的名字>:<vc></vc>
    
<body>
    <div id="app">
        <login></login>
    </div>
    <script>

        const login = Vue.extend({
            template: `
            <div>
                <input type="text" v-model="username">
                <input type="password"v-model="password">
                <button @click="login">登录</button>
            </div>
            `,
            // data必须使用函数,不能使用对象的形式
            data: function(){
                return {
                    username: '',
                    password: ''
                }
            },
            methods: {
                login() {
                    console.log(this.username, this.password)
                }
            }
        })
        const vm = new Vue({
            el: '#app',

            components: {
                login: login
            }
        })

    </script>
</body>

11.1 组件的嵌套

使用组件时,一定将3个步骤落实到位,1.创建,2. 注册,3. 使用

<body>
    <div id="root"></div>
    <script>
// 使用组件的3个步骤,1.创建,2 注册,3 使用,一定要把这3个步骤落实
        const x1 = Vue.extend({
            template: '<div>x1组</div>',
        })

        const y1 = Vue.extend({
            template: '<div>y1组件</div>',
        })

        const x = Vue.extend({
            template: `
            <div>
                <div>x组件</div>
                <x1></x1>
            </div>
            `,
            components: {
                x1: x1
            }
        })


        const y = Vue.extend({
            template: `
            <div>
                <div>y组件</div>
                <y1></y1>
            </div>
            `,
            components: {
                y1: y1
            }
        })

        const app = Vue.extend({
            template: `
            <div>
                 <div>app组件</div>
                 <x></x>
                 <y></y>
            </div>
            `,
            components: {
                x: x,
                y: y
            }
        })

        const root = new Vue({
            el: '#root',
            template : `<app></app>`,
            components: {
                app
            }
        });
    </script>
</body>

结果:(浏览器的Vue Devtool插件的截图)
在这里插入图片描述

12 $nextTick:页面渲染完成后执行

链接
vue执行完渲染后会执行this.nextTick()里面的callback函数。

//           $nextTick:当代码执行完毕后,才开始执行函数中的代码

                this.$nextTick(function(){                    
                    this.$refs.inputInfo.focus()
                })

13 js中的函数reduce

链接
作用:参数a,从0开始计数,箭头函数的返回值就是a下一次的值;参数b是遍历list的对象

this.list.reduce((a, b) => a + (b : (a + 1) : 0), 0);
// this.list.reduce((a, b是list的遍历对象) => a + (b : (a + 1) : 0), a的起始值);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/125035.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

踩坑记录一

先呼自己两耳巴 临床采集的增强CT数据&#xff0c;有时候是同时采集了静脉期和动脉期。就会导致图像多一分如下&#xff1a; 但是勾画的时候&#xff0c;是以下面的期相进行标注的。所以在训练分割&#xff0c;对于这种案例&#xff0c;他识别到了在上面一个期相的目标位置&am…

利用Ansible实现批量Linux服务器安全配置

1.摘要 在上一篇<<初步利用Ansible实现批量服务器自动化管理>>文章中, 我初步实现了通过编写清单和剧本来实现多台服务器的自动化管理,在本章节中, 我将利用Ansible的剧本来实现更实用、更复杂一点的功能, 主要功能包括三个:1.同时在三台服务器中增加IP访问控制,只…

风力发电场集中监控系统解决方案

安科瑞 崔丽洁 作为清洁能源之一&#xff0c;风力发电场近几年装机容量快速增长。8月17日&#xff0c;国家能源局发布1-7月份全国电力工业统计数据。截至7月底&#xff0c;全国累计发电装机容量约27.4亿千瓦&#xff0c;同比增长11.5%。其中&#xff0c;太阳能发电装机容量约4.…

园区网真实详细配置大全案例

实现要求&#xff1a; 1、只允许行政部电脑对全网telnet管理 2、所有dhcp都在核心 3、wifi用户只能上外网&#xff0c;不能访问局域网其它电脑 4、所有交换机上开rstp协议&#xff0c;接入交换机上都开bpdu保护&#xff0c;核心lsw1设置为根桥 5、只允许vlan 10-40上网 5、所有…

2021年12月 Python(四级)真题解析#中国电子学会#全国青少年软件编程等级考试

Python等级考试(1~6级)全部真题・点这里 一、单选题(共25题,每题2分,共50分) 第1题 Python 中函数不包括? A:标准函数 B:第三库函数 C:内建函数 D:参数函数 答案:D 在 Python 中,并没有称为"参数函数"的函数类别。正确的说法是 A:标准函数、B:第…

从公共业务提取来看架构演进——功能设置篇

1.引言 上一篇文章我们以帐号权限的提取为例&#xff0c;介绍了当架构跟不上业务发展时及时调整架构的一种思路。这篇文章我们以功能设置为例&#xff0c;进一步讨论公共业务提取这个话题。 功能设置在本文中是指产品开放给企业和用户的一些功能设置项&#xff0c;以视频会议…

设计模式是测试模式咩?

设计模式和测试模式概述 软件的生命周期为什么要进行测试&#xff08;测试的目的&#xff09;&#xff1f;软件的设计模式1. **瀑布模型**3. 增量和迭代模型4. 敏捷模型5. 喷泉模型 测试模型V模型W模型 一个应用程序从出生到“死亡”会经过非常漫长的流程…… 软件的生命周期 …

剑指JUC原理-15.ThreadLocal

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是爱吃芝士的土豆倪&#xff0c;24届校招生Java选手&#xff0c;很高兴认识大家&#x1f4d5;系列专栏&#xff1a;Spring源码、JUC源码&#x1f525;如果感觉博主的文章还不错的话&#xff0c;请&#x1f44d;三连支持&…

XSS 跨站点脚本漏洞详解

文章目录 漏洞概述XSS漏洞原理xss漏洞危害xss漏洞验证XSS漏洞分类反射型存储型DOM型 固定会话攻击原理简单xss注入复现 XSS 攻防xss构造方法利用标签符号<>事件响应javascript伪协议其他标签 XSS 变形方式xss防御黑白名单策略输入过滤 案例XSS 盲打 漏洞概述 ​ 跨站点脚…

rancher或者其他容器平台使用非root用户启动jar

场景&#xff1a; java程序打成镜像&#xff0c;在rancher上运行&#xff0c;默认是root账户&#xff0c;发现hdfs或者hive不允许root账户操作&#xff1b;所以打算用费root账户启动jar&#xff0c;使其具有hive和hdfs的操作权限。 Dockerfile entrypoint.sh 思路就是上面这样…

【第2章 Node.js基础】2.3 Node.js事件机制

2.3 Node.js事件机制 学习目标 &#xff08;1&#xff09;理解Node.js的事件机制&#xff1b; &#xff08;2&#xff09;掌握事件的监听与触发的用法。 文章目录 2.3 Node.js事件机制什么是事件机制为什么要有事件机制事件循环事件的监听与触发EventEmitter类常用API 什么是…

面包屑实现

背景&#xff1a;面包屑根据菜单内容显示不同内容。首页永远存在&#xff0c;后面的活动管理及多级菜单的面包屑展示。 实现原理&#xff1a; 通过this.$route.matched获取所有匹配路由&#xff0c;将处理首页外的其他路由设置到一个数组中&#xff0c;再通过数组循环方式显示…

Qt国际化

刚开始听到这个名字我还觉得很高大上&#xff0c;最后发现这不就是系统语言选择吗&#xff0c;适应不同国家的人 先在widget.cpp写个要翻译的东西&#xff0c;我这里想做英语翻译成汉语、日语、泰语三种 #include "widget.h"Widget::Widget(QWidget *parent): QWidg…

0基础学习VR全景平台篇第119篇:利用蒙版航拍补天 - PS教程

上课&#xff01;全体起立~ 大家好&#xff0c;欢迎观看蛙色官方系列全景摄影课程&#xff01; 嗨&#xff0c;大家好。欢迎收看蛙色VR系列教程之PS利用蒙版航拍补天。 我们之前已经教过大家如何进行航拍调色&#xff0c;不知道大家学的怎么样呢&#xff1f; 会不会发现&…

壁炉艺术:美与温暖的交汇点

在我们的家中&#xff0c;有一种东西&#xff0c;既能提供温暖&#xff0c;又能为室内增添活力。壁炉不仅是取暖的好帮手&#xff0c;还能成为室内设计的亮点。 壁炉最初是为了取暖而生的&#xff0c;但如今&#xff0c;它们已经变成了室内设计的一部分。现代壁炉不再仅仅是灶…

【Qt之QAssociativeIterable】使用

介绍 QAssociativeIterable类是QVariant中一个关联式容器的可迭代接口。这个类允许多种访问在QVariant中保存的关联式容器元素的方法。如果一个QVariant可以转换为QVariantHash或QVariantMap&#xff0c;那么QAssociativeIterable的实例可以从中提取出来。 QHash<int, QSt…

centos的docker镜像下载ffmpeg的方式

ffmpeg是业界比较好用的开源的音频处理工具&#xff0c;当我们在实际业务中使用ffmpeg的时候&#xff0c;直接使用yum安装回提示找不到ffmpeg的包&#xff0c;遇到这种情况&#xff0c;可以通过以下方式来进行安装&#xff08;docker环境&#xff09;。 已经拥有镜像 更新源 …

【自动化测试】基于Selenium + Python的web自动化框架

一、什么是Selenium&#xff1f; Selenium是一个基于浏览器的自动化工具&#xff0c;她提供了一种跨平台、跨浏览器的端到端的web自动化解决方案。Selenium主要包括三部分&#xff1a;Selenium IDE、Selenium WebDriver 和Selenium Grid&#xff1a;  1、Selenium IDE&…

电脑如何设置不同网段的IP地址,实现访问不同IP的PLC或HMI设备?

电脑如何设置不同网段的IP地址,实现访问不同IP的PLC或HMI设备? 电脑如何设置不同网段的IP地址,实现访问不同IP的PLC或HMI设备? 这里以win10系统为例进行说明: 如下图所示,打开右下角的“网络和Internet设置”, 如下图所示,点击进入“更改适配器选项”, 如下图所示…

软件测试入门之接口测试

首先&#xff0c;什么是接口呢&#xff1f; 接口一般来说有两种&#xff0c;一种是程序内部的接口&#xff0c;一种是系统对外的接口。 系统对外的接口&#xff1a;比如你要从别的网站或服务器上获取资源或信息&#xff0c;别人肯定不会把数据库共享给你&#xff0c;他只能给你…