前端網(wǎng)站搜索導(dǎo)航怎么做網(wǎng)站搜索引擎優(yōu)化診斷
一、ref
1.ref引用
每個vue組件實例上,都包含一個$refs對象,里面存儲著對應(yīng)dom元素或組件的引用。默認(rèn)情況下,組件的$refs指向一個空對象。
2.使用ref獲取dom元素的引用
<template><h3 ref="myh3">ref組件</h3><button @click="getRef">getRef</button>
</template>
<script>
export default{methods:{getRef(){console.log('this',this.$refs);this.$refs.myh3.style.color='red'}}
}
</script>
3.使用ref引用組件實例
<template><MyIndex ref="myIndexRef"></MyIndex><button @click="getRef">getRef</button>
</template>
<script>
import MyIndex from './index copy.vue';
export default{components:{MyIndex},methods:{getRef(){console.log('this',this.$refs);this.$refs.myIndexRef.reset()}}
}
</script><template><div>{{count}}<button @click="this.count+=1">按鈕</button></div>
</template>
<script>
export default{data(){return{count:1}},methods:{reset(){this.count=0}}
}
</script>
4.控制文本框和按鈕的按需切換
<template><input type="text" v-if="inputVisible" ref="ipt"><button v-else @click="showInput">getRef</button>
</template>
<script>
export default{data(){return{inputVisible:false}},methods:{showInput(){this.inputVisible=true;//獲取文本框的引用對象,訪問的ipt是undefind,dom更新是異步的,拿不到最新domthis.$nextTick(()=>{this.$refs.ipt.focus();})}}
}
</script>
5.組件是異步執(zhí)行dom更新的
6.this.$nextTick(cb)
組件的$nextTick(cb)方法,會把cb回調(diào)推遲到下一個dom更新周期之后執(zhí)行。簡單理解:等組件的dom異步地重新渲染完成后,再執(zhí)行cb回調(diào)函數(shù)。從而能保證cb回調(diào)函數(shù)可以操作到最新的dom元素。
二、動態(tài)組件
1.什么是動態(tài)組件
動態(tài)組件時動態(tài)切換組建的顯示與隱藏。vue提供了一個<component>組件,專門用來實現(xiàn)組件的動態(tài)渲染。
a.<component>是組件的占位符
b.通過is屬性動態(tài)指定要渲染的組件名稱
c.<component is="要渲染的組件名稱"></component>
2.如何實現(xiàn)動態(tài)組件渲染
<template><button @click="comName='Home'">首頁</button><button @click="comName='Movie'">電影</button><hr><component :is='comName'></component>
</template>
<script>
import Home from './home.vue'
import Movie from './movie.vue'
export default{components:{Home,Movie},data(){return{comName:'Home'}}
}
</script>
3.使用keep-alive保持組件的狀態(tài)
默認(rèn)情況下,動態(tài)切換組件時無法保持組件的狀態(tài)。可以使用vue內(nèi)置的<keep-alive>組件保持動態(tài)組件的狀態(tài)。
<template><button @click="comName='Home'">首頁</button><button @click="comName='Movie'">電影</button><hr><keep-alive><component :is='comName'></component></keep-alive>
</template>
<script>
import Home from './home.vue'
import Movie from './movie.vue'
export default{components:{Home,Movie},data(){return{comName:'Home'}}
}
</script><template><div>Home組件{{ count }}<button @click="count+=1">+1</button></div>
</template>
<script>
export default{data(){return{count:1}},created(){console.log('created');},unmounted(){console.log('unmounted');},
}
</script>
三、插槽
1.什么是插槽
插槽是vue組件為組件的封裝者提供的能力。允許開發(fā)者在封裝組件時,把不確定、希望由用戶指定的部分定義為插槽。
可以把插槽認(rèn)為是組件封裝期間,為用戶預(yù)留的內(nèi)容占位符。
沒有預(yù)留插槽的內(nèi)容會被丟棄
<template><Home><p>-------------</p></Home>
</template>
<script>
import Home from './home.vue'
export default{components:{Home},
}
</script><template><div>Home組件<p>p1p1p1p1p1p1p1p1p1p1p1p1p1</p><slot></slot><p>p2p2p2p2p2p2p2p2p2p2p2p2p2</p></div>
</template>
2.后備內(nèi)容(默認(rèn)內(nèi)容)
封裝組件時,可以為預(yù)留的<slot>插槽提供后備內(nèi)容(默認(rèn)內(nèi)容)。如果組件的使用者沒有為插槽提供任何內(nèi)容,則后備內(nèi)容會生效。
<template><Home><!-- <p>-------------</p> --></Home>
</template>
<script>
import Home from './home.vue'
export default{components:{Home},
}
</script><template><div>Home組件<p>p1p1p1p1p1p1p1p1p1p1p1p1p1</p><slot>默認(rèn)xxxxxxxx</slot><p>p2p2p2p2p2p2p2p2p2p2p2p2p2</p></div>
</template>
3.具名插槽
如果在封裝組件時需要預(yù)留多個插槽節(jié)點(diǎn),則需要為每個<slot>插槽指定具體的name名稱。這種帶有具體名稱的插槽叫做“具名插槽”。
v-slot:可以簡寫為字符#
<template><Home><!-- v-slot:可簡寫為# --><template v-slot:header>頭部</template><p>-------------</p><template #footer>底部</template></Home>
</template>
<script>
import Home from './home.vue'
export default{components:{Home},
}
</script><template><div>Home組件<slot name="header"></slot><slot>默認(rèn)xxxxxxxx</slot><slot name="footer"></slot></div>
</template>
4.作用域插槽
在封裝組件的過程中,可以為預(yù)留的<slot>插槽綁定props數(shù)據(jù),這種帶有props數(shù)據(jù)的<slot>插槽叫做作用域插槽。
<template><Home><template v-slot:default="scope">{{ scope }}{{ scope.info.name }}</template></Home>
</template>
<script>
import Home from './home.vue'
export default{components:{Home},
}
</script><template><div>Home組件<slot :info="infomation" :msg="msg"></slot></div>
</template>
<script>
export default{data(){return{infomation:{name:'zs',age:18},msg:'123'}}
}
</script>
解構(gòu)作用域插槽
<template><Home><template #default="{info,msg}">{{ info.name }}{{ info.age }}{{ msg }}</template></Home>
</template>
<script>
import Home from './home.vue'
export default{components:{Home},
}
</script>
作用域插槽的使用場景
<template><Home><template #default="{user}"><td>{{user.name}}</td><td>{{ user.age }}</td><td><input type="checkbox" :checked="user.state"></td></template></Home>
</template>
<script>
import Home from './home.vue'
export default{components:{Home},
}
</script><template><div>Home組件<table><tr><td>名字</td><td>年齡</td><td>狀態(tài)</td></tr><tr v-for="item in list" :key="item"><slot :user="item"></slot></tr></table></div>
</template>
<script>
export default{data(){return{list:[{name:'zs1',age:18,state:true},{name:'zs2',age:17,state:false},{name:'zs3',age:15,state:true}],}}
}
</script>
四、自定義指令
vue 中自定義指令分為兩類:私有自定義指令,全局自定義指令。
在每個vue組件中,可以在directives節(jié)點(diǎn)下聲明私有自定義指令。
1.私有自定義指令
<template><input type="text" v-focus>
</template>
<script>
export default{directives:{focus:{//當(dāng)被綁定的元素插入到dom中時,會自定觸發(fā)mounted函數(shù)mounted(el){el.focus()//讓被綁定的元素自動獲取焦點(diǎn)}}}
}
</script>
2.全局自定義指令
在main.js文件中聲明自定義指令
const app = createApp(App)
app.directive('focus',{mounted(el){el.focus()}
})
3.updated函數(shù)
mounted函數(shù)只在元素第一次插入dom時被調(diào)用,當(dāng)dom更新時mounted函數(shù)不會被觸發(fā)。updated函數(shù)會在每次dom更新后被調(diào)用。
<template><input type="text" v-focus>{{ count }}<button @click="count+=1">+1</button>
</template>
<script>
export default{data(){return{count:1}}
}
</script>//main.jsmain.js
const app = createApp(App)
app.directive('focus',{mounted(el){el.focus()},updated(el){el.focus()}
})
在vue2的項目中使用自定義指令時,mounted->bind,updated->update
如果mounted,updated函數(shù)中的邏輯完全相同,可以簡寫
const app = createApp(App)
app.directive('focus',(el)=>{el.focus()
})
4.指令的參數(shù)值
在綁定指令時,可以通過等號的形式為指令綁定具體的參數(shù)值。binding.value
<template><input type="text" v-model.number="count" v-focus v-color="'red'"><p v-color="'green'">{{ count }}</p><button @click="count+=1">+1</button>
</template>
<script>
import Home from './home.vue'
export default{components:{Home},data(){return{count:1}}
}
</script>//main.js
const app = createApp(App)
app.directive('focus',(el)=>{el.focus()
})
app.directive('color',(el,binding)=>{el.style.color=binding.value
})
五、Table案例
1.搭建項目基本結(jié)構(gòu)
npm create vite
cd vite-project
npm install
2.請求商品列表數(shù)據(jù)
npm i axios
//main.js
import axios from 'axios'
//配置請求的根路徑
axios.defaults.baseURL='http://localhost:3000'
//將axios掛載為全局的$http自定義屬性
app.config.globalProperties.$http=axios
3.封裝MyTable組件
a.通過props屬性,為MyTable.vue組件指定數(shù)據(jù)源
b.在MyTable.vue組件中,預(yù)留header的具名插槽
c.在MyTable.vue組件中,預(yù)留body的作用域插槽
<template><table><thead><slot name="header"></slot></thead><tbody><tr v-for="(item,index) in data" :key="item"><slot name="body" :row="item" :index="index"></slot></tr></tbody></table>
</template>
<script>
export default{props:{data:{type:Array,default:[],require:true}}
}
</script>
4.實現(xiàn)刪除功能
5.實現(xiàn)添加標(biāo)簽的功能
a.實現(xiàn)input和button的按需展示(v-if,v-else)
b.讓input自動獲取焦點(diǎn)(自定義指令)
c.文本框失去焦點(diǎn)自動隱藏
d.文本框的enter,esc按鍵事件
把用戶在文本框中輸入的值,預(yù)先轉(zhuǎn)存到常量val中,清空文本的值,v-if='false'隱藏文本框
判斷val的值是否為空,如果為空,則不進(jìn)行添加,
判斷val的值是否已經(jīng)存在于數(shù)組中,如果存在,則不進(jìn)行添加,return
將用戶輸入的內(nèi)容,作為新標(biāo)簽push到當(dāng)前tag數(shù)組中
<template><MyTable :data="goodsList"><template #header><td>#</td><td>商品名稱</td><td>價格</td><td>標(biāo)簽</td><td>操作</td></template> <template #body="{row,index}"><td>{{index+1}}</td><td>{{ row.title }}</td><td>¥{{ row.price }}</td><td><inputv-if="row.inputVisible"ref="InputRef"v-model.trim="row.inputValue"class="ml-1 w-20"@keyup.enter="handleInputConfirm(row)"@blur="handleInputConfirm(row)"@keyup.esc="row.inputValue=''"v-focus/><el-button v-else class="button-new-tag ml-1" size="small" @click="row.inputVisible = true">+Tag</el-button><el-tag class="ml-2" type="success" v-for="item in row.tag" :key="item">{{ item }}</el-tag></td><td><el-button type="danger" @click="deleteFn(row.id)">刪除</el-button></td></template></MyTable>
</template>
<script>
import MyTable from './MyTable.vue'
export default{components:{MyTable},data(){return{goodsList:[]}},methods:{async getGoodsList(){const {data:res}=await this.$http.get('/goodsList')console.log('res',res);this.goodsList = res.map(item=>{return{...item,inputVisible:false,inputValue:''}})},deleteFn(id){this.goodsList = this.goodsList.filter(item=>item.id!==id)},handleInputConfirm(row){const val = row.inputValue;row.inputValue = '';row.inputVisible = false;if(!val||row.tag.indexOf(val) !==-1)returnrow.tag.push(val)},},created(){this.getGoodsList()},directives:{focus(el){el.focus()}}
}
</script>