当前位置: 首页 > news >正文

四川住房建设和城乡建设厅网站php记录网站访问次数

四川住房建设和城乡建设厅网站,php记录网站访问次数,网站做京东联盟,可以做t恤的网站目录 一、 Vue3简介 1. 性能的提升 2. 源码的升级 3. 拥抱TypeScript 4. 新的特性 二、 创建Vue3工程 1. 基于 vue-cli 创建 2. 基于 vite 创建(推荐) 3. 一个简单的效果 三、Vue3核心语法 1. OptionsAPI 与 CompositionAPI #xff08;1#xff09;Options API …目录 一、 Vue3简介 1. 性能的提升 2. 源码的升级 3. 拥抱TypeScript 4. 新的特性 二、 创建Vue3工程 1. 基于 vue-cli 创建 2. 基于 vite 创建(推荐) 3. 一个简单的效果 三、Vue3核心语法 1. OptionsAPI 与 CompositionAPI 1Options API 的弊端 2Composition API 的优势 2. 拉开序幕的 setup 1setup 概述 2setup 的返回值 3setup 与 Options API 的关系 4setup 语法糖 3. ref 创建基本类型的响应式数据 4. reactive 创建对象类型的响应式数据 5. ref 创建对象类型的响应式数据 6. ref 对比 reactive 7. toRefs 与 toRef 8. computed 9.watch 10. watchEffect 11. 标签的 ref 属性 12. props 13. 生命周期 14. 自定义hook 四、 路由 1. 对路由的理解 2. 基本切换效果 3. 两个注意点 4. 路由器工作模式 5. to的两种写法 6. 命名路由 7. 嵌套路由 8. 路由传参 1query参数 2params参数 9. 路由的props配置 10.  replace属性 11. 编程式导航 12. 重定向 五、pinia 1. 准备一个效果 2.搭建 pinia 环境 3.存储读取数据 4. 修改数据(三种方式) 5. storeToRefs 6. getters 7. $subscribe 8. store组合式写法 六、组件通信 1. props 2. 自定义事件 3. mitt 4. v-model 5. $attrs  6. refs、parent 7. provide、inject 8. pinia 9. slot 七、 其它 API 1. shallowRef 与 shallowReactive  1shallowRef 2shallowReactive 2. readonly 与 shallowReadonly 1readonly 2shallowReadonly 3. toRaw 与 markRaw 1toRaw 2markRaw 4. customRef 八、Vue3新组件 1. Teleport 2. Suspense 3. 全局API转移到应用对象 4. 其他 一、 Vue3简介 2020年9月18日Vue.js发布版3.0版本代号One Piecen 经历了4800次提交、40个RFC、600次PR、300贡献者 官方发版地址Release v3.0.0 One Piece · vuejs/core 截止2023年10月最新的公开版本为3.3.4 1. 性能的提升 打包大小减少41%。 初次渲染快55%, 更新渲染快133%。 内存减少54%。 2. 源码的升级 使用Proxy代替defineProperty实现响应式。 重写虚拟DOM的实现和Tree-Shaking。 3. 拥抱TypeScript Vue3可以更好的支持TypeScript。 4. 新的特性 Composition API组合API setup ref与reactive computed与watch … 新的内置组件 Fragment Teleport Suspense … 其他改变 新的生命周期钩子 data 选项应始终被声明为一个函数 移除keyCode支持作为 v-on 的修饰符 … 二、 创建Vue3工程 1. 基于 vue-cli 创建 点击查看官方文档 备注目前vue-cli已处于维护模式官方推荐基于 Vite 创建项目。 ## 查看vue/cli版本确保vue/cli版本在4.5.0以上 vue --version## 安装或者升级你的vue/cli npm install -g vue/cli## 执行创建命令 vue create vue_test## 随后选择3.x ## Choose a version of Vue.js that you want to start the project with (Use arrow keys) ## 3.x ## 2.x## 启动 cd vue_test npm run serve2. 基于 vite 创建(推荐) vite 是新一代前端构建工具官网地址https://vitejs.cnvite的优势如下 轻量快速的热重载HMR能实现极速的服务启动。对 TypeScript、JSX、CSS 等支持开箱即用。真正的按需编译不再等待整个应用编译完成。webpack构建 与 vite构建对比图如下  具体操作如下点击查看官方文档 ## 1.创建命令 npm create vuelatest## 2.具体配置 ## 配置项目名称 √ Project name: vue3_test ## 是否添加TypeScript支持 √ Add TypeScript? Yes ## 是否添加JSX支持 √ Add JSX Support? No ## 是否添加路由环境 √ Add Vue Router for Single Page Application development? No ## 是否添加pinia环境 √ Add Pinia for state management? No ## 是否添加单元测试 √ Add Vitest for Unit Testing? No ## 是否添加端到端测试方案 √ Add an End-to-End Testing Solution? » No ## 是否添加ESLint语法检查 √ Add ESLint for code quality? Yes ## 是否添加Prettiert代码格式化 √ Add Prettier for code formatting? No自己动手编写一个App组件 templatediv classapph1你好啊/h1/div /templatescript langtsexport default {name:App //组件名} /scriptstyle.app {background-color: #ddd;box-shadow: 0 0 10px;border-radius: 10px;padding: 20px;} /style安装官方推荐的vscode插件 总结 Vite 项目中index.html 是项目的入口文件在项目最外层。加载index.html后Vite 解析 script typemodule srcxxx 指向的JavaScript。Vue3**中是通过 **createApp 函数创建一个应用实例。 3. 一个简单的效果 Vue3向下兼容Vue2语法且Vue3中的模板中可以没有根标签 templatediv classpersonh2姓名{{name}}/h2h2年龄{{age}}/h2button clickchangeName修改名字/buttonbutton clickchangeAge年龄1/buttonbutton clickshowTel点我查看联系方式/button/div /templatescript langtsexport default {name:App,data() {return {name:张三,age:18,tel:13888888888}},methods:{changeName(){this.name zhang-san},changeAge(){this.age 1},showTel(){alert(this.tel)}},} /script三、Vue3核心语法 1. OptionsAPI 与 CompositionAPI Vue2的API设计是Options配置风格的。Vue3的API设计是Composition组合风格的。 1Options API 的弊端 Options类型的 API数据、方法、计算属性等是分散在data、methods、computed中的若想新增或者修改一个需求就需要分别修改data、methods、computed不便于维护和复用。 2Composition API 的优势 可以用函数的方式更加优雅的组织代码让相关功能的代码更加有序的组织在一起。 说明以上四张动图原创作者大帅老猿 2. 拉开序幕的 setup 1setup 概述 setup是Vue3中一个新的配置项值是一个函数它是 Composition API “表演的舞台”组件中所用到的数据、方法、计算属性、监视…等等均配置在setup中。 特点如下 setup函数返回的对象中的内容可直接在模板中使用。setup中访问this是undefined。setup函数会在beforeCreate之前调用它是“领先”所有钩子执行的。 templatediv classpersonh2姓名{{name}}/h2h2年龄{{age}}/h2button clickchangeName修改名字/buttonbutton clickchangeAge年龄1/buttonbutton clickshowTel点我查看联系方式/button/div /templatescript langtsexport default {name:Person,setup(){// 数据原来写在data中注意此时的name、age、tel数据都不是响应式数据let name 张三let age 18let tel 13888888888// 方法原来写在methods中function changeName(){name zhang-san //注意此时这么修改name页面是不变化的console.log(name)}function changeAge(){age 1 //注意此时这么修改age页面是不变化的console.log(age)}function showTel(){alert(tel)}// 返回一个对象对象中的内容模板中可以直接使用return {name,age,tel,changeName,changeAge,showTel}}} /script2setup 的返回值 若返回一个对象则对象中的属性、方法等在模板中均可以直接使用**重点关注。**若返回一个函数则可以自定义渲染内容代码如下 setup(){return () 你好啊 }3setup 与 Options API 的关系 Vue2 的配置data、methos…中可以访问到 setup中的属性、方法。但在setup中不能访问到Vue2的配置data、methos…。如果与Vue2冲突则setup优先。 4setup 语法糖 setup函数有一个语法糖这个语法糖可以让我们把setup独立出去代码如下 templatediv classpersonh2姓名{{name}}/h2h2年龄{{age}}/h2button clickchangName修改名字/buttonbutton clickchangAge年龄1/buttonbutton clickshowTel点我查看联系方式/button/div /templatescript langtsexport default {name:Person,} /script!-- 下面的写法是setup语法糖 -- script setup langtsconsole.log(this) //undefined// 数据注意此时的name、age、tel都不是响应式数据let name 张三let age 18let tel 13888888888// 方法function changName(){name 李四//注意此时这么修改name页面是不变化的}function changAge(){console.log(age)age 1 //注意此时这么修改age页面是不变化的}function showTel(){alert(tel)} /script扩展上述代码还需要编写一个不写setup的script标签去指定组件名字比较麻烦我们可以借助vite中的插件简化 第一步npm i vite-plugin-vue-setup-extend -D第二步vite.config.ts import { defineConfig } from vite import VueSetupExtend from vite-plugin-vue-setup-extendexport default defineConfig({plugins: [ VueSetupExtend() ] })第三步script setup langts namePerson 3. ref 创建基本类型的响应式数据 **作用**定义响应式变量。语法let xxx ref(初始值)。**返回值**一个RefImpl的实例对象简称ref对象或refref对象的value属性是响应式的。注意点 JS中操作数据需要xxx.value但模板中不需要.value直接使用即可。对于let name ref(张三)来说name不是响应式的name.value是响应式的。 templatediv classpersonh2姓名{{name}}/h2h2年龄{{age}}/h2button clickchangeName修改名字/buttonbutton clickchangeAge年龄1/buttonbutton clickshowTel点我查看联系方式/button/div /templatescript setup langts namePersonimport {ref} from vue// name和age是一个RefImpl的实例对象简称ref对象它们的value属性是响应式的。let name ref(张三)let age ref(18)// tel就是一个普通的字符串不是响应式的let tel 13888888888function changeName(){// JS中操作ref对象时候需要.valuename.value 李四console.log(name.value)// 注意name不是响应式的name.value是响应式的所以如下代码并不会引起页面的更新。// name ref(zhang-san)}function changeAge(){// JS中操作ref对象时候需要.valueage.value 1 console.log(age.value)}function showTel(){alert(tel)} /script4. reactive 创建对象类型的响应式数据 作用定义一个响应式对象基本类型不要用它要用ref否则报错语法let 响应式对象 reactive(源对象)。**返回值**一个Proxy的实例对象简称响应式对象。注意点reactive定义的响应式数据是“深层次”的。 templatediv classpersonh2汽车信息一台{{ car.brand }}汽车价值{{ car.price }}万/h2h2游戏列表/h2ulli v-forg in games :keyg.id{{ g.name }}/li/ulh2测试{{obj.a.b.c.d}}/h2button clickchangeCarPrice修改汽车价格/buttonbutton clickchangeFirstGame修改第一游戏/buttonbutton clicktest测试/button/div /templatescript langts setup namePerson import { reactive } from vue// 数据 let car reactive({ brand: 奔驰, price: 100 }) let games reactive([{ id: ahsgdyfa01, name: 英雄联盟 },{ id: ahsgdyfa02, name: 王者荣耀 },{ id: ahsgdyfa03, name: 原神 } ]) let obj reactive({a:{b:{c:{d:666}}} })function changeCarPrice() {car.price 10 } function changeFirstGame() {games[0].name 流星蝴蝶剑 } function test(){obj.a.b.c.d 999 } /script5. ref 创建对象类型的响应式数据 其实ref接收的数据可以是基本类型、对象类型。若ref接收的是对象类型内部其实也是调用了reactive函数。 templatediv classpersonh2汽车信息一台{{ car.brand }}汽车价值{{ car.price }}万/h2h2游戏列表/h2ulli v-forg in games :keyg.id{{ g.name }}/li/ulh2测试{{obj.a.b.c.d}}/h2button clickchangeCarPrice修改汽车价格/buttonbutton clickchangeFirstGame修改第一游戏/buttonbutton clicktest测试/button/div /templatescript langts setup namePerson import { ref } from vue// 数据 let car ref({ brand: 奔驰, price: 100 }) let games ref([{ id: ahsgdyfa01, name: 英雄联盟 },{ id: ahsgdyfa02, name: 王者荣耀 },{ id: ahsgdyfa03, name: 原神 } ]) let obj ref({a:{b:{c:{d:666}}} })console.log(car)function changeCarPrice() {car.value.price 10 } function changeFirstGame() {games.value[0].name 流星蝴蝶剑 } function test(){obj.value.a.b.c.d 999 } /script6. ref 对比 reactive 宏观角度看 ref用来定义基本类型数据、对象类型数据 reactive用来定义对象类型数据。 区别 ref创建的变量必须使用.value可以使用volar插件自动添加.value。 reactive重新分配一个新对象会失去响应式可以使用Object.assign去整体替换。 使用原则 若需要一个基本类型的响应式数据必须使用ref。若需要一个响应式对象层级不深ref、reactive都可以。若需要一个响应式对象且层级较深推荐使用reactive。 7. toRefs 与 toRef 作用将一个响应式对象中的每一个属性转换为ref对象。备注toRefs与toRef功能一致但toRefs可以批量转换。语法如下 templatediv classpersonh2姓名{{person.name}}/h2h2年龄{{person.age}}/h2h2性别{{person.gender}}/h2button clickchangeName修改名字/buttonbutton clickchangeAge修改年龄/buttonbutton clickchangeGender修改性别/button/div /templatescript langts setup namePersonimport {ref,reactive,toRefs,toRef} from vue// 数据let person reactive({name:张三, age:18, gender:男})// 通过toRefs将person对象中的n个属性批量取出且依然保持响应式的能力let {name,gender} toRefs(person)// 通过toRef将person对象中的gender属性取出且依然保持响应式的能力let age toRef(person,age)// 方法function changeName(){name.value ~}function changeAge(){age.value 1}function changeGender(){gender.value 女} /script8. computed 作用根据已有数据计算出新数据和Vue2中的computed作用一致。 templatediv classperson姓input typetext v-modelfirstName br名input typetext v-modellastName br全名span{{fullName}}/span brbutton clickchangeFullName全名改为li-si/button/div /templatescript setup langts nameAppimport {ref,computed} from vuelet firstName ref(zhang)let lastName ref(san)// 计算属性——只读取不修改/* let fullName computed((){return firstName.value - lastName.value}) */// 计算属性——既读取又修改let fullName computed({// 读取get(){return firstName.value - lastName.value},// 修改set(val){console.log(有人修改了fullName,val)firstName.value val.split(-)[0]lastName.value val.split(-)[1]}})function changeFullName(){fullName.value li-si} /script9.watch 作用监视数据的变化和Vue2中的watch作用一致特点Vue3中的watch只能监视以下四种数据 ref定义的数据。reactive定义的数据。函数返回一个值getter函数。一个包含上述内容的数组。 我们在Vue3中使用watch的时候通常会遇到以下几种情况 * 情况一 监视ref定义的【基本类型】数据直接写数据名即可监视的是其value值的改变。 templatediv classpersonh1情况一监视【ref】定义的【基本类型】数据/h1h2当前求和为{{sum}}/h2button clickchangeSum点我sum1/button/div /templatescript langts setup namePersonimport {ref,watch} from vue// 数据let sum ref(0)// 方法function changeSum(){sum.value 1}// 监视情况一监视【ref】定义的【基本类型】数据const stopWatch watch(sum,(newValue,oldValue){console.log(sum变化了,newValue,oldValue)if(newValue 10){stopWatch()}}) /script* 情况二 监视ref定义的【对象类型】数据直接写数据名监视的是对象的【地址值】若想监视对象内部的数据要手动开启深度监视。 注意 若修改的是ref定义的对象中的属性newValue 和 oldValue 都是新值因为它们是同一个对象。 若修改整个ref定义的对象newValue 是新值 oldValue 是旧值因为不是同一个对象了。 templatediv classpersonh1情况二监视【ref】定义的【对象类型】数据/h1h2姓名{{ person.name }}/h2h2年龄{{ person.age }}/h2button clickchangeName修改名字/buttonbutton clickchangeAge修改年龄/buttonbutton clickchangePerson修改整个人/button/div /templatescript langts setup namePersonimport {ref,watch} from vue// 数据let person ref({name:张三,age:18})// 方法function changeName(){person.value.name ~}function changeAge(){person.value.age 1}function changePerson(){person.value {name:李四,age:90}}/* 监视情况一监视【ref】定义的【对象类型】数据监视的是对象的地址值若想监视对象内部属性的变化需要手动开启深度监视watch的第一个参数是被监视的数据watch的第二个参数是监视的回调watch的第三个参数是配置对象deep、immediate等等..... */watch(person,(newValue,oldValue){console.log(person变化了,newValue,oldValue)},{deep:true})/script* 情况三 监视reactive定义的【对象类型】数据且默认开启了深度监视。 templatediv classpersonh1情况三监视【reactive】定义的【对象类型】数据/h1h2姓名{{ person.name }}/h2h2年龄{{ person.age }}/h2button clickchangeName修改名字/buttonbutton clickchangeAge修改年龄/buttonbutton clickchangePerson修改整个人/buttonhrh2测试{{obj.a.b.c}}/h2button clicktest修改obj.a.b.c/button/div /templatescript langts setup namePersonimport {reactive,watch} from vue// 数据let person reactive({name:张三,age:18})let obj reactive({a:{b:{c:666}}})// 方法function changeName(){person.name ~}function changeAge(){person.age 1}function changePerson(){Object.assign(person,{name:李四,age:80})}function test(){obj.a.b.c 888}// 监视情况三监视【reactive】定义的【对象类型】数据且默认是开启深度监视的watch(person,(newValue,oldValue){console.log(person变化了,newValue,oldValue)})watch(obj,(newValue,oldValue){console.log(Obj变化了,newValue,oldValue)}) /script* 情况四 监视ref或reactive定义的【对象类型】数据中的某个属性注意点如下 若该属性值不是【对象类型】需要写成函数形式。若该属性值是依然是【对象类型】可直接编也可写成函数建议写成函数。 结论监视的要是对象里的属性那么最好写函数式注意点若是对象监视的是地址值需要关注对象内部需要手动开启深度监视。 templatediv classpersonh1情况四监视【ref】或【reactive】定义的【对象类型】数据中的某个属性/h1h2姓名{{ person.name }}/h2h2年龄{{ person.age }}/h2h2汽车{{ person.car.c1 }}、{{ person.car.c2 }}/h2button clickchangeName修改名字/buttonbutton clickchangeAge修改年龄/buttonbutton clickchangeC1修改第一台车/buttonbutton clickchangeC2修改第二台车/buttonbutton clickchangeCar修改整个车/button/div /templatescript langts setup namePersonimport {reactive,watch} from vue// 数据let person reactive({name:张三,age:18,car:{c1:奔驰,c2:宝马}})// 方法function changeName(){person.name ~}function changeAge(){person.age 1}function changeC1(){person.car.c1 奥迪}function changeC2(){person.car.c2 大众}function changeCar(){person.car {c1:雅迪,c2:爱玛}}// 监视情况四监视响应式对象中的某个属性且该属性是基本类型的要写成函数式/* watch(() person.name,(newValue,oldValue){console.log(person.name变化了,newValue,oldValue)}) */// 监视情况四监视响应式对象中的某个属性且该属性是对象类型的可以直接写也能写函数更推荐写函数watch(()person.car,(newValue,oldValue){console.log(person.car变化了,newValue,oldValue)},{deep:true}) /script* 情况五 监视上述的多个数据 templatediv classpersonh1情况五监视上述的多个数据/h1h2姓名{{ person.name }}/h2h2年龄{{ person.age }}/h2h2汽车{{ person.car.c1 }}、{{ person.car.c2 }}/h2button clickchangeName修改名字/buttonbutton clickchangeAge修改年龄/buttonbutton clickchangeC1修改第一台车/buttonbutton clickchangeC2修改第二台车/buttonbutton clickchangeCar修改整个车/button/div /templatescript langts setup namePersonimport {reactive,watch} from vue// 数据let person reactive({name:张三,age:18,car:{c1:奔驰,c2:宝马}})// 方法function changeName(){person.name ~}function changeAge(){person.age 1}function changeC1(){person.car.c1 奥迪}function changeC2(){person.car.c2 大众}function changeCar(){person.car {c1:雅迪,c2:爱玛}}// 监视情况五监视上述的多个数据watch([()person.name,person.car],(newValue,oldValue){console.log(person.car变化了,newValue,oldValue)},{deep:true})/script10. watchEffect 官网立即运行一个函数同时响应式地追踪其依赖并在依赖更改时重新执行该函数。 watch对比watchEffect 都能监听响应式数据的变化不同的是监听数据变化的方式不同 watch要明确指出监视的数据 watchEffect不用明确指出监视的数据函数中用到哪些属性那就监视哪些属性。 示例代码 templatediv classpersonh1需求水温达到50℃或水位达到20cm则联系服务器/h1h2 iddemo水温{{temp}}/h2h2水位{{height}}/h2button clickchangePrice水温1/buttonbutton clickchangeSum水位10/button/div /templatescript langts setup namePersonimport {ref,watch,watchEffect} from vue// 数据let temp ref(0)let height ref(0)// 方法function changePrice(){temp.value 10}function changeSum(){height.value 1}// 用watch实现需要明确的指出要监视temp、heightwatch([temp,height],(value){// 从value中获取最新的temp值、height值const [newTemp,newHeight] value// 室温达到50℃或水位达到20cm立刻联系服务器if(newTemp 50 || newHeight 20){console.log(联系服务器)}})// 用watchEffect实现不用const stopWtach watchEffect((){// 室温达到50℃或水位达到20cm立刻联系服务器if(temp.value 50 || height.value 20){console.log(document.getElementById(demo)?.innerText)console.log(联系服务器)}// 水温达到100或水位达到50取消监视if(temp.value 100 || height.value 50){console.log(清理了)stopWtach()}}) /script11. 标签的 ref 属性 作用用于注册模板引用。 用在普通DOM标签上获取的是DOM节点。 用在组件标签上获取的是组件实例对象。 用在普通DOM标签上 templatediv classpersonh1 reftitle1尚硅谷/h1h2 reftitle2前端/h2h3 reftitle3Vue/h3input typetext refinpt brbrbutton clickshowLog点我打印内容/button/div /templatescript langts setup namePersonimport {ref} from vuelet title1 ref()let title2 ref()let title3 ref()function showLog(){// 通过id获取元素const t1 document.getElementById(title1)// 打印内容console.log((t1 as HTMLElement).innerText)console.log((HTMLElementt1).innerText)console.log(t1?.innerText)/************************************/// 通过ref获取元素console.log(title1.value)console.log(title2.value)console.log(title3.value)} /script用在组件标签上 !-- 父组件App.vue -- templatePerson refren/button clicktest测试/button /templatescript langts setup nameAppimport Person from ./components/Person.vueimport {ref} from vuelet ren ref()function test(){console.log(ren.value.name)console.log(ren.value.age)} /script!-- 子组件Person.vue中要使用defineExpose暴露内容 -- script langts setup namePersonimport {ref,defineExpose} from vue// 数据let name ref(张三)let age ref(18)/****************************//****************************/// 使用defineExpose将组件中的数据交给外部defineExpose({name,age}) /script12. props // 定义一个接口限制每个Person对象的格式 export interface PersonInter {id:string,name:string,age:number}// 定义一个自定义类型Persons export type Persons ArrayPersonInterApp.vue中代码 templatePerson :listpersons/ /templatescript langts setup nameAppimport Person from ./components/Person.vueimport {reactive} from vueimport {type Persons} from ./typeslet persons reactivePersons([{id:e98219e12,name:张三,age:18},{id:e98219e13,name:李四,age:19},{id:e98219e14,name:王五,age:20}])/script Person.vue中代码 template div classpersonulli v-foritem in list :keyitem.id{{item.name}}--{{item.age}}/li/ul/div/templatescript langts setup namePerson import {defineProps} from vue import {type PersonInter} from /types// 第一种写法仅接收 // const props defineProps([list])// 第二种写法接收限制类型 // defineProps{list:Persons}()// 第三种写法接收限制类型指定默认值限制必要性 let props withDefaults(defineProps{list?:Persons}(),{list:()[{id:asdasg01,name:小猪佩奇,age:18}]})console.log(props)/script13. 生命周期 概念Vue组件实例在创建时要经历一系列的初始化步骤在此过程中Vue会在合适的时机调用特定的函数从而让开发者有机会在特定阶段运行自己的代码这些特定的函数统称为生命周期钩子 规律 生命周期整体分为四个阶段分别是创建、挂载、更新、销毁每个阶段都有两个钩子一前一后。 Vue2的生命周期 创建阶段beforeCreate、created 挂载阶段beforeMount、mounted 更新阶段beforeUpdate、updated 销毁阶段beforeDestroy、destroyed Vue3的生命周期 创建阶段setup 挂载阶段onBeforeMount、onMounted 更新阶段onBeforeUpdate、onUpdated 卸载阶段onBeforeUnmount、onUnmounted 常用的钩子onMounted(挂载完毕)、onUpdated(更新完毕)、onBeforeUnmount(卸载之前) 示例代码 templatediv classpersonh2当前求和为{{ sum }}/h2button clickchangeSum点我sum1/button/div /template!-- vue3写法 -- script langts setup namePersonimport { ref, onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted } from vue// 数据let sum ref(0)// 方法function changeSum() {sum.value 1}console.log(setup)// 生命周期钩子onBeforeMount((){console.log(挂载之前)})onMounted((){console.log(挂载完毕)})onBeforeUpdate((){console.log(更新之前)})onUpdated((){console.log(更新完毕)})onBeforeUnmount((){console.log(卸载之前)})onUnmounted((){console.log(卸载完毕)}) /script14. 自定义hook 什么是hook—— 本质是一个函数把setup函数中使用的Composition API进行了封装类似于vue2.x中的mixin。 自定义hook的优势复用代码, 让setup中的逻辑更清楚易懂。 示例代码 useSum.ts中内容如下 import {ref,onMounted} from vueexport default function(){let sum ref(0)const increment (){sum.value 1}const decrement (){sum.value - 1}onMounted((){increment()})//向外部暴露数据return {sum,increment,decrement} } useDog.ts中内容如下 import {reactive,onMounted} from vue import axios,{AxiosError} from axiosexport default function(){let dogList reactivestring[]([])// 方法async function getDog(){try {// 发请求let {data} await axios.get(https://dog.ceo/api/breed/pembroke/images/random)// 维护数据dogList.push(data.message)} catch (error) {// 处理错误const err AxiosErrorerrorconsole.log(err.message)}}// 挂载钩子onMounted((){getDog()})//向外部暴露数据return {dogList,getDog} }组件中具体使用 templateh2当前求和为{{sum}}/h2button clickincrement点我1/buttonbutton clickdecrement点我-1/buttonhrimg v-for(u,index) in dogList.urlList :keyindex :src(u as string) span v-showdogList.isLoading加载中....../spanbrbutton clickgetDog再来一只狗/button /templatescript langtsimport {defineComponent} from vueexport default defineComponent({name:App,}) /scriptscript setup langtsimport useSum from ./hooks/useSumimport useDog from ./hooks/useDoglet {sum,increment,decrement} useSum()let {dogList,getDog} useDog() /script四、 路由 1. 对路由的理解 2. 基本切换效果 Vue3中要使用vue-router的最新版本目前是4版本。 路由配置文件代码如下 import {createRouter,createWebHistory} from vue-router import Home from /pages/Home.vue import News from /pages/News.vue import About from /pages/About.vueconst router createRouter({history:createWebHistory(),routes:[{path:/home,component:Home},{path:/about,component:About}] }) export default routermain.ts代码如下 import router from ./router/index app.use(router)app.mount(#app)App.vue代码如下 templatediv classapph2 classtitleVue路由测试/h2!-- 导航区 --div classnavigateRouterLink to/home active-classactive首页/RouterLinkRouterLink to/news active-classactive新闻/RouterLinkRouterLink to/about active-classactive关于/RouterLink/div!-- 展示区 --div classmain-contentRouterView/RouterView/div/div /templatescript langts setup nameAppimport {RouterLink,RouterView} from vue-router /script3. 两个注意点 路由组件通常存放在pages 或 views文件夹一般组件通常存放在components文件夹。 通过点击导航视觉效果上“消失” 了的路由组件默认是被卸载掉的需要的时候再去挂载。 4. 路由器工作模式 history模式 优点URL更加美观不带有#更接近传统的网站URL。 缺点后期项目上线需要服务端配合处理路径问题否则刷新会有404错误。 const router createRouter({history:createWebHistory(), //history模式/******/ })hash模式 优点兼容性更好因为不需要服务器端处理路径。 缺点URL带有#不太美观且在SEO优化方面相对较差。 const router createRouter({history:createWebHashHistory(), //hash模式/******/ })5. to的两种写法 !-- 第一种to的字符串写法 -- router-link active-classactive to/home主页/router-link!-- 第二种to的对象写法 -- router-link active-classactive :to{path:/home}Home/router-link6. 命名路由 作用可以简化路由跳转及传参后面就讲。 给路由规则命名 routes:[{name:zhuye,path:/home,component:Home},{name:xinwen,path:/news,component:News,},{name:guanyu,path:/about,component:About} ]跳转路由 !--简化前需要写完整的路径to的字符串写法 -- router-link to/news/detail跳转/router-link!--简化后直接通过名字跳转to的对象写法配合name属性 -- router-link :to{name:guanyu}跳转/router-link7. 嵌套路由 编写News的子路由Detail.vue 配置路由规则使用children配置项 const router createRouter({history:createWebHistory(),routes:[{name:zhuye,path:/home,component:Home},{name:xinwen,path:/news,component:News,children:[{name:xiang,path:detail,component:Detail}]},{name:guanyu,path:/about,component:About}] }) export default router跳转路由记得要加完整路径 router-link to/news/detailxxxx/router-link !-- 或 -- router-link :to{path:/news/detail}xxxx/router-link记得去Home组件中预留一个router-view templatediv classnewsnav classnews-listRouterLink v-fornews in newsList :keynews.id :to{path:/news/detail}{{news.name}}/RouterLink/navdiv classnews-detailRouterView//div/div /template8. 路由传参 1query参数 传递参数 !-- 跳转并携带query参数to的字符串写法 -- router-link to/news/detail?a1b2content欢迎你跳转 /router-link!-- 跳转并携带query参数to的对象写法 -- RouterLink :to{//name:xiang, //用name也可以跳转path:/news/detail,query:{id:news.id,title:news.title,content:news.content}} {{news.title}} /RouterLink接收参数 import {useRoute} from vue-router const route useRoute() // 打印query参数 console.log(route.query)2params参数 传递参数 !-- 跳转并携带params参数to的字符串写法 -- RouterLink :to/news/detail/001/新闻001/内容001{{news.title}}/RouterLink!-- 跳转并携带params参数to的对象写法 -- RouterLink :to{name:xiang, //用name跳转params:{id:news.id,title:news.title,content:news.title}} {{news.title}} /RouterLink接收参数 import {useRoute} from vue-router const route useRoute() // 打印params参数 console.log(route.params)备注1传递params参数时若使用to的对象写法必须使用name配置项不能用path。 备注2传递params参数时需要提前在规则中占位。 9. 路由的props配置 作用让路由组件更方便的收到参数可以将路由参数作为props传给组件 {name:xiang,path:detail/:id/:title/:content,component:Detail,// props的对象写法作用把对象中的每一组key-value作为props传给Detail组件// props:{a:1,b:2,c:3}, // props的布尔值写法作用把收到了每一组params参数作为props传给Detail组件// props:true// props的函数写法作用把返回的对象中每一组key-value作为props传给Detail组件props(route){return route.query} }10.  replace属性 作用控制路由跳转时操作浏览器历史记录的模式。 浏览器的历史记录有两种写入方式分别为push和replace push是追加历史记录默认值。replace是替换当前记录。 开启replace模式 RouterLink replace .......News/RouterLink11. 编程式导航 路由组件的两个重要的属性$route和$router变成了两个hooks import {useRoute,useRouter} from vue-routerconst route useRoute() const router useRouter()console.log(route.query) console.log(route.parmas) console.log(router.push) console.log(router.replace)12. 重定向 作用将特定的路径重新定向到已有路由。 具体编码 {path:/,redirect:/about }五、pinia 1. 准备一个效果 2.搭建 pinia 环境 第一步npm install pinia 第二步操作src/main.ts import { createApp } from vue import App from ./App.vue/* 引入createPinia用于创建pinia */ import { createPinia } from pinia/* 创建pinia */ const pinia createPinia() const app createApp(App)/* 使用插件 */{} app.use(pinia) app.mount(#app)此时开发者工具中已经有了pinia选项 3.存储读取数据 Store是一个保存状态、业务逻辑 的实体每个组件都可以读取、写入它。 它有三个概念state、getter、action相当于组件中的 data、 computed 和 methods。 具体编码src/store/count.ts // 引入defineStore用于创建store import {defineStore} from pinia// 定义并暴露一个store export const useCountStore defineStore(count,{// 动作actions:{},// 状态state(){return {sum:6}},// 计算getters:{} })具体编码src/store/talk.ts // 引入defineStore用于创建store import {defineStore} from pinia// 定义并暴露一个store export const useTalkStore defineStore(talk,{// 动作actions:{},// 状态state(){return {talkList:[{id:yuysada01,content:你今天有点怪哪里怪怪好看的},{id:yuysada02,content:草莓、蓝莓、蔓越莓你想我了没},{id:yuysada03,content:心里给你留了一块地我的死心塌地}]}},// 计算getters:{} })组件中使用state中的数据 templateh2当前求和为{{ sumStore.sum }}/h2 /templatescript setup langts nameCount// 引入对应的useXxxxxStore import {useSumStore} from /store/sum// 调用useXxxxxStore得到对应的storeconst sumStore useSumStore() /scripttemplateulli v-fortalk in talkStore.talkList :keytalk.id{{ talk.content }}/li/ul /templatescript setup langts nameCountimport axios from axiosimport {useTalkStore} from /store/talkconst talkStore useTalkStore() /script4. 修改数据(三种方式) 第一种修改方式直接修改 countStore.sum 666第二种修改方式批量修改 countStore.$patch({sum:999,school:atguigu })第三种修改方式借助action修改action中可以编写一些业务逻辑 import { defineStore } from piniaexport const useCountStore defineStore(count, {/*************/actions: {//加increment(value:number) {if (this.sum 10) {//操作countStore中的sumthis.sum value}},//减decrement(value:number){if(this.sum 1){this.sum - value}}},/*************/ })组件中调用action即可 // 使用countStore const countStore useCountStore()// 调用对应action countStore.incrementOdd(n.value)5. storeToRefs 借助storeToRefs将store中的数据转为ref对象方便在模板中使用。注意pinia提供的storeToRefs只会将数据做转换而Vue的toRefs会转换store中数据。 templatediv classcounth2当前求和为{{sum}}/h2/div /templatescript setup langts nameCountimport { useCountStore } from /store/count/* 引入storeToRefs */import { storeToRefs } from pinia/* 得到countStore */const countStore useCountStore()/* 使用storeToRefs转换countStore随后解构 */const {sum} storeToRefs(countStore) /script 6. getters 概念当state中的数据需要经过处理后再使用时可以使用getters配置。 追加getters配置。 // 引入defineStore用于创建store import {defineStore} from pinia// 定义并暴露一个store export const useCountStore defineStore(count,{// 动作actions:{/************/},// 状态state(){return {sum:1,school:atguigu}},// 计算getters:{bigSum:(state):number state.sum *10,upperSchool():string{return this. school.toUpperCase()}} })组件中读取数据 const {increment,decrement} countStore let {sum,school,bigSum,upperSchool} storeToRefs(countStore)7. $subscribe 通过 store 的 $subscribe() 方法侦听 state 及其变化 talkStore.$subscribe((mutate,state){console.log(LoveTalk,mutate,state)localStorage.setItem(talk,JSON.stringify(talkList.value)) })8. store组合式写法 import {defineStore} from pinia import axios from axios import {nanoid} from nanoid import {reactive} from vueexport const useTalkStore defineStore(talk,(){// talkList就是stateconst talkList reactive(JSON.parse(localStorage.getItem(talkList) as string) || [])// getATalk函数相当于actionasync function getATalk(){// 发请求下面这行的写法是连续解构赋值重命名let {data:{content:title}} await axios.get(https://api.uomg.com/api/rand.qinghua?formatjson)// 把请求回来的字符串包装成一个对象let obj {id:nanoid(),title}// 放到数组中talkList.unshift(obj)}return {talkList,getATalk} })六、组件通信 Vue3组件通信和Vue2的区别 移出事件总线使用mitt代替。 vuex换成了pinia。把.sync优化到了v-model里面了。把$listeners所有的东西合并到$attrs中了。$children被砍掉了。 常见搭配形式 1. props 概述props是使用频率最高的一种通信方式常用与 父 ↔ 子。 若 父传子属性值是非函数。若 子传父属性值是函数。 父组件 templatediv classfatherh3父组件/h3h4我的车{{ car }}/h4h4儿子给的玩具{{ toy }}/h4Child :carcar :getToygetToy//div /templatescript setup langts nameFatherimport Child from ./Child.vueimport { ref } from vue;// 数据const car ref(奔驰)const toy ref()// 方法function getToy(value:string){toy.value value} /script子组件 templatediv classchildh3子组件/h3h4我的玩具{{ toy }}/h4h4父给我的车{{ car }}/h4button clickgetToy(toy)玩具给父亲/button/div /templatescript setup langts nameChildimport { ref } from vue;const toy ref(奥特曼)defineProps([car,getToy]) /script2. 自定义事件 概述自定义事件常用于子 父。注意区分好原生事件、自定义事件。 原生事件 事件名是特定的click、mosueenter等等事件对象$event: 是包含事件相关信息的对象pageX、pageY、target、keyCode自定义事件 事件名是任意名称事件对象$event: 是调用emit时所提供的数据可以是任意类型 示例 !--在父组件中给子组件绑定自定义事件-- Child send-toytoy $event/!--注意区分原生事件与自定义事件中的$event-- button clicktoy $event测试/button//子组件中触发事件 this.$emit(send-toy, 具体数据)3. mitt 概述与消息订阅与发布pubsub功能类似可以实现任意组件间通信。 安装mitt npm i mitt新建文件src\utils\emitter.ts // 引入mitt import mitt from mitt;// 创建emitter const emitter mitt()/*// 绑定事件emitter.on(abc,(value){console.log(abc事件被触发,value)})emitter.on(xyz,(value){console.log(xyz事件被触发,value)})setInterval(() {// 触发事件emitter.emit(abc,666)emitter.emit(xyz,777)}, 1000);setTimeout(() {// 清理事件emitter.all.clear()}, 3000); */// 创建并暴露mitt export default emitter接收数据的组件中绑定事件、同时在销毁前解绑事件 import emitter from /utils/emitter; import { onUnmounted } from vue;// 绑定事件 emitter.on(send-toy,(value){console.log(send-toy事件被触发,value) })onUnmounted((){// 解绑事件emitter.off(send-toy) })【第三步】提供数据的组件在合适的时候触发事件 import emitter from /utils/emitter;function sendToy(){// 触发事件emitter.emit(send-toy,toy.value) }注意这个重要的内置关系总线依赖着这个内置关系 4. v-model 概述实现 父↔子 之间相互通信。 前序知识 —— v-model的本质 !-- 使用v-model指令 -- input typetext v-modeluserName!-- v-model的本质是下面这行代码 -- input typetext :valueuserName inputuserName (HTMLInputElement$event.target).value组件标签上的v-model的本质:moldeValue  update:modelValue事件。 !-- 组件标签上使用v-model指令 -- AtguiguInput v-modeluserName/!-- 组件标签上v-model的本质 -- AtguiguInput :modelValueuserName update:model-valueuserName $event/AtguiguInput组件中 templatediv classbox!--将接收的value值赋给input元素的value属性目的是为了呈现数据 --!--给input元素绑定原生input事件触发input事件时进而触发update:model-value事件--input typetext :valuemodelValue inputemit(update:model-value,$event.target.value)/div /templatescript setup langts nameAtguiguInput// 接收propsdefineProps([modelValue])// 声明事件const emit defineEmits([update:model-value]) /script也可以更换value例如改成abc !-- 也可以更换value例如改成abc-- AtguiguInput v-model:abcuserName/!-- 上面代码的本质如下 -- AtguiguInput :abcuserName update:abcuserName $event/AtguiguInput组件中 templatediv classboxinput typetext :valueabc inputemit(update:abc,$event.target.value)/div /templatescript setup langts nameAtguiguInput// 接收propsdefineProps([abc])// 声明事件const emit defineEmits([update:abc]) /script如果value可以更换那么就可以在组件标签上多次使用v-model AtguiguInput v-model:abcuserName v-model:xyzpassword/5. $attrs  概述$attrs用于实现当前组件的父组件向当前组件的子组件通信祖→孙。 具体说明$attrs是一个对象包含所有父组件传入的标签属性。 注意$attrs会自动排除props中声明的属性(可以认为声明过的 props 被子组件自己“消费”了) 父组件 templatediv classfatherh3父组件/h3Child :aa :bb :cc :dd v-bind{x:100,y:200} :updateAupdateA//div /templatescript setup langts nameFatherimport Child from ./Child.vueimport { ref } from vue;let a ref(1)let b ref(2)let c ref(3)let d ref(4)function updateA(value){a.value value} /script子组件 templatediv classchildh3子组件/h3GrandChild v-bind$attrs//div /templatescript setup langts nameChildimport GrandChild from ./GrandChild.vue /script孙组件 templatediv classgrand-childh3孙组件/h3h4a{{ a }}/h4h4b{{ b }}/h4h4c{{ c }}/h4h4d{{ d }}/h4h4x{{ x }}/h4h4y{{ y }}/h4button clickupdateA(666)点我更新A/button/div /templatescript setup langts nameGrandChilddefineProps([a,b,c,d,x,y,updateA]) /script6. refs、parent 概述 $refs用于 父→子。$parent用于子→父。 原理如下 属性说明$refs值为对象包含所有被ref属性标识的DOM元素或组件实例。$parent值为对象当前组件的父组件实例对象。 7. provide、inject 概述实现祖孙组件直接通信 具体使用 在祖先组件中通过provide配置向后代组件提供数据在后代组件中通过inject配置来声明接收数据 具体编码 【第一步】父组件中使用provide提供数据 templatediv classfatherh3父组件/h3h4资产{{ money }}/h4h4汽车{{ car }}/h4button clickmoney 1资产1/buttonbutton clickcar.price 1汽车价格1/buttonChild//div /templatescript setup langts nameFatherimport Child from ./Child.vueimport { ref,reactive,provide } from vue;// 数据let money ref(100)let car reactive({brand:奔驰,price:100})// 用于更新money的方法function updateMoney(value:number){money.value value}// 提供数据provide(moneyContext,{money,updateMoney})provide(car,car) /script注意子组件中不用编写任何东西是不受到任何打扰的 【第二步】孙组件中使用inject配置项接受数据。 templatediv classgrand-childh3我是孙组件/h3h4资产{{ money }}/h4h4汽车{{ car }}/h4button clickupdateMoney(6)点我/button/div /templatescript setup langts nameGrandChildimport { inject } from vue;// 注入数据let {money,updateMoney} inject(moneyContext,{money:0,updateMoney:(x:number){}})let car inject(car)8. pinia 参考之前pinia部分的讲解 9. slot 1默认插槽 父组件中Category title今日热门游戏ulli v-forg in games :keyg.id{{ g.name }}/li/ul/Category 子组件中templatediv classitemh3{{ title }}/h3!-- 默认插槽 --slot/slot/div/template2具名插槽 父组件中Category title今日热门游戏template v-slot:s1ulli v-forg in games :keyg.id{{ g.name }}/li/ul/templatetemplate #s2a href更多/a/template/Category 子组件中templatediv classitemh3{{ title }}/h3slot names1/slotslot names2/slot/div/template3作用域插槽 理解数据在组件的自身但根据数据生成的结构需要组件的使用者来决定。新闻数据在News组件中但使用数据所遍历出来的结构由App组件决定 具体编码 父组件中Game v-slotparams!-- Game v-slot:defaultparams --!-- Game #defaultparams --ulli v-forg in params.games :keyg.id{{ g.name }}/li/ul/Game子组件中templatediv classcategoryh2今日游戏榜单/h2slot :gamesgames a哈哈/slot/div/templatescript setup langts nameCategoryimport {reactive} from vuelet games reactive([{id:asgdytsa01,name:英雄联盟},{id:asgdytsa02,name:王者荣耀},{id:asgdytsa03,name:红色警戒},{id:asgdytsa04,name:斗罗大陆}])/script七、 其它 API 1. shallowRef 与 shallowReactive  1shallowRef 作用创建一个响应式数据但只对顶层属性进行响应式处理。 用法 let myVar shallowRef(initialValue);特点只跟踪引用值的变化不关心值内部的属性变化。 2shallowReactive 作用创建一个浅层响应式对象只会使对象的最顶层属性变成响应式的对象内部的嵌套属性则不会变成响应式的 用法 const myObj shallowReactive({ ... });特点对象的顶层属性是响应式的但嵌套对象的属性不是。 总结 通过使用 shallowRef() 和 shallowReactive() 来绕开深度响应。浅层式 API 创建的状态只在其顶层是响应式的对所有深层的对象不会做任何处理避免了对每一个内部属性做响应式所带来的性能成本这使得属性的访问变得更快可提升性能。 2. readonly 与 shallowReadonly 1readonly 作用用于创建一个对象的深只读副本。 用法 const original reactive({ ... }); const readOnlyCopy readonly(original);特点 对象的所有嵌套属性都将变为只读。任何尝试修改这个对象的操作都会被阻止在开发模式下还会在控制台中发出警告。 应用场景 创建不可变的状态快照。保护全局状态或配置不被修改。 2shallowReadonly 作用与 readonly 类似但只作用于对象的顶层属性。 用法 const original reactive({ ... }); const shallowReadOnlyCopy shallowReadonly(original);特点 只将对象的顶层属性设置为只读对象内部的嵌套属性仍然是可变的。 适用于只需保护对象顶层属性的场景。 3. toRaw 与 markRaw 1toRaw 作用用于获取一个响应式对象的原始对象 toRaw 返回的对象不再是响应式的不会触发视图更新。 官网描述这是一个可以用于临时读取而不引起代理访问/跟踪开销或是写入而不触发更改的特殊方法。不建议保存对原始对象的持久引用请谨慎使用。 何时使用 —— 在需要将响应式对象传递给非 Vue 的库或外部系统时使用 toRaw 可以确保它们收到的是普通对象 具体编码 import { reactive,toRaw,markRaw,isReactive } from vue;/* toRaw */ // 响应式对象 let person reactive({name:tony,age:18}) // 原始对象 let rawPerson toRaw(person)/* markRaw */ let citysd markRaw([{id:asdda01,name:北京},{id:asdda02,name:上海},{id:asdda03,name:天津},{id:asdda04,name:重庆} ]) // 根据原始对象citys去创建响应式对象citys2 —— 创建失败因为citys被markRaw标记了 let citys2 reactive(citys) console.log(isReactive(person)) console.log(isReactive(rawPerson)) console.log(isReactive(citys)) console.log(isReactive(citys2))2markRaw 作用标记一个对象使其永远不会变成响应式的。 例如使用mockjs时为了防止误把mockjs变为响应式对象可以使用 markRaw 去标记mockjs 编码 /* markRaw */ let citys markRaw([{id:asdda01,name:北京},{id:asdda02,name:上海},{id:asdda03,name:天津},{id:asdda04,name:重庆} ]) // 根据原始对象citys去创建响应式对象citys2 —— 创建失败因为citys被markRaw标记了 let citys2 reactive(citys)4. customRef 作用创建一个自定义的ref并对其依赖项跟踪和更新触发进行逻辑控制。 实现防抖效果useSumRef.ts import {customRef } from vue;export default function(initValue:string,delay:number){let msg customRef((track,trigger){let timer:numberreturn {get(){track() // 告诉Vue数据msg很重要要对msg持续关注一旦变化就更新return initValue},set(value){clearTimeout(timer)timer setTimeout(() {initValue valuetrigger() //通知Vue数据msg变化了}, delay);}}}) return {msg} }组件中使用 八、Vue3新组件 1. Teleport 什么是Teleport—— Teleport 是一种能够将我们的组件html结构移动到指定位置的技术。 teleport tobody div classmodal v-showisShowh2我是一个弹窗/h2p我是弹窗中的一些内容/pbutton clickisShow false关闭弹窗/button/div /teleport2. Suspense 等待异步组件时渲染一些额外内容让应用有更好的用户体验使用步骤 异步引入组件使用Suspense包裹组件并配置好default 与 fallback import { defineAsyncComponent,Suspense } from vue; const Child defineAsyncComponent(()import(./Child.vue))templatediv classapph3我是App组件/h3Suspensetemplate v-slot:defaultChild//templatetemplate v-slot:fallbackh3加载中......./h3/template/Suspense/div /template3. 全局API转移到应用对象 app.componentapp.configapp.directiveapp.mountapp.unmountapp.use 4. 其他 过渡类名 v-enter 修改为 v-enter-from、过渡类名 v-leave 修改为 v-leave-from。 keyCode 作为 v-on 修饰符的支持。 v-model 指令在组件上的使用已经被重新设计替换掉了 v-bind.sync。 v-if 和 v-for 在同一个元素身上使用时的优先级发生了变化。 移除了$on、$off 和 $once 实例方法。 移除了过滤器 filter。 移除了$children 实例 propert。
http://www.pierceye.com/news/548835/

相关文章:

  • 网上手机网站建设计划书百度小说风云榜排名
  • 用js来做网站帝国cms这么做网站
  • 网站建设需求分析班级网站备案服务类型
  • 网站备案幕布照片怎么算合格北京专业网站开发
  • 浙江建设职业技术学院塘栖校区网站网络推广方法有几种
  • 呢图网站场建设封面长安镇做网站
  • 搜索关键词的网站黄山做网站
  • 网络建站系统去除wordpress主题头部作者信息
  • 鼓楼微网站开发番禺有经验的网站建设
  • 对网站建设心得进入公众号继续阅读怎么弄
  • 网站建设公司投诉电话可以先做网站后备案吗
  • 顺的品牌网站设计价位网站开发合同书
  • 用html5制作个人网站深圳百度国际大厦
  • 网络网站公司网站管理平台扩展插件
  • 个人小说网站怎么做把自己做的网页变成网站
  • led网站制作网站登录后不显示内容
  • 推广网站公司兴义市住房和城乡建设局网站
  • 营销网站建设的公司哪家好创建网站超链接
  • 苏州网站优化排名推广企业网站建设价格
  • 在线制作论坛网站wordpress建立好的网站
  • 网站的功能规范商城网站静态模板下载
  • 双语言网站源码制作网页的软件哪个好
  • 政务网站建设需求网站首页页面代码
  • 网站产品详情页怎么做的用服务器做网站空间
  • 河北网站制作报价长春市建设技工学校网站
  • 盘锦做网站专家常州网站建设企业网站制作
  • 关于建设网站的报告wordpress 视频 广告插件
  • 生态养殖网站模板网赌网站建设多少钱
  • wordpress is长沙百度提升优化
  • 福州网站建设哪个好网页被禁止浏览怎么解决