2022全面升级!Vue3 + TS 仿知乎专栏企业级项目完结


2022全面升级!Vue3 + TS 仿知乎专栏企业级项目

download : https://www.sisuoit.com/3301.html


1.使用vue-cli创建Vue3.0项目(js版本)
官方文件:https://cli.vuejs.org/zh/guide/creating-a-project.html # vue-create

比如,随着人工智能的不断发展,机器学习变得越来越重要,很多人都开始学习机器学习。本文介绍了机器学习的基本内容。

# #检查@vue/cli的版本,确保@vue/cli的版本高于4.5.0。
vue版本
# #安装或升级您的@vue/cli
npm安装-g @vue/cli
# #创建
vue创建vue _测试
# #开始
cd vue _测试
npm运行服务
二、常用的组合API
1.设置
了解:
Vue3.0中新增的一个配置项,其值是一个函数。
设置是所有组合API的“表演舞台”。
数据、方法等。在组件中使用的应该在设置中配置。
设置函数的两个返回值:
如果返回一个对象,则该对象中的属性和方法可以直接在模板中使用。(重点!)
如果返回渲染函数,您可以自定义渲染内容。(理解)

注意:
尽量不要和Vue2.x配置混用。

设置中的属性和方法可在Vue2.x配置中访问(数据、方法、计算...).
但是您无法访问Vue2.x配置(数据、方法、计算...)在设置中。
如果有重名,安装程序优先。
Setup不能是异步函数,因为返回值不再是返回的对象,而是承诺,模板看不到返回对象中的属性。(后面也可以返回一个Promise实例,但是需要悬疑和异步组件的配合。)


某人的信息
姓名:{ {姓名}}
年龄:{ {年龄}}
——sayHello(由Vue3配置)



导出默认值{
名称:“应用程序”,
//这里只是对设置的一个测试。我们暂且不考虑响应性的问题。
setup(){
//数据
Let = '张三'
假设年龄= 18岁
设a = 200

//方法
函数sayHello(){
Alert(`我的名字是${name},今年${age}岁。你好!`)
}

//返回一个对象(常用)
返回{
姓名,
年龄,
说你好,
}
}
}

1.1安装时需要注意两点
安装程序的执行时间
在创建之前执行一次,这是未定义的。

设置参数
Props:值是一个对象,它包含:从组件外部传递过来的,由内部组件声明接收的属性。

Attr:值是一个对象,它包含:从组件外部传递过来但没有在props配置中声明的属性,相当于这个。$attrs。
Slots:接收到的slot内容相当于这个。$老虎机。
Emit:分发自定义事件的函数,相当于这个。$emit。
上下文:上下文对象
2.参考函数
1.功能:定义一个响应数据。
2.语法:const xxx = ref(initValue)

创建一个包含响应数据的引用对象(简称ref对象)。
JS: xxx.value中的操作数据
正在读取模板中的数据:。不需要值,直接:{{ xxx }}
3.备注:

接收的数据可以是基本类型或对象类型。
类型的基本数据:响应还是由Object.defineProperty()的get和set来完成。
4.vue3如何通过ref属性获取元素?


我是DIV


导入{ref,onMounted}
导出默认值{
setup(){
let box = ref(null);
onMounted(()=>{
console.log(box.value)
});
返回{box}
}
}

5.Vue3的父组件调用子组件的方法

//父组件


父页面

试验




导入{
定义一个组件,
裁判,
}来自‘vue’;

导出默认定义组件({
setup(){
const son ref = ref(null);
const handleClick = () => {
son ref . value . song();
}
return { sonRef,handleClick,}
}
})

//子组件


子页面




导入{
定义组件
}来自‘vue’;

导出默认定义组件({
setup(){
const song =()= > alert(' hello world ');
返回{
宋,//不忘回报
}
}
})


某人的信息
姓名:{ {姓名}}
年龄:{ {年龄}}
作业类型:{{job.type}}
薪资:{{job.salary}}
修改人们的信息



从“vue”导入{ref}
导出默认值{
名称:“应用程序”,
setup(){
//数据
Let = ref('张三')
设年龄= ref(18)
let job = ref({
类型:“前端工程师”,
薪水:“30K”
})

//方法
函数changeInfo(){
// name.value = '李四'
// age.value = 48
console.log(作业.值)
// job.value.type = 'UI designer '
// job.value.salary = '60K '
// console.log(姓名,年龄)
}

//返回一个对象(常用)
返回{
姓名,
年龄,
工作,
changeInfo
}
}
}

3.反应函数
函数:定义对象类型的响应数据(不要将其用于基本类型,使用ref函数)
语法:const Proxy object = reactive(源对象)接收一个对象(或数组)并返回一个代理对象(Proxy的实例对象,简称代理对象)。
reactive定义的响应式数据是“深度”的。
基于内部ES6的代理实现通过代理对象操作源对象的内部数据。


某人的信息
姓名:{{person.name}}
年龄:{{person.age}}
作业类型:{{person.job.type}}
薪资:{{person.job.salary}}
爱好:{{person.hobby}}
测试数据c: {{person.job.a.b.c}}
修改人们的信息



从“vue”导入{reactive}
导出默认值{
名称:“应用程序”,
setup(){
//数据
让人=被动({
姓名:'张三',
年龄:18,
工作:{
类型:“前端工程师”,
工资:' 30K ',
答:{
乙:{
丙:666
}
}
},
爱好:['抽烟','喝酒','烫发']
})

//方法
函数changeInfo(){
Person.name = '李四'
人.年龄= 48
Person.job.type = 'UI designer '
person.job.salary = '60K '
person . job . a b . c = 999
Person.hobby[0] = '学习'
}

//返回一个对象(常用)
返回{
人,
changeInfo
}
}
}

4.VUE 3.0中的回应原则
4.1 vue 2 . x的响应
1.实施原则:

类型:通过Object.defineProperty()拦截属性的读取和修改(数据劫持)。
数组类型:通过重写一系列更新数组的方法来实现拦截。(改变数组的方法是包装好的)。

Object.defineProperty(data,' count ',{
get () {},
set () {}
})
2.存在的问题:

添加或删除属性,界面不会更新。
通过下标直接修改数组,界面不会自动更新。
仿真Vue2中响应的实现

//源数据
let person = {
姓名:'张三',
年龄:18岁
}

Object.defineProperty(p,' name ',{
可配置:真,
当有人读名字时调用Get(){ //函数
返回人员姓名
},
Set(value){ //当有人修改名称时调用
console . log(‘有人修改了name属性,我发现了。我要更新界面了!)
person.name =值
}
})
Object.defineProperty(p,' age ',{
Get(){ //当有人读取年龄时调用
返回person.age
},
Set(value){ //当有人修改年龄时调用
console . log(‘有人修改了年龄属性,我发现了。我要更新界面了!)
人.年龄=价值
}
})
4.2响应4.2 Vue3.0
1.实施原则:

通过代理:拦截对象中任意属性的变化,包括读写属性值、添加属性、删除属性等。
通过反射:对源对象的属性进行操作。
MDN文档中描述的代理和反射:

代理:https://developer.mozilla.org...
反射:https://developer.mozilla.org...
2.模拟Vue3中的响应

//源数据
let person = {
姓名:'张三',
年龄:18岁
}
const p =新代理(person,{
//当有人读取p的一个属性时调用。
get(目标,属性名){
Console.log(`有人读取了P `上的 { propName }属性)
返回Reflect.get(目标,属性名)
},
//当有人修改或将属性追加到p时调用。
set(目标,属性名,值){
Console.log(`有人修改了p上的${propName}属性,我要更新界面了!`)
Reflect.set(目标,属性名,值)
},
//当有人删除p的一个属性时调用。
deleteProperty(target,propName){
Console.log(`有人删除了p上的${propName}属性,我要更新界面了!`)
返回Reflect.deleteProperty(目标,属性名)
}
})
5.电抗与基准电压的关系
1.从定义数据的角度进行比较:

Ref用于定义:基本类型数据。
Reactive用于定义:对象(或数组)类型数据。
注意:ref也可以用来定义对象(或数组)类型数据,其内部会通过reactive自动转换为代理对象。
2.从原理角度比较:

响应(数据劫持)是通过Object.defineProperty()的get和set实现的。
Reactive通过使用代理实现responsive(数据劫持),通过Reflect操作源对象内部的数据。
3.从使用角度比较:

引用定义的数据:。值是操作数据所必需的,但是。读取数据时,模板中的直接读取不需要值。
反应式定义数据:运行数据和读取数据:不需要。价值。
7.计算属性和监控
7.1.计算函数
与Vue2.x中computed的配置功能一致
写作方法


某人的信息
姓氏:

名称:

全名:{{person.fullName}}

全名:



从“vue”导入{反应式,计算式}
导出默认值{
名称:'演示',
setup(){
//数据
让人=被动({
名字:'张',
姓氏:“三”
})
//计算属性-速记(不考虑计算属性的修改)
/* person . full name = computed(()= > {
返回person . first name+'-'+person . last name
}) */

//计算属性——全写(考虑读写)
person.fullName = computed({
get(){
返回person . first name+'-'+person . last name
},
设置(值){
const nameArr = value.split('-')
person.firstName = nameArr[0]
person.lastName = nameArr[1]
}
})

//返回一个对象(常用)
返回{

}
}
}

7.2.手表功能
1.与Vue2.x中的手表配置功能一致
2.两个小“坑”:

在监控reactive定义的响应式数据时:oldValue无法正确获取,强行开启深度监控(深度配置失败)。
当监控由reactive: deep配置定义的响应数据中的属性时,该配置有效。
3.写作方法


当前总和为:{{sum}}
点+1

当前信息是:{{msg}}
修改信息

姓名:{{person.name}}
年龄:{{person.age}}
薪资:{{person.job.j1.salary}}K
修改名称
成长年龄
涨薪



从“vue”导入{ref,reactive,watch}
导出默认值{
名称:'演示',
setup(){
//数据
让sum = ref(0)
Let msg = ref ('Hello ')
让人=被动({
名字:“小叮当~”,
年龄:18,
工作:{
j1:{
工资:20英镑
}
}
})

//情况1:监控ref定义的响应数据
手表(总和,(新值,旧值)=>{
Console.log('sum changed ',newValue,oldValue)
},{immediate:true})

//情况2:监控ref定义的多个响应数据
手表([sum,msg],(newValue,oldValue)=>{
Console.log('sum或msg已更改',新值,旧值)
},{immediate:true})

/*
案例3:监控由reactive定义的响应数据的所有属性。
1.注意:此处无法正确获取旧值。
2.注意:深度监控是强制开启的(深度配置无效)
*/
手表(人,(新值,旧值)=>{
Console.log('人员已更改',新值,旧值)
},{deep:false}) //此处的深度配置无效。

//情况4:监控reactive定义的响应数据中的一个属性。
手表(()=>person.name,(newValue,oldValue)=>{
Console.log('人名已更改',新值,旧值)
})

//情况五:监控reactive定义的一个响应式数据中的一些属性。
watch([()=>person.name,()=>person.age],(newValue,oldValue)=>{
Console.log('姓名或年龄已更改',newValue,oldValue)
})

//特殊情况
手表(()=>person.job,(newValue,oldValue)=>{
Console.log('人员的工作已更改',新值,旧值)
},{deep:true})
//在这里,深度配置是有效的,因为它监视由反应性元素定义的对象中的一个属性。

//返回一个对象(常用)
返回{
总和,
味精,

}
}
}

7.3.watchEffect功能
1.watch的套路是:既要指明被监控的属性,又要指明被监控的回调。
2.watchEffect的套路是:不需要指明要监控哪个属性,监控的回调中使用了哪个属性,那么就可以监控哪个属性。
3.watchEffect有点像computed:

但是computed注重的是计算值(回调函数的返回值),所以需要写返回值。
WatchEffect更注重过程(回调函数的函数体),所以不需要写返回值。


总和:{{sum}}
点+1

当前信息:{{msg}}
修改

姓名:{{person.name}}
年龄:{{person.age}}
薪资:{{person.job.j1.salary}}K
修改名称
成长年龄
涨薪



从“vue”导入{ref,reactive,watch,watchEffect}
导出默认值{
名称:'演示',
setup(){
//数据
让sum = ref(0)
Let msg = ref ('Hello ')
让人=被动({
姓名:'张三',
年龄:18,
工作:{
j1:{
工资:20英镑
}
}
})

//监控
/* watch(sum,(newValue,oldValue)=>{
console . log(' sum的值已更改',newValue,oldValue)
},{immediate:true}) */

watchEffect(()=>{
常数x1 = sum.value
const x2 = person.job.j1.salary
Console.log(“执行了watcheffect指定的回调”)
})

//返回一个对象(常用)
返回{
总和,
味精,

}
}
}

8.生存期
生命周期图
1.在Vue3.0中可以继续使用Vue2.x中的生命周期钩子,但是其中两个已经被重命名了:

BeforeDestroy被重命名为beforeUnmount。
已销毁被重命名为已卸载。
2.Vue3.0还以Composition API的形式提供了生命周期钩子,与Vue2.x中钩子的对应关系如下:

beforeCreate === >设置()
已创建======= >安装程序()
beforeMount ===> onBeforeMount
已安装======= >已安装
beforeUpdate ===> onBeforeUpdate
更新======= >未更新
before unmount = = > onBeforeUnmount
未安装===== >未安装

当前总和为:{{sum}}
点+1



从“vue”导入{ref,onBeforeMount,onMounted,onBeforeUpdate,onUpdated,onBeforeUnmount,onUnmounted}
导出默认值{
名称:'演示',

setup(){
console.log(' - setup -')
//数据
让sum = ref(0)

//使用复合API形式的生命周期挂钩
onBeforeMount(()=>{
console.log(' - onBeforeMount -')
})
onMounted(()=>{
console.log(' - onMounted -')
})
onBeforeUpdate(()=>{
console.log(' - onBeforeUpdate -')
})
未更新(()=>{
console.log(' - onUpdated -')
})
onBeforeUnmount(()=>{
console.log(' - onBeforeUnmount -')
})
未安装(()=>{
console.log(' - onUnmounted -')
})

//返回一个对象(常用)
返回{sum}
},
//以配置项的形式使用生命周期挂钩
//#区域
创建之前(){
console.log(' - beforeCreate -')
},
已创建(){
console.log(' - created -')
},
beforeMount() {
console.log(' - beforeMount -')
},
已安装(){
console.log(' - mounted -')
},
更新之前(){
console.log(' -更新前-')
},
已更新(){
console.log(' -已更新-')
},
卸载之前(){
console.log(' - beforeUnmount -')
},
卸载(){
console.log(' -已卸载-')
},
//#结束区域
}

9.自定义挂钩功能
1.钩子是什么?-本质是一个函数,封装了setup函数中使用的Composition API。
2.类似于vue2.x中的mixin
3.自定义钩子的优点:复用代码,使设置中的逻辑更加清晰易懂。
4.演示. vue


当前总和为:{{sum}}
点+1

在当前点击时,鼠标的坐标是:x: {{point.x}},y: {{point.y}}



从“vue”导入{ref}
从'导入使用点'../hooks/usePoint
导出默认值{
名称:'演示',
setup(){
//数据
让sum = ref(0)
设point = usePoint()

//返回一个对象(常用)
返回{sum,point}
}
}

5、hooks/usePoint.js

从“vue”导入{reactive,onMounted,onBeforeUnmount}
导出默认函数(){
//鼠标“打点”的相关数据
let point = reactive({
x:0,
y:0
})

//与鼠标“打点”相关的方法
函数保存点(事件){
point . x = event . paxx
point.y =事件.页面
console.log(event.pageX,event.pageY)
}

//实现鼠标“打点”相关的生命周期钩子
onMounted(()=>{
window.addEventListener('click ',保存点)
})

onBeforeUnmount(()=>{
window . removeeventlistener(' click ',保存点)
})

返回点
}
10.托雷夫
1.角色:创建一个ref对象,其值指向另一个对象中的一个属性。
2.语法:const name = toRef(person,' name ')
3.应用:当响应对象中的一个属性只供外部使用时。
4.扩展:torefs的功能和toRef一样,但是可以批量创建多个Ref对象。语法:toRefs(person)


{{person}}
姓名:{ {姓名}}
年龄:{ {年龄}}
薪资:{{job.j1.salary}}K
修改名字~
年龄增长~
升上人生巅峰。



从“vue”导入{ref,reactive,toRef,toRef }
导出默认值{
名称:'演示',
setup(){
//数据
让人=被动({
姓名:'张三',
年龄:18,
工作:{
j1:{
工资:20英镑
}
}
})

// const name1 = person.name
// console.log('*** ',name1)

// const name2 = toRef(person,' name ')
// console.log(' ... '),名称2)

const x = toRefs(人)
console.log('***** ',x)

//返回一个对象(常用)
返回{
人,
// name:toRef(person,' name '),
// age:toRef(person,' age '),
//薪金:toRef(person.job.j1,'薪金'),
...斗牛士(人)
}
}
}

三。其他成分API
1.浅层无功和浅层参考
1.shallowReactive:只处理对象最外层属性的响应(浅层响应)。
2.shallowRef:只处理基本数据类型的响应,不处理对象的响应。
3.什么时候用?

如果有一个对象数据,结构是深的,但当它发生变化时,只是外层属性的变化= = ===> shallowReactive。
如果有一个对象数据,后续函数不会修改对象中的属性,而是创建一个新的对象来替换===> shallowRef。

的当前x.y值为:{{x.y}}
单击我替换x
点我x.y++

{{person}}
姓名:{ {姓名}}
年龄:{ {年龄}}
薪资:{{job.j1.salary}}K
修改名称
成长年龄
涨薪



从“vue”导入{ref,reactive,toRef,toRef,shallowReactive,shallowRef}
导出默认值{
名称:'演示',
setup(){
//数据
//let person = shallow reactive({//只考虑第一层数据的响应。
让人=被动({
姓名:'张三',
年龄:18,
工作:{
j1:{
工资:20英镑
}
}
})
设x = shallowRef({
y:0
})
console.log('***** ',x)

//返回一个对象(常用)
返回{
x,
人,
...斗牛士(人)
}
}
}

2.只读和浅只读
1.readonly:将响应数据设为只读(深度只读)。
2.shallowReadonly:将响应数据设为只读(浅只读)。
3.应用场景:不希望数据被修改的时候。


当前总和为-:{{sum}}
点我++吧

姓名:{ {姓名}}
年龄:{ {年龄}}
薪资:{{job.j1.salary}}K
修改名称
成长年龄
涨薪



从“vue”导入{ref,reactive,toRefs,readonly,shallowReadonly}
导出默认值{
名称:'演示',
setup(){
//数据
让sum = ref(0)
让人=被动({
姓名:'张三',
年龄:18,
工作:{
j1:{
工资:20英镑
}
}
})

person = readonly(person)
//person = shallow readonly(person)
// sum = readonly(总和)
// sum = shallowReadonly(sum)

//返回一个对象(常用)
返回{
总和,
...斗牛士(人)
}
}
}

3.托拉和马克劳
1、托拉:

功能:将reactive生成的一个响应对象变成一个正常对象。
使用场景:用于读取响应对象对应的普通对象。对这个普通对象的所有操作都不会导致页面更新。
2、markRaw:
角色:标记一个对象,使其永远不再是响应对象。
应用场景:

有些值不应该设置为响应式,比如复杂的第三方类库。
当呈现具有不可变数据源的大型列表时,跳过响应转换可以提高性能。

当前总和为:{{sum}}
点我++吧

姓名:{ {姓名}}
年龄:{ {年龄}}
薪资:{{job.j1.salary}}K
汽车信息:{{person.car}}
修改名称
成长年龄
涨薪
输出原人物。
给人加个车。
更改汽车的名称
改变价格



从“vue”导入{ref,reactive,toRefs,toRaw,markRaw}
导出默认值{
名称:'演示',
setup(){
//数据
让sum = ref(0)
让人=被动({
姓名:'张三',
年龄:18,
工作:{
j1:{
工资:20英镑
}
}
})

函数showRawPerson(){
const p = toRaw(人)
p.age++
控制台. log(p)
}

函数addCar(){
汽车= {名称:'奔驰',价格:40}
person.car = markRaw(汽车)
}

函数changePrice(){
person.car.price++
console.log(person.car.price)
}

//返回一个对象(常用)
返回{
总和,
人,
...toRefs(人),
showRawPerson,
addCar,
改变价格
}
}
}

4.customRef
1.功能:创建自定义ref,并显式控制其依赖跟踪和更新触发器。
2.达到防抖效果:


{{ keyWord }}



从“vue”导入{ref,customRef}
导出默认值{
名称:“应用程序”,
setup() {
//自定义一个名为:myRef的ref
函数myRef(值,延迟){
让计时器
return customRef((track,trigger)=>{
返回{
get(){
Console.log(`有人从这个容器myRef中读取了数据,我给了他${value} `)
Track() //通知Vue跟踪值的变化(提前和get商量,让他觉得这个值有用)
返回值
},
set(newValue){
Console.log(`有人将容器myRef中的数据更改为:$ {newvalue } `)
清除超时(定时器)
timer = setTimeout(()=>{
值=新值
Trigger() //通知Vue重新解析模板。
},延迟)
},
}
})
}

// let keyWord = ref('hello') //使用Vue提供的ref
Let keyword = myref ('hello ',500)//使用程序员定义的ref

返回{keyWord}
}
}

5.提供和注射
流程图
1.功能:实现祖先和后代组件之间的通信。
2.例程:父组件有一个提供选项来提供数据,子组件有一个注入选项来开始使用数据。
3.具体写法:

祖先组件:

setup(){
......
Car = reactive ({name:'奔驰',价格:' 40万' })
提供(“汽车”,汽车)
......
}
在后代组件中:

设置(道具、上下文){
......
const car = inject(“汽车”)
返回{汽车}
......
}
6.响应数据的判断
Is:检查一个值是否是ref对象。
IsReactive:检查对象是否是由Reactive创建的响应代理。
Readonly:检查对象是否是由readonly创建的只读代理。
IsProxy:检查对象是否是由reactive或readonly方法创建的代理。

setup(){
汽车=无功({名称:'奔驰',价格:' 40W'})
让sum = ref(0)
让car2 = readonly(汽车)

console.log(isRef(sum))
console.log(isReactive(car))
console.log(isReadonly(car2))
console.log(isProxy(car))
console.log(isProxy(sum))

返回{...toRefs(汽车)}
}
四。新组件
1.碎片
1.在Vue2中:组件必须有一个根标签。
2.在Vue3中:组件可以没有根标签,一个片段虚拟元素中会包含多个标签。
3.好处:减少标签级别和内存占用。

2.传送
什么是瞬间移动?-Teleport是一种可以将我们组件的html结构移动到指定位置的技术。




我是一个弹出窗口。
关闭弹出窗口



3.焦虑
1.在等待异步组件的同时呈现一些额外的内容,让应用程序有更好的用户体验。
2.使用步骤:

异步引入组件

从“vue”导入{defineAsyncComponent}
const Child = defineeasynccomponent(()= > import('。/components/Child.vue '))
用暂记包装组件,并配置默认和回退。


我是一个应用组件

装货.....

动词 (verb的缩写)其他人
1.全球API转移
1.Vue 2.x有很多全局API和配置。

例如,注册全局组件、注册全局指令等。

//注册全局组件
Vue.component('MyButton ',{
数据:()=> ({
计数:0
}),
模板:“点击了{{ count }}次。”
})

//注册全局指令
Vue.directive('focus ',{
inserted: el => el.focus()
}
2.这些API在Vue3.0中进行了调整:

将全局API,即Vue.xxx,调整到应用实例(app)。
2.x全局API (vue) 3.x实例API (app)
vue . config . xxxx app . config . xxxx
vue . config . production已删除提示
组件应用程序
指令
vue . misinapp . mixin
vue . use app . use
vue . prototypeapp . config . global properties
2.其他变化
1.数据选项应该始终声明为函数。

过多的类名更改:

。回车,
。v-离开到{
不透明度:0;
}
。v-离开,
。v-enter-to {
不透明度:1;
}
Vue3.x写作

。v-enter-from,
。v-离开到{
不透明度:0;
}

。v-离开-离开,
。v-enter-to {
不透明度:1;
}
3.去掉keyCode作为v-on的修饰符,同时不再支持config.keyCodes。
4.删除v-on.native修饰符

父组件中的绑定事件


在子组件中声明自定义事件。


导出默认值{
发出:['close']
}

5.拆下过滤器。
Filter虽然这个看起来很方便,但是需要一个自定义的语法来打破花括号里的表达式“只是JavaScript”的假设,这不仅有学习成本,还有实现成本!建议用方法调用或计算属性替换筛选器。


展开阅读全文

页面更新:2024-03-05

标签:企业级   总和   函数   组件   属性   定义   姓名   对象   年龄   名称   专栏   项目   数据

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2008-2024 All Rights Reserved. Powered By bs178.com 闽ICP备11008920号-3
闽公网安备35020302034844号

Top