IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> 前端框架 Vue.js -> 正文阅读

[JavaScript知识库]前端框架 Vue.js

一、MVC模式和MVVM模式的区别

由于vue框架采用的是mvvm模式的开发,这里把MVC模式和MVVM两种模式做一个详细的解释说明。

在解释两种模式之前,首先要先理解一个概念,MVC是一种设计模式,这个模式既可以用在前端也可以用在后端,基于这个模式衍生出许多mvc框架,比如SpringMVC、Struts2、Tapestry、JSF等。但是千万不要把mvc错误认为就是SpringMVC,模式是模式,模式是可以复用到很多地方的,框架是框架,框架的出现是为了解决某一特定的问题的。比如springmvc就是为了解决网站应用程序或者服务web开发——URL路由、Session、模板引擎、静态Web资源等这些问题而出现的一个MVC框架。

MVC模式
在这里插入图片描述
mvc即Model、View、Controller,从上图来理解就是,用户对View进行的操作(这个操作很多比如提交了表单,input框输入了内容等)交给了Controller来处理,控制器Controller调用方法去执行操作相应的Model,一旦Model发生变化后View立即做出相应。

如果前端没有框架,我们可以简单去这么理解,html就是Viewjs相当于Controller用来监听view的操作(比如点击,输入等),把ajax当成Model层,js就是对Model进行操作,并完成Model与View的同步。当然这个解释多少是有点牵强了,但目的是为了让我们更简单去从前端的层面理解这个MVC模式的应用场景。

MVC模式的应用在前端看似是OK的,但是随着时间的发展,前端的业务逻辑随之也变得十分的复杂,这种在前端使用的MVC模式就暴露出了几个问题:

  1. 开发者在前端代码中大量调用相同DOM API ,处理繁琐,操作冗余。
  2. 大量的DOM操作使得页面渲染性能降低,加载速度变慢。
  3. 最重要的一点,当Model发生变化,开发中需要主动更新到View,而View发生变化,开发者又要将变化的数据同步到Model中,这样不仅工作繁琐而且对一些复杂的数据很难维护。

而MVVM模式的出现,完美的解决了上面这三个问题。

MVVM模式
在这里插入图片描述
MVVM模式与MVC模式最大的区别就是它实现了View和Model的自动同步,也就是常说的双向绑定。当Model改变时View也会随之变化,而不用我们手动去操作dom来达到改变View的操作了,反之亦然。目前实现MVVM模式的框架有Vue、AngularJS等。

MVVM即Model、View、ViewModel,其中Model和View没什么说的和mvc中的一样,关键是这个ViewModel层。
ViewModel 是由前端开发人员组织生成和维护的视图数据层。在这一层,前端开发者对从后端获取的Model 数据进行转换处理,做二次封装,以生成符合 View 层使用预期的视图数据模型。

ViewModel所封装出来的数据模型包括视图的状态和行为两部分

  1. 视图状态:比如页面的这一块展示什么,那一块展示什么这些都属于视图状态
  2. 视图行为:页面加载进来时发生什么,点击这一块发生什么,这一块滚动时发生什么这些都属于视图行为(交互)

视图状态和行为都封装在了 ViewModel 里。这样的封装使得 ViewModel 可以完整地去描述 View 层。由于实现了双向绑定,ViewModel 的内容会实时展现在 View 层,这是激动人心的,因为前端开发者再也不必低效又麻烦地通过操纵 DOM 去更新视图(MVVM帮我们做好了这块,而这块也恰恰是最繁琐和重复的一块内容)。

简单来说,View层展示的是ViewModel中封装好的数据,ViewModel层用来和Model层交互,通过ViewModel也就完全解耦了View层和Model层

总结:
MVC模式和MVVM模式都是为了解决现有的问题而出现,基于这两种模式可以开发出相应的框架来解决具体的问题,值得注意的一点是模式是模式,框架是框架,两者的概念不能搞混。.

再一个,有时候我们摸不清分层的界限。比如MVC模式中,到底哪一块是Model,哪一块是Controller的代码,又或者MVVM模式中,Model和ViewModel的区分严格界限到底在哪里,其实这些界限并不重要,重要的是这两种模式的基本思想,根据这中模式的思想设计出相应的框架来解决实际开发中的问题这个才是最重要的。

二、Vue概述

Vue (读音 /vju?/,类似于 view) 是一套用于构建用户界面的渐进式JavaScript框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用(SPA)提供驱动。

为什么要使用Vue.js?

  1. 轻量级,体积小,Vue.js压缩后只有22kb左右(Angular 压缩后 56kb+,React压缩后 44kb+)
  2. 移动优先。更适合移动端,比如移动端的 Touch 事件
  3. 吸取了 Angular(模块化)和 React(虚拟 DOM)的长处,并拥有自己独特的功能,如:计算属性
  4. 易上手,文档全,开源,活跃度高等

第一个Vue程序,Hello,Vue !

<!DOCTYPE html>
<html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml" xmlns:v-if="http://www.w3.org/1999/xhtml"
      xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <title>HelloVue</title>
    <!--引入Vue.js (注意,这里是为了方便测试,采用这种src引入vue,实际开发中都是npm 安装Vue的)-->
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
</head>
<body>
<div id="app" >
    {{message}}    // 双括号用来获取数据    
</div>
</body>
<script>
    var vm = new Vue({
        el:"#app",
        data:{
            message:"hello vue!"   
        }
     });

</script>
</html>

三、Vue.js基础语法

每一个前端的框架肯定都有自己的基础语法,这些语法说白了就是实现元素赋值,循环,判断,以及事件响应即可!

v-bind、v-on、v-if、v-for

<!DOCTYPE html>
<html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml" xmlns:v-if="http://www.w3.org/1999/xhtml"
      xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <title>vue基本语法</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
</head>
<body>
<!--v-bind 绑定数据-->
<div id="app" v-bind:title="message">
    <!--v-bind 可以简写为:-->
    <span :title="message">aaa</span>
    <!--在标签外也可以直接用{{}}直接进行数据渲染-->
    {{message}}

    <!--v-on 监听事件-->
    <button v-on:click="sayHello">点击测试</button>
    <!--v-on可以简写为@ -->
    <button @click="sayHello">点击测试</button>

    <!--if -->
    <li v-if="ok">123</li>
    <li v-if="type=='A'">A</li>
    <li v-else-if="type=='B'">B</li>
    <li v-else>C</li>

    <!--for-->
    <li v-for="m in messageList">
        {{m.num}}
    </li>


</div>
</body>
<script>
    var vm = new Vue({
        el:"#app",
        data:{
            message:"hello vue!",
            ok:false,
            type:"A",
            messageList:[{num:"1"},{num:"2"},{num:"3"}]

        },
        methods: {
            sayHello: function () {
                alert(this.message);
            }
        }
    });

</script>
</html>

v-model:双向绑定,MVVM的实现之处,上面的v-bind可以看出数据发生改变后视图就会相应改变,v-model一般用在input、textarea、select上,即视图View发生改变后,Model数据也会立即变化。

<!DOCTYPE html>
<html lang="en" xmlns:v-model="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <title>vue双向绑定</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
</head>
<body>
    <div id="app">
    	<!--input框通过v-model绑定message,那input框值发生改变后,下面展示的message也会立马发生改变(不用我们再去操作dom来修改内容了,这个vue的双向绑定就直接帮我们完成这个动作了)-->
       输入的文本 <input type="text" v-model="message"> <br>
        展示的文本:{{message}}<br>

        <select v-model="msg">
            <option value="1">1</option>
            <option value="2">2</option>
            <option value="3">3</option>
        </select>
        选中了:{{msg}}
    </div>
</body>

<script>
    var vm = new Vue({
        el:"#app",
        data:{
            message:"123",
            msg:''
        },

    })
</script>
</html>

四、组件

组件是Vue.js中最强大的功能之一,组件可以扩展html元素封装可重用的代码。组件说白了就是一组可重复使用的模板。
在这里插入图片描述
若还是不太理解,可以观察上图,一个页面可能包含多个模块,例如页面头部、侧边栏、内容区等多个模块,这每一个模块对应的就是一个组件每一个大的组件下又可以有很多小的组件例如导航链接、博文之类的小组件。

在vue中的所有页面都是一个个的组件拼接出来的,它不像我们之前的有很多.jsp,.html文件,每一个页面对应一个文件,在vue中是很多很多的.vue组件,组件之间的相互引用组成了一个个的页面。
在这里插入图片描述
如上图,在实际开发中组件是最重要的(或者说你可以把组件当前原来的一个个的模板页面jsp或thymeleaf),页面只有一个。

下面使用简单的示例,来解释组件的应用,当然在开发中肯定不是下面这么用的,下面这个示例只是为了让我们更简单的去理解什么是组件。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>组件</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
</head>
<body>
    <div id="app">
        <!-- v-bind:da="item"  就是命名一个中间值给组件赋值-->
        <hhl v-for="item in items" v-bind:da="item"></hhl>
        <hhl v-bind:da="123456"></hhl>
    </div>
</body>
<script>
    /*定义一个vue组件*/
    Vue.component("hhl",{
        props:['da'], // 要通过一个中间值da来绑定到组件中template里面
        template:'<li>{{da}}</li>'
    });

    var vm = new Vue({
        el:"#app",
        data:{
            items:['a','b','c']
        }
    });

</script>

</html>

五、插槽

案例:比如准备制作一个待办事项组件(todo),该组件由待办标题(todo-title)和待办内容(todo-items)组成,但这三个组件又是相互独立的,该如何操作呢?
我们的目的是为了让这三个组件可以嵌套组合,也就是说todo里面放入todo-title和todo-items。这就用到了插槽。

在 Vue 中我们使用 元素,作为承载分发内容的出口,作者称其为 插槽,可以应用在组合组件的场景中

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>插槽</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
</head>
<body>

    <!--插槽,可以应用在组合组件的场景中-->
    <div id="app">

        <todo>
            <!--将两个组件和插槽互相绑定,这样就相当于组件之间灵活组合起来了,也表明了组件可复用的概念-->
            <todo-title slot="todo-title" title="NBA季后赛"></todo-title>
            <todo-items slot="todo-items" v-for="(item,idx) in todoItems"
                    v-bind:index="idx" v-bind:item="item"
                    v-on:remove="removeItems(idx)"></todo-items>
        </todo>

    </div>

</body>

<script>
    /*Vue.component('todo',{
        template: `<div>
                        <div>NBA季后赛</div>
                        <ul>
                            <li>篮网</li>
                        </ul>
                    </div>`
    });*/

    // 定义一个组件,但是其中的一个div和li标签我想做成可以灵活配置的,可根据我的需要随时改变的内容,这就用到了插槽
    Vue.component('todo',{
        template: `<div>
                        <slot name="todo-title"></slot>
                        <ul>
                            <slot name="todo-items"></slot>
                        </ul>
                    </div>`
    });

    // 定义title组件
    Vue.component('todo-title',{
        props: ['title'],
        template: '<div>{{title}}</div>'
    });

    // 定义li组件
    Vue.component('todo-items',{
        props: ['index','item'],
        template: '<li>{{index+1}}.{{item}}<button @click="removeabc" >删除</button></li>',
        methods: {
            removeabc: function (index) {

                //前端html代码、Vue 、Vue组件 三者是独立的,前端和Vue可以通过id互相绑定,然后前端就可以调用Vue里定义的方法了
                // 组件也可通过插槽和前端连接

                // 但是组件和Vue模块是没有联系的,所以要想组件里调用Vue模块里的方法,就要根据$emit

                // 自定义事件:通过$emit('自定义事件名',参数)触发当前实例上的remove事件,而上面remove又绑定的是Vue模块中的方法,这样也就间接达到了组件调用Vue模块方法的效果
                this.$emit('remove',index);
            }
        }
    });

    var vm = new Vue({
        el:"#app",
        data: {
            todoItems: ['篮网','雄鹿','太阳']
        },
        methods:{
            removeItems: function (i) {
                alert("删除了"+this.todoItems[i]+"OK");
                this.todoItems.splice(i,1); // splice(a,b) 从索引a的元素开始删除,删除b个
            }
        }
    });

</script>

</html>

六、计算属性

计算属性的重点突出在 属性 两个字上(属性是名词),首先它是个 属性 其次这个属性有 计 算 的能力(计算是动词),这里的 计算 就是个函数;简单点说,它就是一个能够将计算结果缓存起来的属性(将行为转化成了静态的属性),仅此而已;可以想象为缓存

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>计算属性</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
</head>
<body>
    <div id="app">
        <!-- 调方法 要加括号-->
        <p>currentTime01 : {{currentTime01()}} </p>

        <!--调计算属性,不加括号,因为这是个属性-->
        <p>currentTime02 : {{currentTime02}} </p>
    </div>
</body>

<script>
    // 浏览器console中调用 vm.currentTime01() 调方法   vm.currentTime02 调计算属性
    var vm = new Vue({
        el:"#app",
        data:{
          msg:"Hello computed!"
        },
        methods:{ // 方法
            currentTime01:function () {
                return Date.now();
            }
        },

        computed:{ // 计算属性   computed的方法名不能和methods里的方法名一样,若一样则只会调用methods里的方法
            currentTime02:function () {
                // 这里的计算属性可以理解为缓存,就是当此属性方法里的内容没有发生改变时,浏览器会调用缓存数据

                // 当msg发生改变时(在浏览器控制台可以输入vm.msg="xxx" 来改变msg值),再调currentTime02这个属性就不会去读缓存了,会重新执行此属性方法
                console.log(this.msg);
                return Date.now();
            }
        }

    })

</script>

</html>

运行上面的代码,控制台出入一下命令
在这里插入图片描述

计算属性的主要特性就是为了将不经常变化的计算结果进行缓存,以节约我们的系统开销

七、Axios

Axios 是一个开源的可以用在浏览器端和 NodeJS 的异步通信框架,它的主要作用就是实现 ajax 异步通信

由于Vue.js是一个视图层框架,vue本身并不包含ajax通信功能,所以要使用axios框架来进行通信。(虽然jquery也可以做ajax通信,但是jquery操作dom太频繁,所以不推荐使用jquery)

<!DOCTYPE html>
<html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <title>axios</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>

    <div id="app">
        <li>姓名:{{info.name}}</li>
        <li>年龄:{{info.age}}</li>
        <li>省:{{info.address.province}}</li>
        <li>市:{{info.address.city}}</li>

        <a v-bind:href="info.url" >点击跳转页面</a>
    </div>

</body>

<script>
    var vm = new Vue({
        el:"#app",

        // 这里的data()主要是对axios返回的数据进行操作
        data(){
            return{
                // 请求的返回参数格式  必须和json字符串一样
                info:{
                    name:null,   // 在这里都设置成null,因为这里是接收参数值的
                    age:null,
                    address:{
                        province:null,
                        city:null
                    },
                    url:null
                }
            }
        },
        mounted(){// 钩子函数 链式编程 ES6新特性
        // data.json是一个json格式的文件,用来模拟url请求
            axios.get("data.json").then(response=>this.info=response.data)// 把返回值赋给data()里定义的info
        }
    })

</script>
</html>

八、路由Vue Router

在解释路由之前,首先来了解一个概念,单页面应用SPA

所谓单页面应用,就是指整个前端只有一个页面的Web应用,一开始只需加载一次js、css等相关资源(这些资源一般都被webpack打包为一个文件了),后面的所有请求,都不会再重新加载页面或者刷新跳转了,而是利用 JavaScript 动态的变换 HTML(采用的是 div 切换显示和隐藏),从而实现UI与用户的交互。在 SPA 应用中,应用加载之后就不会再有整页刷新。
在这里插入图片描述

在这里插入图片描述
一般来说之前的开发以多页面应用MPA为主,一个url就对应一个页面,每次请求都会重新加载新的页面。而单页面就是那种只有一个页面,每次请只是去该这个页面对应的html内容,而不会重新去加载页面。
在这里插入图片描述

用vue写的项目是单页应用,刷新页面会请求一个HTML文件,切换页面的时候,并不会发起新的请求一个HTML文件,只是页面内容发生了变化

Vue-Router概念:路由就是SPA(single page application单页应用)的路径管理器。vue的单页面应用是基于路由和组件的,路由的作用就是用于设定访问路径,并将路径和组件映射起来,路由模块的本质就是建立起url和页面之间的映射关系

简单来理解就是,vue项目是单页面应用,里面主要是有很多组件在不停的切换,而这些组件如何切换,就是根据路由,每一个路由对应一个url并绑定一个组件,这样通过路由和组件就可以实现单页面应用程序的开发了。

从上面的解释来看,我们可以发现路由的作用其实就相当于a标签一样,但是为什么我们不直接使用a标签?
因为a标签是从一个页面跳转到另一个页面,页面会重新加载,相当于打开了一个新的网页。而这显然与vue的单页面应用冲突了,在vue项目中我们需要的不是跳转页面,而是对相应的组件进行渲染。

下面是vue-router的代码实现:

  1. 安装路由,因为vue-router是一个插件包
npm install vue-router --save-dev
  1. 先看一下项目大致内容
    在这里插入图片描述
  2. 定义一些组件,Content.vue
<template>
    <div>
      <!--<h1>用户{{$route.params.id}}</h1>-->
      <h1>用户id:{{id}}</h1>  <!--通过prop传参,就可以直接获取,而不用根据$route来获取参数了-->
      <h1>用户name:{{name}}</h1>
      <h1>用户name:{{age}}</h1>
    </div>
</template>

<script>
    export default {
        props: ['id','name','age'],
        name: "Content",
        // 路由钩子函数:也就是下面的两个方法,它们和java中的拦截器类似,可以在进入该路由的前后做一下事情
        beforeRouteEnter:(to,from,next)=>{
            console.log("进入路由之前"),
            next(vm => {
                vm.getData(); // 在路由执行之前,通过axios获取到数据
            }); // 放行,类似servlet中的chain.doFilter(request, response);

        },
        beforeRouteLeave:(to,from,next)=>{
            console.log("进入路由之后");
            next();
        },
        methods:{
            getData:function () {
                this.axios({
                  method: 'get',
                  url: 'http://localhost:8080/static/mock/data.json',
                }).then(function (response) {
                    console.log(response.data);
                })
            }
        }
    }
</script>

<style scoped>

</style>

  1. 定义路由配置文件
import Vue from 'vue' // 导入Vue
import Router from 'vue-router' // 导入路由插件
import Content from '../components/Content' // 导入刚定义好的Content组件
import Main from '../components/Main' //  导入刚定义好的Main组件
import NotFound from '../components/404'

Vue.use(Router); // 安装路由,也就是导入路由后要使用路由,就要这样声明

// 配置路由  怎么理解这个路由呢? 就像java中的@RequestMapping ,就是一个路径,根据这个路径去执行所对应的方法(这里就是组件)
export default new Router({
    mode: 'history',
    routes: [
      {
          path: '/content/:id/:name/:age',  //路由路径
          name: 'content',  // 路由名称
          component: Content,  // 调转到哪个组件
          props: true // 允许传参
      },
      {
          path: '/main',  //路由路径
          name: 'main',  // 路由名称
          component: Main  // 调转到哪个组件
      },
      {
          path: '*',
          component: NotFound // 404页面
      },
      {
          path: '/goHome',
          redirect: '/main' // 重定向
      }
    ]

})

  1. APP.vue
<template>
  <div id="app">


    <!--
        router-link : 默认会被渲染成一个 <a> 标签,to 属性为指定链接
        router-view: 用于渲染路由匹配到的组件,写一个就行,写多个的话就会渲染多个产生重复的效果
    -->
    <router-link to="/main">首页</router-link>
    <router-link :to="{name:'content',params:{id: 1,name:'詹姆斯',age: 34}}">用户页</router-link>
    <router-link to="/goHome">goHome</router-link>
    <router-view></router-view>

  </div>
</template>

<script>

export default {
  name: 'App',
  components: {
  }
}
</script>

<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

  1. main.js
import Vue from 'vue'
import App from './App'
import router from './router' // 导入路由配置目录
import axios from 'axios'
import VueAxios from 'vue-axios'

Vue.use(VueAxios,axios)

Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router, // 配置路由
  components: { App },
  template: '<App/>'
})

Content.vue中有路由钩子函数,类似java中的拦截器。404组件、重定向的配置在index.js中。

九、Element-ui

element-ui 是饿了么前端出品的基于 Vue.js的 后台组件库,方便程序员进行页面快速布局和构建。Element-ui官网

安装Element-ui

npm i element-ui -S

然后按照官网的教程,引入相应的组件就可以用了。

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-07-10 14:27:32  更:2021-07-10 14:28:57 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/8 18:06:56-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码