Vue2入门级基础学习笔记一

1. 什么是Vue

  1. Vue是一套用于构建用户界面渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用(简单应用只需一个小巧的核心库,复杂应用可以引入各式各样的Vue插件)。
  2. 特点
  • 采用组件化模式,提高代码复用率,且让代码更好维护。
  • 声明式编码,让编码人员无需直接操作DOM,提高开发效率
    在这里插入图片描述
  • 使用虚拟DOM+Diff算法,尽量复用DOM节点。
    在这里插入图片描述

2. Vue实例

  • 想让Vue工作,就必须创建一个Vue实例,且要传入一个配置对象
  • root容器里的代码依然符合html规范,只不过混入了一些特殊的Vue语法(插值语法);
  • root容器里的代码被称为“Vue模板“;
  • Vue实例和容器是一一对应的;
<!DOCTYPE html>
<html lang="en">

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

<body>
    <!-- 准备一个容器 -->
    <div id="root">
        <!-- 插值语法 -->
        <h1>hello,{{name}}</h1>
    </div>

    <script>
        Vue.config.productionTip = false; //设置为 false 以阻止 vue 在启动时生成生产提示。
        //创建Vue示例
        const x = new Vue({
            el: '#root', //建立关系,指定当前Vue实例为哪个容器服务,值通常为css选择器字符串
            data: { //data用于存储数据,数据供el所指定的容器使用,值我们暂时先写成一个对象
                name: 'joney'
            }
        })
    </script>
</body>

</html>

在这里插入图片描述

  • 真实开发中只有一个Vue实例,并且会配合着组件一起使用;
  • {{xxx}}中的xxx要写js表达式,且xxx可以自动读取到data中的所有属性;

注意区分:js表达式 和 js代码(语句)
1.表达式:一个表达式会产生一个值,可以放在任何一个需要值的地方:
(1). a
(2). a+b
(3). demo(1)
(4). x === y ? ‘a’ : ‘b’
2.js代码(语句)
(1). if(){}
(2). for(){}

  • 一旦data中的数据发生改变,那么页面中用到该数据的地方也会自动更新
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8" />
		<title>初识Vue</title>
		<!-- 引入Vue -->
		<script type="text/javascript" src="../js/vue.js"></script>
	</head>
	<body>
			<!-- 准备好一个容器 -->
		<div id="demo">
			<h1>Hello,{{name.toUpperCase()}},{{address}}</h1>
		</div>

		<script type="text/javascript" >
			Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。

			//创建Vue实例
			new Vue({
				el:'#demo', //el用于指定当前Vue实例为哪个容器服务,值通常为css选择器字符串。
				data:{ //data中用于存储数据,数据供el所指定的容器去使用,值我们暂时先写成一个对象。
					name:'atguigu',
					address:'北京'
				}
			})

		</script>
	</body>
</html>

在这里插入图片描述

3. 模板语法

插值语法(双大括号表达式)

功能:用于解析标签体内容
写法{{xxx}},xxx是js表达式,且可以直接读取到data中的所有属性。

指令语法(以 v-开头)

功能:用于解析标签(包括:标签属性、标签体内容、绑定事件…)。
举例v-bind:href="xxx"或 简写为 :href="xxx",xxx同样要写js表达式,且可以直接读取到data中的所有属性。
备注:Vue中有很多的指令,且形式都是:v-????,此处我们只是拿v-bind举个例子。

代码

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8" />
    <title>模板语法</title>
    <!-- 引入Vue -->
    <script type="text/javascript" src="../js/vue.js"></script>
</head>

<body>
    <!-- 准备好一个容器-->
    <div id="root">
        <h1>插值语法</h1>
        <h3>你好,{{name}}</h3>
        <hr/>
        <h1>指令语法</h1>
        <a v-bind:href="school.url.toUpperCase()" x="hello">点我去{{school.name}}学习1</a>
        <a :href="school.url" x="hello">点我去{{school.name}}学习2</a>
    </div>
</body>

<script type="text/javascript">
    Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。

    new Vue({
        el: '#root',
        data: {
            name: 'jack',
            school: {
                name: '湖南大学',
                url: 'https://www.baidu.com/',
            }
        }
    })
</script>

</html>

在这里插入图片描述

4. 数据绑定

单向数据绑定

语法:v-bind:href =“xxx” 或简写为 :href 2.

特点数据只能从 data 流向页面

双向数据绑定

语法:v-mode:value=“xxx” 或简写为 v-model="xxx",因为v-model默认收集的就是value值。

使用:双向绑定一般都应用在表单类元素上(如:input、select等有value值的标签)

特点数据不仅能从 data 流向页面,还能从页面流向 data

代码

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

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

<body>
    <!-- 准备一个容器 -->
    <div id="root">
        <!-- 普通写法 -->
			<!-- 单向数据绑定:<input type="text" v-bind:value="name"><br/>
			双向数据绑定:<input type="text" v-model:value="name"><br/> -->

			<!-- 简写 -->
			单向数据绑定:<input type="text" :value="name"><br/>
			双向数据绑定:<input type="text" v-model="name"><br/>

			<!-- 如下代码是错误的,因为v-model只能应用在表单类元素(输入类元素)上 -->
			<!-- <h2 v-model:x="name">你好啊</h2> -->
    </div>
    <script>
        Vue.config.productionTip = false; //设置为 false 以阻止 vue 在启动时生成生产提示。
        //创建Vue示例
        new Vue({
            el: '#root', //建立关系,指定当前Vue实例为哪个容器服务,值通常为css选择器字符串
            data: { //data用于存储数据,数据供el所指定的容器使用,值我们暂时先写成一个对象
                name: 'joney'
            }
        })
    </script>
</body>

</html>

在这里插入图片描述

5. data与el的2种写法

data

(1).对象式

new Vue({
el:'#root',
//data的第一种写法:对象式
data:{
	name:'joney'
}

(2).函数式

new Vue({
	el:'#root',
	//data的第二种写法:函数式
	data(){
		console.log('@@@',this) //此处的this是Vue实例对象
		return{
			name:'joney'
		}
	}
})

注意

  • 以后学习到组件时,data必须使用函数式,否则会报错。
  • 由Vue管理的函数,一定不要写箭头函数,一旦写了箭头函数,this就不再是Vue实例了。

el

(1). new Vue时候配置el属性

new Vue({
 el:'#root', //第一种写法
 data:{
		name:'尚硅谷'
	}
})

(2). 先创建Vue实例,随后再通过vm.$mount('#root')指定el的值。

const v = new Vue({
	//el:'#root', //第一种写法
	data:{
		name:'尚硅谷'
  }
})
console.log(v) // Vue对象实例
v.$mount('#root') //第二种写法

6. MVVM 模型

  • M:模型(Model) :对应 data 中的数据
  • V:视图(View) :模板
  • VM:视图模型(ViewModel) : Vue 实例对象
    在这里插入图片描述
    在这里插入图片描述

console.log(vm);输出Vue对象实例,发现data中所有的属性,最后都出现在了vm身上
在这里插入图片描述
总结:vm身上所有的属性 及 Vue原型上所有属性,在Vue模板中都可以直接使用。

<div id="root">
        <!-- 插值语法 -->
        <h1>hello,{{name}}</h1>
        <h1>去{{address}}上学</h1>
        <h1>测试一下1:{{1+1}}</h1>
        <!-- Vue身上的属性$options -->
        <h1>测试一下2:{{$options}}</h1>
        <!-- Vue原型身上的属性$emit -->
        <h1>测试一下3:{{$emit}}</h1>
        <!-- Vue身上的不带$的属性_c -->
        <h1>测试一下4:{{_c}}</h1>
    </div>

在这里插入图片描述

7. 数据代理

Object.defineProperty

obj:需要定义属性的对象
prop:需要定义的属性
descriptor:属性的描述描述符

Object.defineProperty(obj, prop, descriptor)

代码:

 let person = {
     name: '张三',
     sex: '男',
 }

 Object.defineProperty(person, 'age', {
     value: 18,
     enumerable: true, //控制属性是否可以枚举(遍历),默认值是false
     writable: true, //控制属性是否可以被修改,默认值是false
     configurable: true //控制属性是否可以被删除,默认值是false
 })
 console.log(person)
 //console.log(Object.keys(person))  遍历对象

在这里插入图片描述
Object.defineProperty将变量numberage绑定在一起

 <script type="text/javascript">
        let number = 18
        let person = {
            name: '张三',
            sex: '男',
        }

        Object.defineProperty(person, 'age', {
            // value:18,
            // enumerable:true, //控制属性是否可以枚举,默认值是false
            // writable:true, //控制属性是否可以被修改,默认值是false
            // configurable:true //控制属性是否可以被删除,默认值是false

            //当有人读取person的age属性时,get函数(getter)就会被调用,且返回值就是age的值
            get() {
                console.log('有人读取age属性了')
                return number
            },

            //当有人修改person的age属性时,set函数(setter)就会被调用,且会收到修改的具体值
            set(value) {
                console.log('有人修改了age属性,且值是', value)
                number = value
            }

        })
        console.log(person)
    </script>

在这里插入图片描述

数据代理

数据代理:通过一个对象代理对另一个对象属性的操作**(读/写)**

<script type="text/javascript" >
	let obj = {x:100}
	let obj2 = {y:200}

	Object.defineProperty(obj2,'x',{
		get(){
			return obj.x
		},
		set(value){
			obj.x = value
		}
	})
</script>

在这里插入图片描述

Vue中的数据代理

Vue中的数据代理:通过vm对象来代理data对象属性的操作(读/写)

Vue中数据代理的好处:更加方便的操作data中的数据

基本原理

  • 通过Object.defineProperty()把data对象中所有属性添加到vm上
  • 为每一个添加到vm上的属性都指定一个getter/setter
  • 在getter/setter内部去操作(读/写)data中对应的属性
    在这里插入图片描述
    在这里插入图片描述

8. 事件处理

基本使用

1.使用v-on:xxx@xxx 绑定事件,其中xxx是事件名;

<!--两种写法相同-->
<!--这里的showInfo可加()也可以不加-->
<button v-on:click="showInfo">点我提示信息</button>
<button @click="showInfo">点我提示信息</button>

<!-- 绑定事件的时候:@xxx="yyy" yyy可以写一些简单的语句,而不是函数-->
<button @click="isHot = !isHot">切换天气</button>

2.事件的回调需要配置在methods对象中,最终会在vm上

new Vue({
     el: '#root',
     data: {
         name: 'joney'
     },
     methods: {
         showInfo() {
             alert('同学你好')
         }
     }
 })

注意:如果想调用函数(不以回调的形式),则按如下形式进行调用,一定要写括号

<span>{{showInfo()}}</span>

3.methods中配置的函数,不要用箭头函数!否则this就不是vm,而是window

4.methods中配置的函数,都是被Vue所管理的函数,this的指向是vm 或 组件实例对象

5.@click="demo"@click="demo($event)"效果一致,但后者可以传参;

<button @click="showInfo1">点我提示信息1(不传参)</button>
<button @click="showInfo2($event,66)">点我提示信息2(传参)</button>

<script>
    Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。

    const vm = new Vue({
        el: '#root',
        data: {
            name: 'joney',
        },
        methods: {
            showInfo1(event) {
                console.log(event.target) // <button>点我提示信息1(不传参)</button>
                alert('同学你好!')
            },
            showInfo2(event, number) {
                console.log(event, number) // PointerEvent,66
                alert('同学你好!!')
            }
        }
    })
</script>

事件修饰符

  • prevent阻止默认事件(常用);
  • stop阻止事件冒泡(常用);
  • once事件只触发一次(常用);
  • capture:使用事件的捕获模式;
  • self:只有event.target是当前操作的元素时才触发事件;
  • passive:事件的默认行为立即执行,无需等待事件回调执行完毕;
<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8" />
    <title>事件修饰符</title>
    <!-- 引入Vue -->
    <script type="text/javascript" src="../js/vue.js"></script>
    <style>
        * {
            margin-top: 20px;
        }
        
        .demo1 {
            height: 50px;
            background-color: skyblue;
        }
        
        .box1 {
            padding: 5px;
            background-color: skyblue;
        }
        
        .box2 {
            padding: 5px;
            background-color: orange;
        }
        
        .list {
            width: 200px;
            height: 200px;
            background-color: peru;
            overflow: auto;
        }
        
        li {
            height: 100px;
        }
    </style>
</head>

<body>
    <!-- 准备好一个容器-->
    <div id="root">
        <h2>欢迎来到{{name}}学习</h2>
        <!-- 阻止默认事件(常用) -->
        <a href="https://www.csdn.net/" @click.prevent="showInfo">点我提示信息</a>

        <!-- 阻止事件冒泡(常用) -->
        <div class="demo1" @click="showInfo">
            <button @click.stop="showInfo">点我提示信息</button>
            <!-- 修饰符可以连续写 -->
            <!-- <a href="https://www.csdn.net/" @click.prevent.stop="showInfo">点我提示信息</a> -->
        </div>

        <!-- 事件只触发一次(常用) -->
        <button @click.once="showInfo">点我提示信息</button>

        <!-- 使用事件的捕获模式 -->
        <div class="box1" @click.capture="showMsg(1)">
            div1
            <div class="box2" @click="showMsg(2)">
                div2
            </div>
        </div>

        <!-- 只有event.target是当前操作的元素时才触发事件; -->
        <div class="demo1" @click.self="showInfo">
            <button @click="showInfo">点我提示信息</button>
        </div>

        <!-- 事件的默认行为立即执行,无需等待事件回调执行完毕; -->
        <ul @wheel.passive="demo" class="list">
            <li>1</li>
            <li>2</li>
            <li>3</li>
            <li>4</li>
        </ul>

    </div>
</body>

<script type="text/javascript">
    Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。

    new Vue({
        el: '#root',
        data: {
            name: '这里'
        },
        methods: {
            showInfo(e) {
                alert('同学你好!')
              // console.log(e.target)
            },
            showMsg(msg) {
                console.log(msg)
            },
            demo() {
                for (let i = 0; i < 100000; i++) {
                    console.log('#')
                }
                console.log('累坏了')
            }
        }
    })
</script>

</html>

键盘事件

1.Vue中常用的按键别名:

  • 回车 => enter
  • 删除 => delete (捕获“删除”和“退格”键)
  • 退出 => esc
  • 空格 => space
  • 换行 => tab (特殊,必须配合keydown去使用)
  • 上 => up
  • 下 => down
  • 左 => left
  • 右 => right

示例:

<body>
    <!-- 准备好一个容器-->
    <div id="root">
        <input type="text" placeholder="按下回车提示输入" @keyup.enter="showInfo">
    </div>
</body>

<script type="text/javascript">
    Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。

    new Vue({
        el: '#root',
        methods: {
            showInfo(e) {
                // console.log(e.key,e.keyCode)
                console.log(e.target.value)
            }
        },
    })
</script>

在这里插入图片描述

2.Vue未提供别名的按键,可以使用按键原始的key值去绑定但注意要转为kebab-case(短横线命名)

比如 console.log(e.key,e.keyCode)获取CapsLock 20CapsLock需要转化为caps-lock

<body>
    <!-- 准备好一个容器-->
    <div id="root">
        <input type="text" placeholder="按下回车提示输入" @keyup.caps-lock="showInfo">
    </div>
</body>

<script type="text/javascript">
    Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。

    new Vue({
        el: '#root',
        methods: {
            showInfo(e) {
                // console.log(e.key, e.keyCode)
                console.log(e.target.value)
            }
        },
    })
</script>

3.系统修饰键(用法特殊):ctrl、alt、shift、meta

  • 配合keyup使用:按下修饰键的同时,再按下其他键,随后释放其他键,事件才被触发
  • 配合keydown使用:正常触发事件。
 <!-- ctrl+任何键都可以触发 -->
 <input type="text" placeholder="按下回车提示输入" @keyup.ctrl="showInfo">
 <!-- ctrl+y才可以触发 -->
 <input type="text" placeholder="按下回车提示输入" @keyup.ctrl.y="showInfo">

注意实际中推荐和tab一样使用keydown

4.也可以使用keyCode去指定具体的按键。但是不推荐,因为该特性已经从 Web 标准中删除,虽然一些浏览器目前仍然支持它,但也许会在未来的某个时间停止支持。

<input type="text" placeholder="按下回车提示输入" @keyup.13="showInfo">

5.Vue.config.keyCodes.自定义键名 = 键码,可以去定制按键别名

<body>
    <!-- 准备好一个容器-->
    <div id="root">
        <input type="text" placeholder="按下回车提示输入" @keydown.huiche="showInfo">
    </div>
</body>

<script type="text/javascript">
    Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
    Vue.config.keyCodes.huiche = 13 //定义了一个别名按键
    new Vue({
        el: '#root',
        methods: {
            showInfo(e) {
                // console.log(e.key, e.keyCode)
                console.log(e.target.value)
            }
        },
    })
</script>

9. 计算属性

1.定义:要用的属性不存在,要通过已有属性计算得来。

2.使用:在 computed 对象中定义计算属性 ,在页面中使用{{方法名}}来显示计算的结果(不用加括号)。

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8" />
    <title>姓名案例_计算属性实现</title>
    <!-- 引入Vue -->
    <script type="text/javascript" src="../js/vue.js"></script>
</head>

<body>
    <!-- 准备好一个容器-->
    <div id="root">
        姓:<input type="text" v-model="firstName"> <br/><br/> 
        名:<input type="text" v-model="lastName"> <br/><br/> 
        全名:<span>{{fullName}}</span> <br/><br/>
    </div>
</body>

<script type="text/javascript">
    Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。

    const vm = new Vue({
        el: '#root',
        data: {
            firstName: '张',
            lastName: '三',
        },
        computed: {
            fullName: {
                //get有什么作用?当有人读取fullName时,get就会被调用,且返回值就作为fullName的值
                //get什么时候调用?1.初次读取fullName时。2.所依赖的数据发生变化时。
                get() {
                    //里面的属性要加this
                    return this.firstName + '-' + this.lastName
                },
                //set什么时候调用? 当fullName被修改时。
                set(value) {
                    console.log('set', value)
                    const arr = value.split('-')
                    this.firstName = arr[0]
                    this.lastName = arr[1]
                }
            }
        }
    })
</script>

</html>

3.原理:底层借助了Objcet.defineproperty方法提供的gettersetter

4.get函数初次读取时会执行一次当依赖的数据发生改变时会被再次调用

5.优势:与methods实现相比,内部有缓存机制(复用),效率更高,调试方便

6.注意

  • 计算属性最终会出现在vm上,直接读取使用即可(不用加括号)。
  • 如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时依赖的数据发生改变。

7.当计算属性只需要显示不需要修改时,我们可以省略set函数,得到计算属性的简写形式

<body>
		<!-- 准备好一个容器-->
		<div id="root">
			姓:<input type="text" v-model="firstName"> <br/><br/>
			名:<input type="text" v-model="lastName"> <br/><br/>
			全名:<span>{{fullName}}</span> <br/><br/>
		</div>
	</body>

	<script type="text/javascript">
		Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。

		const vm = new Vue({
			el:'#root',
			data:{
				firstName:'张',
				lastName:'三',
			},
			computed:{
				//简写: 不需要set函数,只需要get函数
				fullName(){
					console.log('get被调用了')
					return this.firstName + '-' + this.lastName
				}
			}
		})
	</script>

10. 监视属性(侦听属性)

一层监视

1.使用:通过 vm 对象的$watch()watch 配置来监视指定的属性

  • new Vue时传入watch配置
const vm = new Vue({
        el: '#root',
        data: {
            isHot: true,
        },
        computed: {
            info() {
                return this.isHot ? '炎热' : '凉爽'
            }
        },
        methods: {
            changeWeather() {
                this.isHot = !this.isHot
            }
        },
        // 写法一
        watch:{
           // 被监视的属性 isHot
        	isHot:{
        		immediate:true, //初始化时让handler调用一下
                
                // newValue是修改后的新值,oldValue是修改前的值
        		handler(newValue,oldValue){
        			console.log('isHot被修改了',newValue,oldValue)
        		}
        	}
        } 
    })
  • 通过vm.$watch监视
vm.$watch('isHot', {
        immediate: true, //初始化时让handler调用一下

        // newValue是修改后的新值,oldValue是修改前的值
        handler(newValue, oldValue) {
            console.log('isHot被修改了', newValue, oldValue)
        }
    })

2.当被监视的属性变化时, 回调函数handler自动调用, 进行相关操作

注意:监视的属性必须存在,才能进行监视。若不存在也不会报错

深度监视

Vue中的watch默认不监测对象内部值的改变(一层),配置deep:true可以监测对象内部值改变(多层)

const vm = new Vue({
	el:'#root',
	data:{
		isHot:true,
		numbers:{
			a:1,
			b:1,
			c:{
				d:{
					e:100
				}
			}
		}
	},
	watch:{
		//监视多级结构中某个属性的变化
		'numbers.a':{
			handler(){
				console.log('a被改变了')
			}
		},
		//监视多级结构中所有属性的变化
		numbers:{
			deep:true,
			handler(){
				console.log('numbers改变了')
			}
		}
	}
})

注意Vue自身可以监测对象内部值的改变,但Vue提供的watch默认不可以!

代码简写

代码在没有配置immediatedeep等属性,只有handler时可以进行简写。

  • new Vue时传入watch配置
const vm = new Vue({
	el:'#root',
	data:{
		isHot:true,
	},
	watch:{
		//正常写法
		isHot:{
			// immediate:true, //初始化时让handler调用一下
			// deep:true,//深度监视
			handler(newValue,oldValue){
				console.log('isHot被修改了',newValue,oldValue)
			}
		},
		//简写
		isHot(newValue,oldValue){
			console.log('isHot被修改了',newValue,oldValue,this)
		} 
	}
})
  • 通过vm.$watch监视
//正常写法
vm.$watch('isHot',{
	immediate:true, //初始化时让handler调用一下
	deep:true,//深度监视
	handler(newValue,oldValue){
		console.log('isHot被修改了',newValue,oldValue)
	}
})

//简写
vm.$watch('isHot',function(newValue,oldValue){
	console.log('isHot被修改了',newValue,oldValue,this)
})

计算属性 vs 侦听属性

computedwatch之间的区别:

  • computed能完成的功能,watch都可以完成。
  • watch能完成的功能,computed不一定能完成,例如:watch可以进行异步操作。
watch:{
	firstName(val){
	// 这里的this指向的是vm,因为setTimeout是箭头函数
	setTimeout(()=>{
		//console.log(this)
		this.fullName = val + '-' + this.lastName
	},1000);
   }
}

注意:

  • 所被Vue管理的函数,最好写成普通函数,这样this的指向才是vm 或 组件实例对象。
  • 所有不被Vue所管理的函数(定时器的回调函数、ajax的回调函数等、Promise的回调函数),最好写成箭头函数 ,这样this的指向才是vm 或 组件实例对象。
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

焦妮敲代码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值