快速入门Vue-3

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
.cn 域名,1个 12个月
简介: 快速入门Vue

2.2 非单文件组件

非单文件组件就是一个html页面里有多个组件


先来补充下template的功能


2.2.1 template

template用来定义html结构,其实``为模板字符串。它可以随意的换行


第一种情况,有 template:


如果 el 绑定的容器没有任何内容,就一个空壳子,但在 Vue 实例中写了 template,就会编译解析这个 template 里的内容,生成虚拟 DOM,最后将 虚拟 DOM 转为 真实 DOM 插入页面(其实就可以理解为 template 替代了 el 绑定的容器的内容)。


    <div id="app">
    </div>
    <script>
        new Vue({
            el: '#app',
            template:`
            <div>
                <h2>当前的n值是:{{n}}</h2>
                <button @click="n++">点我n+1</button>
            </div>
            `,
            data: {
                n:'1'
            }
        })
    </script>

f9acdbb9d16527de2124646a3147343c_f29d4d43fb7681fe4382d4345bf932f9.png


第二种情况,没有 template:


没有 template,就编译解析 el 绑定的容器,生成虚拟 DOM,后面就顺着生命周期执行下去


2.2.2 基本使用

Vue中使用组件的三大步骤:


  • 定义组件(创建组件)
  • 注册组件
  • 使用组件(写组件标签)

定义组件


使用Vue.extend(options)创建,其中options和new Vue(options)时传入的那个options几乎一样,但也有点区别;


区别如下:


el不要写,为什么? ——— 最终所有的组件都要经过一个vm的管理,由vm中的el决定服务哪个容器。


组件中定义的data必须写成函数,为什么? ———— 避免组件被复用时,数据存在引用关系。

讲解一下面试小问题:data必须写成函数:


这是 js 底层设计的原因:举个例子


对象形式


let data = {
    a: 99,
    b: 100
}
let x = data;
let y = data;
// x 和 y 引用的都是同一个对象,修改 x 的值, y 的值也会改变
x.a = 66;
console.loh(x); // a:66 b:100
console.log(y); // a:66 b:100

函数形式


其中data可省略


function data() {
    return {
        a: 99,
        b: 100
    }
}
let x = data();
let y = data();
console.log(x === y); // false
//函数每调用一次就创建一个新的对象返回给他们

备注:使用template可以配置组件结构。


创建一个组件案例:Vue.extend() 创建


<script type="text/javascript">
    Vue.config.productionTip = false
    //第一步:创建school组件
    const school = Vue.extend({
        template:`
        <div class="demo">
          <h2>学校名称:{{schoolName}}</h2>
          <h2>学校地址:{{address}}</h2>
          <button @click="showName">点我提示学校名</button>  
    </div>
      `,
        // el:'#root', //组件定义时,一定不要写el配置项,因为最终所有的组件都要被一个vm管理,由vm决定服务于哪个容器。
        data(){
            return {
                schoolName:'尚硅谷',
                address:'北京昌平'
            }
        },
        methods: {
            showName(){
                alert(this.schoolName)
            }
        },
    })
    //第一步:创建student组件
    const student = Vue.extend({
        template:`
        <div>
          <h2>学生姓名:{{studentName}}</h2>
          <h2>学生年龄:{{age}}</h2>
    </div>
      `,
        data(){
            return {
                studentName:'张三',
                age:18
            }
        }
    })
    //第一步:创建hello组件
    const hello = Vue.extend({
        template:`
        <div> 
          <h2>你好啊!{{name}}</h2>
    </div>
      `,
        data(){
            return {
                name:'Tom'
            }
        }
    })
</script>

注册组件


  • 局部注册:靠new Vue的时候传入components选项
  • 全局注册:靠Vue.component(‘组件名’,组件)

局部注册


<script>
  //创建vm
    new Vue({
        el: '#root',
        data: {
            msg:'你好啊!'
        },
        //第二步:注册组件(局部注册)
        components: {
            school: school,
            student: student
            // ES6简写形式
            // school,
            // student
        }
    })
</script>

全局注册


<script>
  //第二步:全局注册组件
  Vue.component('hello', hello)
</script>

写组件标签


<!-- 准备好一个容器-->
<div id="root">
    <hello></hello>
    <hr>
    <h1>{{msg}}</h1>
    <hr>
    <!-- 第三步:编写组件标签 -->
    <school></school>
    <hr>
    <!-- 第三步:编写组件标签 -->
    <student></student>
</div>

2.2.3 几个注意点

关于组件名:


一个单词组成:


  • 第一种写法(首字母小写):school
  • 第二种写法(首字母大写):School


多个单词组成:


  • 第一种写法(kebab-case命名):my-school
  • 第二种写法(CamelCase命名):MySchool (需要Vue脚手架支持)

备注:


(1).组件名尽可能回避HTML中已有的元素名称,例如:h2、H2都不行。


(2).可以使用name配置项指定组件在开发者工具中呈现的名字。


关于组件标签


第一种写法:


第二种写法:


备注:不用使用脚手架时,会导致后续组件不能渲染。


一个简写方式:


const school = Vue.extend(options) 可简写为:const school = options


2.2.4 组件的嵌套

<!-- 准备好一个容器-->
<div id="root">
</div>
<script type="text/javascript">
    Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
    //定义student组件
    const student = Vue.extend({
        name:'student',
        template:`
        <div>
          <h2>学生姓名:{{name}}</h2>  
          <h2>学生年龄:{{age}}</h2> 
    </div>
      `,
        data(){
            return {
                name:'尚硅谷',
                age:18
            }
        }
    })
    //定义school组件
    const school = Vue.extend({
        name:'school',
        template:`
        <div>
          <h2>学校名称:{{name}}</h2>  
          <h2>学校地址:{{address}}</h2> 
          <student></student>
    </div>
      `,
        data(){
            return {
                name:'尚硅谷',
                address:'北京'
            }
        },
        // 注册组件(局部)
        components:{
            student
        }
    })
    //定义hello组件
    const hello = Vue.extend({
        template:`<h1>{{msg}}</h1>`,
        data(){
            return {
                msg:'欢迎来到尚硅谷学习!'
            }
        }
    })
    //定义app组件
    const app = Vue.extend({
        template:`
        <div> 
          <hello></hello>
          <school></school>
    </div>
      `,
        components:{
            school,
            hello
        }
    })
    //创建vm
    new Vue({
        template:'<app></app>',
        el:'#root',
        //注册组件(局部)
        components:{app}
    })
</script>

2.2.5 VueComponent

school组件本质是一个名为VueComponent的构造函数,且不是程序员定义的,是Vue.extend生成的。


我们只需要写<school/>或<school><school/>,解析时会帮我们创建school组件的实例对象,即Vue帮我们执行的:new VueComponent(options)。


特别注意:每次调用Vue.extend,返回的都是一个全新的VueComponent!!!!(这个VueComponent可不是实例对象)


关于this指向:


组件配置中:data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是【VueComponent实例对象】。


new Vue(options)配置中:data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是【Vue实例对象】。


VueComponent的实例对象,以后简称vc(也可称之为:组件实例对象)。


Vue的实例对象,以后简称vm。


Vue 在哪管理 VueComponent?

8b78946be7944b4117822c969e1022e3_483892eb89916d0d5038f76e52639a77.png


2.2.6 一个重要的内置关系

  • 一个重要的内置关系:VueComponent.prototype.proto === Vue.prototype
  • 为什么要有这个关系:让组件实例对象(vc)可以访问到 Vue原型上的属性、方法。

35507e743866b207442e9be15ce82ab8_645f0042c1d9f4c77570a0f57b0eec9b.png


2.3 单文件组件

单文件组件就是将一个组件的代码写在 .vue 这种格式的文件中,webpack 会将 .vue 文件解析成 html,css,js这些形式。


单文件组件写法介绍


1a4932a496baa9f296adb410d20646b6_cfd99b9ee24520b130109df7d039adf2.png


2.3.1 定义组件

School.vue


<template>
  <div class="demo">
    <h2>学校名称:{{name}}</h2>
    <h2>学校地址:{{address}}</h2>
    <button @click="showName">点我提示学校名</button>  
  </div>
</template>
<script>
   export default {
    name:'School',
    data(){
      return {
        name:'尚硅谷',
        address:'北京昌平'
      }
    },
    methods: {
      showName(){
        alert(this.name)
      }
    },
  }
</script>
<style>
  .demo{
    background-color: orange;
  }
</style>

Student.vue


<template>
<!-- template里写组件的结构
    template不参与编译,最后结构就只剩<div></div>里面的东西
 -->
    <div class="demo">
        <h2>学生名称:{{name}}</h2>
        <h2>学生地址:{{address}}</h2>
        <button @click="showName">点我提示学生地址</button>
    </div>
</template>
<script>
/**
 * script写交互相关的代码(数据方法等)
 * 只有暴露组件,才能引入
 * 关键字export能让组件暴露,可以被重用
 * export default是默认暴露
 *  */ 
export default {
    //name为组件名
    name:'student',
    //以下为配置项
    data() {
        return {
            name:'库里',
            address:'JinZhou'
        }
    },
    methods: {
        showName(){
            alert(this.name)
        }
    },
}
</script>
<style>
/* style写组件的样式 */
    .demo{
        background-color: orange;
    }
</style>

2.3.2 注册组件

把组件写到App汇总组件里


App.vue


用来汇总所有的组件(大总管)


<template>
  <div>
    <School></School>
    <Student></Student>
  </div>
</template>
<script>
  //引入组件
  import School from './School.vue'
  import Student from './Student.vue'
  export default {
    name:'App',
    components:{
      School,
      Student
    }
  }
</script>

2.3.3 写组件标签

在入口文件main.js,通过template写组件标签


main.js


在这个文件里面创建 vue 实例


import App from './App.vue'
new Vue({
  el:'#root',
  template:`<App></App>`,
  components:{App},
})

最后通过index.html页面来显示


引入vue.js文件和main.js文件即可


index.html


在这写 vue 要绑定的容器


<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>练习一下单文件组件的语法</title>
  </head>
  <body>
    <!-- 准备一个容器 -->
    <div id="root"></div>
        <script type="text/javascript" src="../js/vue.js"></script>
    <script type="text/javascript" src="./main.js"></script>
  </body>
</html>

打开index.html看下


es6不支持模块化语法,所以不显示。


我们下面用脚手架即可


b3ada98e3cda63aa2b66df246829a324_4c7270ade8a989ae069c4440bc350a62.png


三、使用Vue脚手架


安装node.js会自动安装npm命令


3.1 安装

配置 npm 淘宝镜像:npm config set registry https://registry.npm.taobao.org


使用前置:


第一步(没有安装过的执行):全局安装 @vue/cli


npm install -g @vue/cli


第二步:切换到要创建项目的目录,然后使用命令创建项目


vue create xxxxx


第三步:启动项目


npm run serve


3c48316275901dc3479bc42e5a80b238_7ccfb7c6086c496096d10b106ab1c14e.png


a9505844d11f48f8be473de587dafbc6_6d8e3a134119e091c5b74b6664224f64.png


脚手架创建成功


fbeec464bfa0852917862cb2edbeffc2_daa8a58e55843bb422f6d40cb40bd428.png


3.2 访问测试

4e072d1ee3e308c96c5648ed6255dfd9_3b2686c6fcebccf5062576d56e0c7e22.png


3.3 脚手架文件结构

├── node_modules 
├── public
│   ├── favicon.ico: 页签图标
│   └── index.html: 主页面
├── src
│   ├── assets: 存放静态资源
│   │   └── logo.png
│   │── component: 存放组件
│   │   └── HelloWorld.vue
│   │── App.vue: 汇总所有组件
│   │── main.js: 入口文件
├── .gitignore: git版本管制忽略的配置
├── babel.config.js: babel的配置文件
├── package.json: 应用包配置文件 
├── README.md: 应用描述文件
├── package-lock.json:包版本控制文件

66106475d27fe8cf3bb8eab2364fd4c5_55e0a5b4a7b02c906f4b43f03fcf4ff7.png

图里没有截取完整,在 main.js中还有


render: h => h(App) 它的作用就是将App汇总组件放入容器中


new Vue({
 el: '#app',
 // 使用组件
 router,
 store,
 // 将App组件放入容器中
 render: h => h(App)
})

更换我们前面写的组件看看能不能生效


3d79e1c6e97642d093e9f327ad5d224c_04daebcbe6dc5127e3b2faafd28d474c.png


3.4 render函数

使用 import 导入第三方库的时候不需要 加 ‘./’


导入我们自己写的:

import App from './App.vue'

导入第三方的

import Vue from 'vue'

不需要在 from ‘vue’ 加 ‘./’ 的原因是第三方库 node_modules 人家帮我们配置好了。


我们通过 import 导入第三方库,在第三方库的 package.json 文件中确定了我们引入的是哪个文件


vue.js与vue.runtime.xxx.js的区别:


vue.js是完整版的Vue,包含:核心功能+模板解析器。


vue.runtime.xxx.js是运行版的Vue,只包含:核心功能;没有模板解析器。


因为vue.runtime.xxx.js没有模板解析器,所以不能使用template配置项,需要使用render函数接


收到的createElement函数去指定具体内容。


3.5 组件化编程流程

  1. 拆分静态组件:组件要按照功能点拆分,命名不要与html元素冲突。
  2. 实现动态组件:考虑好数据的存放位置,数据是一个组件在用,还是一些组件在用:
  3. 一个组件在用:放在组件自身即可。
  4. 一些组件在用:放在他们共同的父组件上(状态提升)。
  5. 实现交互:从绑定事件开始。


  • 使用v-model时要切记:v-model绑定的值不能是props传过来的值,因为props是不可以修改的!
  • props传过来的若是对象类型的值,修改对象中的属性时Vue不会报错,但不推荐这样做。


3.6 浏览器本地存储

Cookie

Cookie是最早被提出来的本地存储方式,在此之前,服务端是无法判断网络中的两个请求是否是同一用户发起的,为解决这个问题,Cookie就出现了。Cookie 是存储在用户浏览器中的一段不超过 4 KB 的字符串。它由一个名称(Name)、一个值(Value)和其它几个用 于控制 Cookie 有效期、安全性、使用范围的可选属性组成。不同域名下的 Cookie 各自独立,每当客户端发起请求时,会自动把当前域名下所有未过期的 Cookie 一同发送到服务器。


Cookie的特性:


Cookie一旦创建成功,名称就无法修改

Cookie是无法跨域名的,也就是说a域名和b域名下的cookie是无法共享的,这也是由Cookie的隐私安全性决定的,这样就能够阻止非法获取其他网站的Cookie

每个域名下Cookie的数量不能超过20个,每个Cookie的大小不能超过4kb

有安全问题,如果Cookie被拦截了,那就可获得session的所有信息,即使加密也于事无补,无需知道cookie的意义,只要转发cookie就能达到目的

Cookie在请求一个新的页面的时候都会被发送过去


Cookie 在身份认证中的作用


客户端第一次请求服务器的时候,服务器通过响应头的形式,向客户端发送一个身份认证的 Cookie,客户端会自动 将 Cookie 保存在浏览器中。


随后,当客户端浏览器每次请求服务器的时候,浏览器会自动将身份认证相关的 Cookie保存,通过请求头的形式发送给 服务器,服务器即可验明客户端的身份。


02d26e55b81ac2b4014b4f1044773a35_9392df239ee396d02fa2382babde2bcd.png


Cookie 不具有安全性


由于 Cookie 是存储在浏览器中的,而且浏览器也提供了读写 Cookie 的 API,因此 Cookie 很容易被伪造,不具有安全 性。因此不建议服务器将重要的隐私数据,通过 Cookie 的形式发送给浏览器。


注意:千万不要使用 Cookie 存储重要且隐私的数据!比如用户的身份信息、密码等。


Session

Session是另一种记录客户状态的机制,不同的是Cookie保存在客户端浏览器中,而Session保存在服务器上。客户端访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上。这就是Session。客户端再次访问时只需要从该Session中查找该客户的状态就可以了。session是一种特殊的cookie。cookie是保存在客户端的,而session是保存在服务端。


为什么要用session

由于cookie 是存在用户端,而且它本身存储的尺寸大小也有限,最关键是用户可以是可见的,并可以随意的修改,很不安全。那如何又要安全,又可以方便的全局读取信息呢?于是,这个时候,一种新的存储会话机制:session 诞生了


session原理


当客户端第一次请求服务器的时候,服务器生成一份session保存在服务端,并将该数据(session)的id以cookie的形式传递给客户端;以后的每次请求,浏览器都会自动的携带cookie来访问服务器(session数据id)。


图示:


ecda58623fb46d98622c365d822b19eb_a45b3f67617d745cc721d591c2e91626.png


session 标准工作流程


cd12c0a00afae63c0eac17ad95acf1b4_fc92284749f0c68b2ee24e58f7111478.png


LocalStorage

LocalStorage是HTML5新引入的特性,由于有的时候我们存储的信息较大,Cookie就不能满足我们的需求,这时候LocalStorage就派上用场了。


LocalStorage的优点:


  • 在大小方面,LocalStorage的大小一般为5MB,可以储存更多的信息
  • LocalStorage是持久储存,并不会随着页面的关闭而消失,除非主动清理,不然会永久存在
  • 仅储存在本地,不像Cookie那样每次HTTP请求都会被携带


LocalStorage的缺点:


  • 存在浏览器兼容问题,IE8以下版本的浏览器不支持
  • 如果浏览器设置为隐私模式,那我们将无法读取到LocalStorage
  • LocalStorage受到同源策略的限制,即端口、协议、主机地址有任何一个不相同,都不会访问


LocalStorage的常用API:


// 保存数据到 localStorage
localStorage.setItem('key', 'value');
// 从 localStorage 获取数据
let data = localStorage.getItem('key');
// 从 localStorage 删除保存的数据
localStorage.removeItem('key');
// 从 localStorage 删除所有保存的数据
localStorage.clear();
// 获取某个索引的Key
localStorage.key(index)

LocalStorage的使用场景:


有些网站有换肤的功能,这时候就可以将换肤的信息存储在本地的LocalStorage中,当需要换肤的时候,直接操作LocalStorage即可


在网站中的用户浏览信息也会存储在LocalStorage中,还有网站的一些不常变动的个人信息等也可以存储在本地的LocalStorage中


SessionStorage

SessionStorage和LocalStorage都是在HTML5才提出来的存储方案,SessionStorage 主要用于临时保存同一窗口(或标签页)的数据,刷新页面时不会删除,关闭窗口或标签页之后将会删除这些数据。


SessionStorage与LocalStorage对比:


  • SessionStorage和LocalStorage都在本地进行数据存储;
  • SessionStorage也有同源策略的限制,但是SessionStorage有一条更加严格的限制,
  • SessionStorage只有在同一浏览器的同一窗口下才能够共享;
  • LocalStorage和SessionStorage都不能被爬虫爬取;


SessionStorage的常用API:


// 保存数据到 sessionStorage
sessionStorage.setItem('key', 'value');
// 从 sessionStorage 获取数据
let data = sessionStorage.getItem('key');
// 从 sessionStorage 删除保存的数据
sessionStorage.removeItem('key');
// 从 sessionStorage 删除所有保存的数据
sessionStorage.clear();
// 获取某个索引的Key
sessionStorage.key(index)

SessionStorage的使用场景


由于SessionStorage具有时效性,所以可以用来存储一些网站的游客登录的信息,还有临时的浏览记录的信息。当关闭网站之后,这些信息也就随之消除了。


四、Vue中的ajax


通用的 Ajax 请求库, 官方推荐,使用广泛


4.1 axios简介

就是在vue发送ajax请求


f93eccacbdfe7efac9f6bfe7f99fec7f_fd13d73d6c8c9af2804c6f208b2e7d0e.png


vscode中使用node.js


如果遇见问题可以重启vscode即可


98475ea65501e0c6427eaf3f743352fe_3c3b816848704f94304a9362cf4aaa5e.png


五、Vuex


5.1 概念

在Vue中实现集中式状态(数据)管理的一个Vue插件,对vue应用中多个组件的共享状态进行集中式的管理(读/写),也是一种组件间通信的方式,且适用于任意组件间通信。


5.2 何时使用?

多个组件需要共享数据时


六、Vue-router


6.1 简介

理解: 一个路由(route)就是一组映射关系(key - value),多个路由需要路由器(router)进行管理。


前端路由:key是路径,value是组件。


5f9d14d2538ab867f8547f258528d028_6c27ba796bdbe91c73df7387d1e29e81.png


3e25c25a72b2dc87a050801f86530e74_29024a81c929088715ecf4541d96abd0.png


  • 路由就是一组key-value对应关系
  • 多个路由,需要经过路由器的管理


6.2 基本使用

  1. 安装vue-router,命令:npm i vue-router
  2. 应用插件:Vue.use(VueRouter)
  3. 编写router配置项:
//引入VueRouter
import VueRouter from 'vue-router'
//引入Luyou 组件
import About from '../components/About'
import Home from '../components/Home'
//创建router实例对象,去管理一组一组的路由规则
const router = new VueRouter({
  routes:[
    {
      path:'/about',
      component:About
    },
    {
      path:'/home',
      component:Home
    }
  ]
})
//暴露router
export default router

4.实现切换(active-class可配置高亮样式)

<router-link active-class="active" to="/about">About</router-link>

5.指定展示位置

<router-view></router-view>

6.3 几个注意点

  1. 路由组件通常存放在pages文件夹,一般组件通常存放在components文件夹。
  2. 通过切换,“隐藏”了的路由组件,默认是被销毁掉的,需要的时候再去挂载。
  3. 每个组件都有自己的$route属性,里面存储着自己的路由信息。
  4. 整个应用只有一个router,可以通过组件的$router属性获取到。


6.4 多级路由(多级路由)

1.配置路由规则,使用children配置项:

routes:[
  {
    path:'/about',
    component:About,
  },
  {
    path:'/home',
    component:Home,
    children:[ //通过children配置子级路由
      {
        path:'news', //此处一定不要写:/news
        component:News
      },
      {
        path:'message',//此处一定不要写:/message
        component:Message
      }
    ]
  }
]

2.跳转(要写完整路径):

<router-link to="/home/news">News</router-link>

3.指定展示位置

<router-view></router-view>

6.5 命名路由

  1. 作用:可以简化路由的跳转。
  2. 如何使用

1.给路由命名:

{
  path:'/demo',
  component:Demo,
  children:[
    {
      path:'test',
      component:Test,
      children:[
        {
                      name:'hello' //给路由命名
          path:'welcome',
          component:Hello,
        }
      ]
    }
  ]
}

2.简化跳转:

<!--简化前,需要写完整的路径 -->
<router-link to="/demo/test/welcome">跳转</router-link>
<!--简化后,直接通过名字跳转 -->
<router-link :to="{name:'hello'}">跳转</router-link>
<!--简化写法配合传递参数 -->
<router-link 
  :to="{
    name:'hello',
    query:{
       id:666,
            title:'你好'
    }
  }"
>跳转</router-link>
相关文章
|
JSON JavaScript 前端开发
快速入门Vue-2
快速入门Vue
66 0
|
Web App开发 JavaScript 前端开发
Vue快速入门
Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。
108 0
Vue快速入门
|
缓存 JavaScript 前端开发
03、vue2.x组件快速入门
03、vue2.x组件快速入门
|
5月前
|
移动开发 JavaScript 编译器
Vue3 系列教程 — Vue 3 简介
Vue3 系列教程 — Vue 3 简介
|
6月前
|
JavaScript API iOS开发
vue3 教程(上)
vue3 教程(上)
72 0
|
6月前
|
JavaScript API
vue3 教程(中)
vue3 教程(中)
45 0
|
8月前
|
移动开发 JSON JavaScript
VUE2.0快速入门(二)
VUE2.0快速入门
60 2
|
8月前
|
缓存 JavaScript 前端开发
VUE2.0快速入门(一)
VUE2.0快速入门
98 0
|
缓存 JavaScript 前端开发
快速入门Vue-1
快速入门Vue
60 0
|
JavaScript 索引
vue快速入门(九) 之 v-for用法
vue快速入门(九) 之 v-for用法
114 0

热门文章

最新文章