共计 15232 个字符,预计需要花费 39 分钟才能阅读完成。
22. 自定义指令
22.1 自定义指令基本语法
22.1.2 自定义指令.vue
template>
div id="app">
input v-model="msg" type="text">
input :value="msg" @input="msg=$event.target.value" type="text">
div>
template>
script>
export default {}
script>
style scoped>
style>
22.1.2 App.vue
template>
div>
h1 v-color="color1">自定义指令 1 h1>
h1 v-color="color2">自定义指令 2 h1>
input v-focus ref="inp" type="text">
div>
template>
script>
export default {
directives:{
focus:{
inserted(el){
el.focus()
}
},
color:{
inserted(el,binding){
el.style.color=binding.value
},
update(el,binding){
console.log("指令的值修改了")
el.style.color=binding.value
}
}
},
data(){
return{
color1:"red",
color2:"orange"
}
}
}
script>
style>
style>
22.2 自定义指令(v-loading 指令封装)
22.2.1 自定义指令
template>
div id="app">
input v-model="msg" type="text">
input :value="msg" @input="msg=$event.target.value" type="text">
div>
template>
script>
export default {}
script>
style scoped>
style>
22.2.2 App.vue
template>
div class="box" v-loading="isloading">
ul>
li v-for="item in list" :key="item.id" class="news">
div class="left">
div class="title">{{item.title}}div>
div class="info">
span>{{item.source}}span>
span>{{item.time}}span>
div>
div>
div class="right">
img :src="item.img" alt="">
div>
li>
ul>
div>
template>
script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js">script>
script>
export default {
data() {
return {
list: [],
isloading: true
}
},
async created() {
const res = await axios.get("http://hmajax.itheima.net/api/news")
setTimeout(() => {
this.list = res.data.data
this.isLoading = false
}, 2000)
},
directives: {
loading: {
inserted(el, binding) {
binding.value ? el.classList.add("loading") : el.classList.remove('loading')
},
update(el, binding) {
binding.value ? el.classList.add("loading") : el.classList.remove('loading')
}
}
}
}
script>
style>
.loading:before {
content: "";
position: absolute;
left: 0;
width: 100%;
height: 100%;
background: #fff url("./img/loading.gif") no-repeat;
}
style>
23. 插槽
23.1 默认插槽
23.1.1 默认插槽
template>
div id="app">
input v-model="msg" type="text">
input :value="msg" @input="msg=$event.target.value" type="text">
div>
template>
script>
export default {}
script>
style scoped>
style>
23.1.2 App.vue
template>
div>
MyDialog>确定要删除吗?MyDialog>
MyDialog>确定要退出系统吗?MyDialog>
div>
template>
script>
import MyDialog from "./components/MyDialog"
export default {
data() {
return {}
},
components: {
MyDialog
}
}
script>
style>
.loading:before {
content: "";
position: absolute;
left: 0;
width: 100%;
height: 100%;
}
style>
23.1.3 MyDialog.vue
template>
div class="dialog">
div class="dialog-header">
h3>友情提示h3>
span class="close">Xspan>
div>
div class="dialog-content">
slot>slot>
div>
div class="dialog-footer">
button>取消button>
button>确认button>
div>
div>
template>
script>
export default {
name: "MyDialog"
}
script>
style scoped>
style>
23.2 后备内容(插槽默认的内容)
23.2.1 后备内容
template>
div id="app">
input v-model="msg" type="text">
input :value="msg" @input="msg=$event.target.value" type="text">
div>
template>
script>
export default {}
script>
style scoped>
style>
23.2.2 App.vue
template>
div>
MyDialog>确定要删除吗?MyDialog>
MyDialog>确定要退出系统吗?MyDialog>
MyDialog>MyDialog>
div>
template>
script>
import MyDialog from "./components/MyDialog"
export default {
data() {
return {}
},
components: {
MyDialog
}
}
script>
style>
.loading:before {
content: "";
position: absolute;
left: 0;
width: 100%;
height: 100%;
}
style>
23.2.3 MyDialog.vue
template>
div class="dialog">
div class="dialog-header">
h3>友情提示h3>
span class="close">Xspan>
div>
div class="dialog-content">
slot>后备内容slot>
div>
div class="dialog-footer">
button>取消button>
button>确认button>
div>
div>
template>
script>
export default {
name: "MyDialog"
}
script>
style scoped>
style>
23.3 具名插槽
23.3.1 具名插槽
template>
div id="app">
input v-model="msg" type="text">
input :value="msg" @input="msg=$event.target.value" type="text">
div>
template>
script>
export default {}
script>
style scoped>
style>
23.3.2 App.vue
template>
div>
MyDialog>
template #head>
div>大标题div>
template>
template #content>
div>内容文本div>
template>
template #footer>
template>
button>确认button>
button>取消button>
template>
template>
MyDialog>
div>
template>
script>
import MyDialog from "./components/MyDialog"
export default {
data() {
return {}
},
components: {
MyDialog
}
}
script>
style>
.loading:before {
content: "";
position: absolute;
left: 0;
width: 100%;
height: 100%;
}
style>
23.3.3 MyDialog.vue
template>
div class="dialog">
div class="dialog-header">
slot>slot>
div>
div class="dialog-content">
slot name="content">slot>
div>
div class="dialog-footer">
slot name="footer">slot>
div>
div>
template>
script>
export default {
name: "MyDialog"
}
script>
style scoped>
style>
23.4 作用域插槽
23.4.1 作用域插槽
template>
div id="app">
input v-model="msg" type="text">
input :value="msg" @input="msg=$event.target.value" type="text">
div>
template>
script>
export default {}
script>
style scoped>
style>
23.4.2 App.vue
template>
div>
MyTable :data="list">
template #default="obj">
{{obj}}
button @click="del(obj.row.id)">删除button>
template>
MyTable>
MyTabe :data="list2">
template #default="{row}">
button @click="show(row)">查看button>
template>
MyTabe>
div>
template>
script>
import MyTable from "./components/MyTable"
export default {
data() {
return {
list: [
{id: 1, name: "yuer", age : 18},
{id: 2, name: "yuer2", age : 19},
{id: 3, name:"yuer3", bag :17},
],
list2: [
{id: 1, name: "yuer", age : 18},
{id: 2, name: "yuer2", age : 19},
{id: 3, name:"yuer3", bag :17},
]
}
},
methods:{
del(id){
this.list=this.list.filter(item=>item)
},
show(row){
console.log(row);
}
},
components: {
MyTable
}
}
script>
style>
.loading:before {
content: "";
position: absolute;
left: 0;
width: 100%;
height: 100%;
}
style>
23.4.3 MyTable.vue
template>
div>
tr v-for="(item,index) in data" :key="item.id">
td>{{index + 1}}td>
td>{{item.name}}td>
td>{{item.age}}td>
td>
slot :row="item" msg="测试数据">slot>
td>
tr>
div>
template>
script>
export default {
name: "MyDialog"
}
script>
style scoped>
style>
24. 路由
24.1 单页应用程序 & 路由简单介绍
template>
div id="app">
input v-model="msg" type="text">
input :value="msg" @input="msg=$event.target.value" type="text">
div>
template>
script>
export default {}
script>
style scoped>
style>
24.2 VueRouter 的介绍
template>
div id="app">
input v-model="msg" type="text">
input :value="msg" @input="msg=$event.target.value" type="text">
div>
template>
script>
export default {}
script>
style scoped>
style>
24.3 组件存放目录问题
template>
div id="app">
input v-model="msg" type="text">
input :value="msg" @input="msg=$event.target.value" type="text">
div>
template>
script>
export default {}
script>
style scoped>
style>
24.4 VueRouter 的完整实现步骤
24.4.1 main.js
import Vue from 'vue'
import App from './App.vue'
import VueRouter from "vue-router";
import Find from "./views/Find.vue"
import My from "./views/My.vue"
import Friend from "./views/Friend.vue"
Vue.use(VueRouter)
const r = new VueRouter({
routes: [
{path: "/find", component: Find},
{path: "/my", component: My},
{path: "/friend", component: Friend},
]
}
)
Vue.config.productionTip = false
new Vue({
render: h => h(App),
router: r
}).$mount('#app')
24.4.2 App.vue
template>
div>
div class="footer_wrap">
a href="#/find">发现音乐a>
a href="#/my">我的音乐a>
a href="#/friend">朋友a>
div>
div class="top">
router-view>router-view>
div>
div>
template>
script>
export default {}
script>
style>
.footer_wrap {
position: fixed;
left: 0;
top: 0;
display: flex;
width: 100%;
height: 100%;
}
style>
24.4.3 Find.vue
template>
div>
p>发现音乐p>
p>发现音乐p>
p>发现音乐p>
div>
template>
script>
export default {
name: "FindMusic"
}
script>
style scoped>
style>
24.4.4 My.vue
template>
div>
p>我的歌单p>
p>我的歌单p>
p>我的歌单p>
div>
template>
script>
export default {
name: "MyMusic"
}
script>
style scoped>
style>
24.4.5 Friend.vue
template>
div>
p>朋友歌单p>
p>朋友歌单p>
p>朋友歌单p>
div>
template>
script>
export default {
name: "FriendMusic"
}
script>
style scoped>
style>
总结:
路由的使用步骤(5+2)
5 步基础步骤:
(1)项目终端中下载
(2)(3)(4)(5)在 main.js 文件中实现
2 步核心步骤:
(1)创建子组件 vue 文件,在 main.js 文件中导入,并将这些文件和路径地址进行匹配;
(2)在根组件中使用这些子组件,App.js 文件
25. 路由进阶
25.1 路由的封装抽离
template>
div id="app">
input v-model="msg" type="text">
input :value="msg" @input="msg=$event.target.value" type="text">
div>
template>
script>
export default {}
script>
style scoped>
style>
25.1.1 router 目录—index.js(路由的封装)
import Vue from 'vue'
import VueRouter from "vue-router";
import Find from "@/views/Find"
import My from "@/views/My"
import Friend from "@/views/Friend"
Vue.use(VueRouter)
const router = new VueRouter({
routes: [
{path: "/find", component: Find},
{path: "/my", component: My},
{path: "/friend", component: Friend},
]
}
)
export default router
25.1.2 main.js 导入封装路由
import Vue from 'vue'
import App from './App.vue'
import router from './router/index'
Vue.config.productionTip = false
new Vue({
render: h => h(App),
router
}).$mount('#app')
25.1.3 App.vue
template>
div>
div class="footer_wrap">
a href="#/find">发现音乐a>
a href="#/my">我的音乐a>
a href="#/friend">朋友a>
div>
div class="top">
router-view>router-view>
div>
div>
template>
script>
export default {}
script>
style>
.footer_wrap {
position: fixed;
left: 0;
top: 0;
display: flex;
width: 100%;
height: 100%;
}
style>
25.1.4 Find.vue
template>
div>
p>发现音乐p>
p>发现音乐p>
p>发现音乐p>
div>
template>
script>
export default {
name: "FindMusic"
}
script>
style scoped>
style>
25.1.5 Friend.vue
template>
div>
p>朋友歌单p>
p>朋友歌单p>
p>朋友歌单p>
div>
template>
script>
export default {
name: "FriendMusic"
}
script>
style scoped>
style>
25.1.6 My.vue
template>
div>
p>我的歌单p>
p>我的歌单p>
p>我的歌单p>
div>
template>
script>
export default {
name: "MyMusic"
}
script>
style scoped>
style>
25.2 使用 router-link 替代 a 标签实现高亮
25.2.1 使用 router-link 替代高亮
template>
div id="app">
input v-model="msg" type="text">
input :value="msg" @input="msg=$event.target.value" type="text">
div>
template>
script>
export default {}
script>
style scoped>
style>
25.2.2 index.js
import Vue from 'vue'
import VueRouter from "vue-router";
import Find from "@/views/Find"
import My from "@/views/My"
import Friend from "@/views/Friend"
Vue.use(VueRouter)
const router = new VueRouter({
routes: [
{path: "/find", component: Find},
{path: "/my", component: My},
{path: "/friend", component: Friend},
],
linkActiveClass: 'active',
linkExactActiveClass:'exact-active'
}
)
export default router
25.2.3 main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router/index'
Vue.config.productionTip = false
new Vue({
render: h => h(App),
router
}).$mount('#app')
25.2.4 App.vue
template>
div>
div class="footer_wrap">
router-link to="/find">发现音乐歌单router-link>
router-link to="/my">我的歌单router-link>
router-link to="/friend">朋友的歌单router-link>
div>
div class="top">
router-view>router-view>
div>
div>
template>
script>
export default {}
script>
style>
body{
margin:0;
padding:0;
}
.footer_wrap {
position: relative;
left: 0;
top: 0;
display: flex;
width: 100%;
text-align:center;
background-color: #333;
color: #ccc;
}
.footer_wrap a{
flex:1;
text-decoration: none;
padding:20px 0;
line-height: 20px;
background-color: #333;
color:#ccc;
border:1px solid black;
}
.footer_wrap a.active{
background-color: purple;
}
.footer_wrap a:hover{
background-color: #555;
}
style>
子组件与上节相同
25.3 声明式导航 - 跳转传参
25.3.1 声明式导航 - 跳转传参
template>
div id="app">
input v-model="msg" type="text">
input :value="msg" @input="msg=$event.target.value" type="text">
div>
template>
script>
export default {}
script>
style scoped>
style>
25.3.2 router—index.js
import Vue from 'vue'
import VueRouter from "vue-router";
import Home from "@/views/Home"
import Search from "@/views/Search"
Vue.use(VueRouter)
const router = new VueRouter({
routes: [
{path:"/home",component:Home},
{path:"/search/:words",component:Search}
],
}
)
export default router
25.3.3 main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router/index'
Vue.config.productionTip = false
new Vue({
render: h => h(App),
router
}).$mount('#app')
25.3.4 App.vue
template>
div id="app">
div class="link">
router-link to="/find">首页router-link>
router-link to="/my">搜索页router-link>
div>
router-view>router-view>
div>
template>
script>
export default {}
script>
style>
.link{
height:50px;
line-height:50px;
background-color: #495150;
display:flex;
margin:-8px -8px 0 -8px;
margin-bottom: 50px;
}
.footer_wrap {
position: relative;
left: 0;
top: 0;
display: flex;
width: 100%;
text-align: center;
background-color: #333;
color: #ccc;
}
.footer_wrap a {
flex: 1;
text-decoration: none;
padding: 20px 0;
line-height: 20px;
background-color: #333;
color: #ccc;
border: 1px solid black;
}
.footer_wrap a.active {
background-color: purple;
}
.footer_wrap a:hover {
background-color: #555;
}
style>
25.3.5 Home.vue
template>
div class="home">
div class="logo-box">div>
div class="search-box">
input type="text">
button>搜索一下button>
div>
div class="hot-link">
热门搜索:router-link to="/search/ 发现歌单 "> 发现歌单router-link>
router-link to="/search/ 我的歌单 "> 我的歌单router-link>
router-link to="/search/ 朋友歌单 "> 朋友歌单router-link>
div>
div>
template>
script>
export default {
name: "HomeComponent"
}
script>
style scoped>
.logo-box{
}
style>
25.3.6 Search.vue
template>
div class="search">
p>搜索关键字:{{$route.params.words}}p>
p>搜索结果:p>
ul>
li>..............li>
li>..............li>
li>..............li>
li>..............li>
li>..............li>
li>..............li>
ul>
div>
template>
script>
export default {
name: "SearchComponent",
created() {
console.log(this.$route.params.words)
}
}
script>
style scoped>
.search {
width: 400px;
height: 240px;
padding: 0 20px;
}
style>
25.4 Vue 路由 - 重定向
25.4.1 Vue 路由 - 重定向
template>
div id="app">
input v-model="msg" type="text">
input :value="msg" @input="msg=$event.target.value" type="text">
div>
template>
script>
export default {}
script>
style scoped>
style>
25.4.2 router—index.js
import Vue from 'vue'
import VueRouter from "vue-router";
import Home from "@/views/Home"
import Search from "@/views/Search"
import NotFound from "@/views/NotFound"
Vue.use(VueRouter)
const router = new VueRouter({
mode: "history",
routes: [
{path: "/", redirect: '/home'},
{path: "/home", component: Home},
{path: "/search/:words", component: Search},
{path: "*", component: NotFound}
],
}
)
export default router
25.4.3 App.vue
template>
div id="app">
div class="link">
router-link to="/find">首页router-link>
router-link to="/my">搜索页router-link>
div>
router-view>router-view>
div>
template>
script>
export default {}
script>
style>
.link{
height:50px;
line-height:50px;
background-color: #495150;
display:flex;
margin:-8px -8px 0 -8px;
margin-bottom: 50px;
}
.footer_wrap {
position: relative;
left: 0;
top: 0;
display: flex;
width: 100%;
text-align: center;
background-color: #333;
color: #ccc;
}
.footer_wrap a {
flex: 1;
text-decoration: none;
padding: 20px 0;
line-height: 20px;
background-color: #333;
color: #ccc;
border: 1px solid black;
}
.footer_wrap a.active {
background-color: purple;
}
.footer_wrap a:hover {
background-color: #555;
}
style>
25.4.4 NotFound.vue
template>
div>
404
div>
template>
script>
export default {
name: "NotFound"
}
script>
style scoped>
style>
其他文件见 25.3
25.5 编程式导航
25.5.1 基本跳转
template>
div id="app">
input v-model="msg" type="text">
input :value="msg" @input="msg=$event.target.value" type="text">
div>
template>
script>
export default {}
script>
style scoped>
style>
25.5.2 路由传参
template>
div id="app">
input v-model="msg" type="text">
input :value="msg" @input="msg=$event.target.value" type="text">
div>
template>
script>
export default {}
script>
style scoped>
style>
25.5.3 index.js
import Vue from 'vue'
import VueRouter from "vue-router";
import Home from "@/views/Home"
import Search from "@/views/Search"
import NotFound from "@/views/NotFound"
Vue.use(VueRouter)
const router = new VueRouter({
mode: "history",
routes: [
{path: "/", redirect: '/home'},
{path: "/home", component: Home},
{name:"search", path: "/search/:words?", component: Search},
{path: "*", component: NotFound}
],
}
)
export default router
25.5.4 main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router/index'
Vue.config.productionTip = false
new Vue({
render: h => h(App),
router
}).$mount('#app')
25.5.5 Home.vue
template>
div class="home">
div class="logo-box">div>
div class="search-box">
input v-model="inpValue" type="text">
button @click="goSearch">搜索一下button>
div>
div class="hot-link">
热门搜索:router-link to="/search/ 发现歌单 "> 发现歌单router-link>
router-link to="/search/ 我的歌单 "> 我的歌单router-link>
router-link to="/search/ 朋友歌单 "> 朋友歌单router-link>
div>
div>
template>
script>
export default {
name: "HomeComponent",
data() {
return {
inpValue: ""
}
},
methods: {
goSearch() {
this.$router.push({
name: 'search',
params: {
words: this.inpValue
}
})
}
}
}
script>
style scoped>
.logo-box {
height: 150px;
background: url('@/assets/logo.jpg') no-repeat center;
}
.search-box {
display: flex;
justify-content: center;
}
style>
25.5.6 Search.vue
template>
div class="search">
p>搜索关键字:{{$route.params.words}}p>
p>搜索结果:p>
ul>
li>..............li>
li>..............li>
li>..............li>
li>..............li>
li>..............li>
li>..............li>
ul>
div>
template>
script>
export default {
name: "SearchComponent",
created() {
console.log(this.$route.params.words)
}
}
script>
style scoped>
.search {
width: 400px;
height: 240px;
padding: 0 20px;
}
style>
原文地址: 第三部分 Vue 讲解(22-25)(代码版)
正文完