## 一、 发送AJAX请求

### 1. 简介
    vue本身不支持发送AJAX请求,需要使用vue-resource、axios等插件实现
    axios是一个基于Promise的HTTP请求客户端,用来发送请求,也是vue2.0官方推荐的,同时不再对vue-resource进行更新和维护
    
    参考:GitHub上搜索axios,查看API文档

### 2. 使用axios发送AJAX请求

#### 2.1 安装axios并引入
    npm install axios -S
    也可直接下载axios.min.js文件

#### 2.2 基本用法  
    axios([options])  
    axios.get(url[,options]);
        传参方式:
            1.通过url传参
            2.通过params选项传参
    axios.post(url,data,[options]);
        axios默认发送数据时,数据格式是Request Payload,并非我们常用的Form Data格式,
        所以参数必须要以键值对形式传递,不能以json形式传参
        传参方式:
            1.自己拼接为键值对
            2.使用transformRequest,在请求发送前将请求数据进行转换
            3.如果使用模块化开发,可以使用qs模块进行转换
    
    axios本身并不支持发送跨域的请求,没有提供相应的API,作者也暂没计划在axios添加支持发送跨域请求,所以只能使用第三方库

### 3. 使用vue-resource发送跨域请求

#### 3.1 安装vue-resource并引入    
    cnpm install vue-resource -S

#### 3.2 基本用法
    使用this.$http发送请求  
        this.$http.get(url, [options])
        this.$http.head(url, [options])
        this.$http.delete(url, [options])
        this.$http.jsonp(url, [options])
        this.$http.post(url, [body], [options])
        this.$http.put(url, [body], [options])
        this.$http.patch(url, [body], [options])

### 4. 练习
    百度搜索列表
    课后作业:
        1.只显示4条
        2.回车后在新页面中显示搜索结果

## 二、Vue生命周期
    vue实例从创建到销毁的过程,称为生命周期,共有八个阶段

## 三、计算属性

### 1. 基本用法
    计算属性也是用来存储数据,但具有以下几个特点:
        a.数据可以进行逻辑处理操作
        b.对计算属性中的数据进行监视

### 2.计算属性 vs 方法
    将计算属性的get函数定义为一个方法也可以实现类似的功能
    区别:
        a.计算属性是基于它的依赖进行更新的,只有在相关依赖发生改变时才能更新变化
        b.计算属性是缓存的,只要相关依赖没有改变,多次访问计算属性得到的值是之前缓存的计算结果,不会多次执行

### 3. get和set
    计算属性由两部分组成:get和set,分别用来获取计算属性和设置计算属性
    默认只有get,如果需要set,要自己添加

## 四、 vue实例的属性和方法

### 1. 属性
    vm.$el
    vm.$data
    vm.$options
    vm.$refs

### 2. 方法
    vm.$mount()
    vm.$destroy()
    vm.$nextTick(callback)

vm.$set(object,key,value)
    vm.$delete(object,key)
    vm.$watch(data,callback[,options])

## 五、自定义指令
    分类:全局指令、局部指令

### 1. 自定义全局指令
    使用全局方法Vue.directive(指令ID,定义对象)

### 2. 自定义局部指令

### 3. 练习
    拖动页面中的元素
    onmouseover onmouseout 
    onmousedown onmousemove  onmouseup

## 六、过渡(动画)

### 1. 简介
    Vue 在插入、更新或者移除 DOM 时,提供多种不同方式的应用过渡效果
    本质上还是使用CSS3动画:transition、animation

### 2. 基本用法
    使用transition组件,将要执行动画的元素包含在该组件内
        <transition>
            运动的元素
        </transition>       
    过滤的CSS类名:6个
    
### 3. 钩子函数
    8个

### 4. 结合第三方动画库animate..css一起使用
    <transition enter-active-class="animated fadeInLeft" leave-active-class="animated fadeOutRight">
        <p v-show="flag">网博</p>
    </transition>

### 5. 多元素动画
    <transition-group>

### 6. 练习
    多元素动画

<!DOCTYPE html>
<html><head><meta charset="utf-8"><title>发送ajax请求</title><script src="js/vue.js"></script><script src="js/axios.min.js"></script><script src="js/vue-resource.min.js"></script><script>window.onload=function(){new Vue({el:'#itan',data:{user:{name:'alice',age:19},uid:''},methods:{send(){axios({methods:'get',url:'user.json'}).then(function(resp){console.log(resp.data);}).catch(resp=>{console.log(resp);console.log('请求失败:'+resp.status+','+resp.statusText);});},sendGet(){/* axios.get('server.php?name=tom&age=23') */axios.get('server.php',{params:{name:'alice',age:19}}) .then(resp => {console.log(resp.data);}).catch(err => {console.log('请求失败:'+err.status+','+err.statusText);});},// 使用transformRequest,在请求发送前将请求数据进行转换sendPost(){// axios.post('server.php',{//      name:'alice',//       age:19// })// axios.post('server.php','name=alice&age=20&') //方式1axios.post('server.php',this.user,{transformRequest:[function(data){let params='';for(let index in data){params+=index+'='+data[index]+'&';}return params;}]}).then(resp => {console.log(resp.data);}).catch(err => {console.log('请求失败:'+err.status+','+err.statusText);});},getUserById(uid){axios.get(`https://api.github.com/users/${uid}`).then(resp => {// console.log(resp.data);this.user=resp.data;});},//跨越请求sendJSONP(){//https://sug.so.360.cn/suggest?callback=suggest_so&encodein=utf-8&encodeout=utf-8&format=json&fields=word&word=athis.$http.jsonp('https://sug.so.360.cn/suggest',{params:{word:'a'}}).then(resp => {console.log(resp.data.s);});},sendJSONP2(){//https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=a&json=1&p=3&sid=1420_21118_17001_21931_23632_22072&req=2&csor=1&cb=jQuery110208075694879886905_1498805938134&_=1498805938138this.$http.jsonp('https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su',{params:{wd:'a'},jsonp:'cb' //百度使用的jsonp参数名为cb,所以需要修改}).then(resp => {console.log(resp.data.s);});}}})}</script></head><body><div id="itan"><button @click="send">发送AJAX请求</button><button @click="sendGet">GET方式发送AJAX请求</button><button @click="sendPost">POST方式发送AJAX请求</button>GitHub ID: <input type="text" v-model="uid"><button @click="getUserById(uid)">获取指定GitHub账户信息并显示</button><br>姓名:{{user.name}} <br>头像:<img :src="user.avatar_url" alt=""><hr><button @click="sendJSONP">向360搜索发送JSONP请求</button><button @click="sendJSONP2">向百度搜索发送JSONP请求</button><hr><br></div></body>
</html>
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>发送AJAX请求</title><style>.current{background-color:#ccc;}</style><script src="js/vue.js"></script><script src="js/vue-resource.min.js"></script><script>window.onload=function(){new Vue({el:'#itany',data:{keyword:'',myData:[],now:-1 //当前选中项的索引},methods:{getData(e){//如果按方向键上、下,则不发请求if(e.keyCode==38||e.keyCode==40) return;this.$http.jsonp('https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su',{params:{wd:this.keyword},jsonp:'cb'}).then(resp => {this.myData=resp.data.s;});},changeDown(){this.now++;this.keyword=this.myData[this.now];if(this.now==this.myData.length){this.now=-1;}},changeUp(){this.now--;this.keyword=this.myData[this.now];if(this.now==-2){this.now=this.myData.length-1;}}}});}</script>
</head>
<body><div id="itany"><input type="text" v-model="keyword" @keyup="getData($event)" @keydown.down="changeDown" @keydown.up.prevent="changeUp"><ul><li v-for="(value,index) in myData" :class="{current:index==now}">{{value}}</li></ul><p v-show="myData.length==0">暂无数据....</p></div>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Vue生命周期</title><script src="js/vue.js"></script><script>window.onload=function(){let vm=new Vue({el:'#itany',data:{msg:'welcome to itany'},methods:{update(){this.msg='欢迎来到南京网博!';},destroy(){// this.$destroy();vm.$destroy();}},/* beforeCreate(){alert('组件实例刚刚创建,还未进行数据观测和事件配置');},created(){  //常用!!!alert('实例已经创建完成,并且已经进行数据观测和事件配置');},beforeMount(){alert('模板编译之前,还没挂载');},mounted(){ //常用!!!alert('模板编译之后,已经挂载,此时才会渲染页面,才能看到页面上数据的展示');},beforeUpdate(){alert('组件更新之前');},updated(){alert('组件更新之后');},beforeDestroy(){alert('组件销毁之前');},destroyed(){alert('组件销毁之后');} */});}</script>
</head>
<body><div id="itany">{{msg}}<br><button @click="update">更新数据</button><button @click="destroy">销毁组件</button> //销毁组件将无法进行更新了</div>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>计算属性</title><script src="js/vue.js"></script>
</head>
<body><div id="itany"><!-- 1.基本用法--><h2>{{msg}}</h2><h2>{{msg2}}</h2><!-- 对数据处理再显示 --><h2>{{msg.split(' ').reverse().join(' ')}}</h2><h2>{{reverseMsg}}</h2><button @click="change">修改值</button> <!-- 2.计算属性 vs 方法--><h2>{{num1}}</h2><h2>{{num2}}</h2><h2>{{getNum2()}}</h2> <button onclick="fn()">测试</button><!-- 3.get和set--><h2>{{num2}}</h2><button @click="change2">修改计算属性</button> </div><script>var vm=new Vue({el:'#itany',data:{ //普通属性msg:'welcome to itany',num1:8},computed:{ //计算属性msg2:function(){ //该函数必须有返回值,用来获取属性,称为get函数return '欢迎来到南京网博';},reverseMsg:function(){//可以包含逻辑处理操作,同时reverseMsg依赖于msgreturn this.msg.split(' ').reverse().join(' ');},num2:{get:function(){ //默认会调用此方法console.log('num2:'+new Date());return this.num1-1;},set:function(val){ //当值被修改过后会调用console.log('修改num2值');// this.num2=val;this.num1=250;}}},methods:{change(){this.msg='i love you';//this.num1=666;},getNum2(){console.log(new Date());return this.num1-1;},change2(){this.num2=111;} }});function fn(){setInterval(function(){// console.log(vm.num2);console.log(vm.getNum2());},1000);}</script></body>
</html>
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>vue实例的属性和方法</title><script src="js/vue.js"></script>
</head>
<body><div id="itany">{{msg}}<h2 ref="hello">你好</h2><p ref="world">世界</p><hr><h1 ref="title">标题:{{name}}</h1></div><script>var vm=new Vue({el:'#itany',data:{msg:'welcome to itany'},name:'tom',age:24,show:function(){console.log('show');}});/*** 属性*///vm.属性名 获取data中的属性console.log(vm.msg);//vm.$el 获取vue实例关联的元素console.log(vm.$el); //DOM对象vm.$el.style.color='red';//vm.$data //获取数据对象dataconsole.log(vm.$data);console.log(vm.$data.msg);//vm.$options //获取自定义属性console.log(vm.$options.name);console.log(vm.$options.age);vm.$options.show();//vm.$refs 获取所有添加ref属性的元素console.log(vm.$refs);console.log(vm.$refs.hello); //DOM对象vm.$refs.hello.style.color='blue';/*** 方法*///vm.$mount()  手动挂载vue实例// vm.$mount('#itany');var vm=new Vue({data:{msg:'欢迎来到南京网博',name:'tom'}}).$mount('#itany');//vm.$destroy() 销毁实例// vm.$destroy();// vm.$nextTick(callback) 在DOM更新完成后再执行回调函数,一般在修改数据之后使用该方法,以便获取更新后的DOM//修改数据vm.name='汤姆';//DOM还没更新完,Vue实现响应式并不是数据发生改变之后DOM立即变化,需要按一定的策略进行DOM更新,需要时间!!// console.log(vm.$refs.title.textContent);vm.$nextTick(function(){//DOM更新完成,更新完成后再执行此代码console.log(vm.$refs.title.textContent);});</script></body>
</html>
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>添加和删除属性:$set、$delete</title><script src="js/vue.js"></script>
</head>
<body><div id="itany"><button @click="doUpdate">修改属性</button><button @click="doAdd">添加属性</button><button @click="doDelete">删除属性</button><hr>   <h2>{{user.name}}</h2><h2>{{user.age}}</h2></div><script>var vm=new Vue({el:'#itany',data:{user:{id:1001,name:'tom'}},methods:{doUpdate(){this.user.name='汤姆'},doAdd(){// this.user.age=25; //通过普通方式为对象添加属性时vue无法实时监视到// this.$set(this.user,'age',18); //通过vue实例的$set方法为对象添加属性,可以实时监视// Vue.set(this.user,'age',22);if(this.user.age){this.user.age++;}else{Vue.set(this.user,'age',1);}// console.log(this.user);},doDelete(){if(this.user.age){// delete this.user.age; //无效Vue.delete(this.user,'age');}}}});</script></body>
</html>
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>监视数据的变化:$watch</title><script src="js/vue.js"></script>
</head>
<body><div id="itany"><input type="text" v-model="name"><h3>{{name}}</h3><hr><input type="text" v-model="age"><h3>{{age}}</h3><hr><input type="text" v-model="user.name"><h3>{{user.name}}</h3></div><script>var vm=new Vue({el:'#itany',data:{name:'tom',age:23,user:{id:1001,name:'alice'}},watch:{ //方式2:使用vue实例提供的watch选项age:(newValue,oldValue) => {console.log('age被修改啦,原值:'+oldValue+',新值:'+newValue);},user:{handler:(newValue,oldValue) => {console.log('user被修改啦,原值:'+oldValue.name+',新值:'+newValue.name);},deep:true //深度监视,当对象中的属性发生变化时也会监视}}});//方式1:使用vue实例提供的$watch()方法vm.$watch('name',function(newValue,oldValue){console.log('name被修改啦,原值:'+oldValue+',新值:'+newValue);});</script></body>
</html>
<!DOCTYPE html>
<html><head><meta charset="utf-8"><title>自定义指令</title>、<script src="js/vue.js"></script></head><body><!-- <div id="itany"><h3 v-hello>{{msg}}</h3><button @click="change">更新数据</button> --><h3 v-world:wbs17022.hehe.haha="username">{{msg}}</h3><p v-world>网博,专业的前端培训</p> <h3 v-wbs>网博</h3> <input type="text" v-model="msg" v-focus> </div><script>/*** 自定义全局指令* 主:使用指令时必须在指定名称前加前缀v- 即v-指令名称*/Vue.directive('hello',{bind(){//常用alert("指令第一次绑定到元素上时调用,只调用一次,可执行初始化操作");},inserted(){alert('被绑定元素插入到dom中时调用');},update(){alert("被绑定元素所在模板更新时调用");},componentUpdated(){alert('被绑定元素所在模板完成一次更新周期时调用');},unbind(){alert('指令与元素解绑时调用,只调用一次');}});//钩子函数Vue.directive('world',{bind(el,binding){console.log(el); //指令绑定的元素,Dom对象el.style.color='red';console.log(binding); *///name}});//传入一个简单的函数 ,bind和update 时调用Vue.directive('wbs',function(){alert('wbs17022');});var vm = new Vue({el:'#itany',data:{msg:'welcome to ma an shan',username:'alice'},methods:{change(){this.msg='欢迎来到马鞍山'}},deactivated:{//自定义局部命令focus:{//当被绑定元素插入到Dom 中时 获取焦点inserted(el){el.focus();}}}});</script></body>
</html>
<!DOCTYPE html>
<html><head><meta charset="utf-8"><title>练习:自定义指令</title><script src="js/vue.js"></script><style>#itany div{width: 100px;height: 100px;position:absolute;}#itany .hello{background-color:red;top:0;left:0;}#itany .world{background-color:blue;top:0;right:0;}</style></head><body><div id="itany"><div class="hello" v-drag>itany</div><div class="word" v-drag> 网博</div></div><script>Vue.directive('drag',function(el){el.onmousedown=function(e){//获取鼠标点击处分别与div左边和上边的距离:鼠标位置-div位置var disX=e.clientX-el.offsetLeft;var disY=e.clientY-el.offsetTop;console.log(disX,disY);//包含在onmousedown里面,表示点击后才移动,为防止鼠标移出div,使用document.onmousemovedocument.onmousemove=function(e){//获取移动后div的位置:鼠标位置-disX/disYvar l=e.clientX-disX;var t=e.clientY-disY;el.style.left=l+'px';el.style.top=t+'px';}//停止移动document.onmouseup=function(e){document.onmousemove=null;document.onmouseup=null;}}});var vm=new Vue({el:'#itany',data:{msg:'welcome to itany',username:'alice'},methods:{change(){this.msg='欢迎来到南京网博'}}});</script></body>
</html>
<!DOCTYPE html>
<html><head><meta charset="utf-8"><title>动画</title><script src="js/vue.js"></script><style>p{width: 300px;height: 300px;background-color:red;}.fade-enter-active,.fade-leave-active{transition:all 3s ease;}.fade-enter-active{opacity:1;width:300px;height:300px;}.fade-leave-active{opacity:0;width:50px;height:50px;}/* .fade-enter需要放在.fade-enter-active的后面 */.fade-enter{opacity:0;width: 100px;height: 100px;}</style></head><body><div id="itany"><button @click="flag=!flag">点我</button><transition name="fade" @before-enter="beforeEnter"@enter="enter"@after-enter="afterEnter"@before-leave="beforeLeave"@leave="leave"@after-leave="afterLeave"><p v-show="flag">网博</p></transition></div><script>var vm=new Vue({el:'#itany',data:{flag:false},methods:{beforeEnter(el){// alert('动画进入之前');},enter(){// alert('动画进入');},afterEnter(el){// alert('动画进入之后');el.style.background='blue';},beforeLeave(){// alert('动画即将之前');},leave(){// alert('动画离开');},afterLeave(el){// alert('动画离开之后');el.style.background='red';}}});</script></body>
</html>
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>动画</title><link rel="stylesheet" href="css/animate.css"><script src="js/vue.js"></script><style>p{width: 300px;height: 300px;background-color:red;margin:0 auto;}</style>
</head>
<body><div id="itany"><button @click="flag=!flag">点我</button><transition enter-active-class="animated fadeInLeft" leave-active-class="animated fadeOutRight"><p v-show="flag">网博</p></transition></div><script>var vm=new Vue({el:'#itany',data:{flag:false}});</script></body>
</html>
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>多元素动画</title><link rel="stylesheet" href="css/animate.css"><script src="js/vue.js"></script><style>p{width: 100px;height: 100px;background-color:red;margin:20px auto;}</style>
</head>
<body><div id="itany"><button @click="flag=!flag">点我</button><transition-group enter-active-class="animated bounceInLeft" leave-active-class="animated bounceOutRight"><p v-show="flag" :key="1">itany</p><p v-show="flag" :key="2">网博</p></transition-group></div><script>var vm=new Vue({el:'#itany',data:{flag:false}});</script></body>
</html>
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>练习:多元素动画</title><link rel="stylesheet" href="css/animate.css"><script src="js/vue.js"></script><style>p{width: 100px;height: 100px;background-color:red;margin:20px auto;}</style>
</head>
<body><div id="itany"><input type="text" v-model="name"><transition-group enter-active-class="animated bounceInLeft" leave-active-class="animated bounceOutRight"><p v-for="(v,k) in arr2" :key="k">{{v}}</p></transition-group></div><script>var vm=new Vue({el:'#itany',data:{flag:true,arr:['tom','jack','mike','alice','alex','mark'],name:''},computed:{arr2:function(){var temp=[];this.arr.forEach(val => {if(val.includes(this.name)){temp.push(val);}});return temp;}}});</script></body>
</html>

vue学习DAY02相关推荐

  1. 前端Vue学习之路(二)-Vue-router路由

    Vue学习之路 (二) Vue-router(基础版) 一.增加静态路由 二.动态路由+路由嵌套+404页面 三. 编程式导航 四.命名路由 五.命名视图 六.重定向和起别名 1.重定向 2.起别名 ...

  2. 前端Vue学习之路(一)-初识Vue

    Vue学习之路 (一) 1.引言 2.更换npm国内镜像源 3.用npm下载Vue 4.Vue全家桶 5.使用命令创建项目 5.推荐插件 6.推荐网站 7.学习扩展 1.引言 先安装node.js环境 ...

  3. 菜鸟Vue学习笔记(三)

    菜鸟Vue学习笔记(三) 本周使用了Vue来操作表单,接下来说下Vue中双向绑定表单元素的用法. Vue中双向绑定是使用的v-model,所谓的双向绑定即改变变量的值,表单元素的值也会改变,同样的,改 ...

  4. 好程序员Web前端教程分享Vue学习心得

    为什么80%的码农都做不了架构师?>>>    好程序员Web前端教程分享Vue学习心得,Vue是一套用于构建用户界面的渐进式框架.与其它大型框架不同的是,Vue 被设计为可以自底向 ...

  5. Vue学习(一)-邂逅Vuejs

    Vue学习(一)- 邂逅Vuejs 零.视频链接 一.邂逅Vuejs 1.认识Vuejs 1.1 为什么学习Vuejs 1.2 简单认识一下Vuejs 2.Vuejs安装方式 2.1 CDN引入 2. ...

  6. Vue 学习第八天

    Vue  学习第八天 1. 了解了回掉函数的使用,了解了文件的读取, 2.Promise 函数讲解 console.dir(Promise) //Promise 函数讲解 //1.其是一个构造函数,既 ...

  7. Vue 学习 第六天学习笔记

    Vue 学习 第六天学习笔记 1.webpack  使用复习 第一步:先建立文件夹. 第二步,用webpack将其初始化,建立管理.npm 的包管理工具管理起来, npm init -y  .注意{查 ...

  8. Vue 学习第五天 学习笔记

    Vue   学习第五天 1. keyup事件 <div id="app"> <input type="text" v-model=" ...

  9. Vue 学习第四天--第一部分 --盲点整理与昨天知识回顾

    Vue   学习第四天--第一部分 1.父组件向子组件传值 v-bind:临时变量名="父组件变量名" v-bind:value="fathervalue" 子 ...

最新文章

  1. 【ES6】 let与const详解
  2. java arraylist 序列化_无法序列化/反序列化ArrayList
  3. c语言 数组比较不等往下累加,用C语言确定两个数组内的元素排列顺序不同,但是元素相同,代码有bug找不出?...
  4. CentOS7安装Python3.4 ,让Python2和3共存
  5. 一文读懂数据分析必备思维:框架思维
  6. 动手动脑及课后实践3
  7. 核磁谱图分析步骤_质谱仪、红外光谱、核磁共振氢谱
  8. python 菜鸟-Python IDE
  9. 【手写数字识别】基于matlab GUI BP神经网络手写数字识别(手写+带面板)【含Matlab源码 1196期】
  10. html5车牌效果,车牌自编效果预览软件【京牌】
  11. labview高级视频150讲下载_视频剪辑篇|讲真的,这些软件素材资源我真舍不得分享!(附下载包)...
  12. C# TCP通讯大族激光打标机
  13. hadoop视频教程下载链接汇总
  14. 《东周列国志》第五十四回 荀林父纵属亡师 孟侏儒托优悟主
  15. Vue3.x 深入浅出系列(连载三)
  16. jQuery closest() 方法
  17. NowcoderGirl编程比赛(三)
  18. Java 环境JDK下载、安装以及环境变量配置详细图解
  19. 2019最新web前端学科全套项目实战教程(完整)
  20. 鱼眼深度估计!环视近场感知系列之几何预测

热门文章

  1. C919刚一落地,外媒的评论就跟上了
  2. Python史上最牛逼的可视化神器
  3. jeeplus工作流版
  4. Android 高仿微信图片选择器
  5. IBM China Global Delivery Center将于3月11日举行上海地区软件人才专场招聘会
  6. ECDH产生共享密钥
  7. 官方标配,吊炸天的Linux可视化管理工具,必须推荐给你~
  8. 颜色直方图 灰度图彩色图
  9. 视频下载网站链接:B站视频下载链接
  10. 最受欢迎的当代设计风格