元件
定義Vue元件
什麼是元件: 元件的出現,就是為了拆分Vue例項的程式碼量的,能夠讓我們以不同的元件,來劃分不同的功能模組,將來我們需要什麼樣的功能,就可以去呼叫對應的元件即可; 元件化和模組化的不同:
- 模組化: 是從程式碼邏輯的角度進行劃分的;方便程式碼分層開發,保證每個功能模組的職能單一;
- 元件化: 是從UI介面的角度進行劃分的;前端的元件化,方便UI元件的重用;
全域性元件定義的三種方式
- 使用 Vue.extend 配合 Vue.component 方法:
var login = Vue.extend({
template: '<h1>登入</h1>'
});
Vue.component('login', login);
複製程式碼
- 直接使用 Vue.component 方法:
Vue.component('register', {
template: '<h1>註冊</h1>'
});
複製程式碼
- 將模板字串,定義到script標籤種:
<script id="tmpl" type="x-template">
<div><a href="#">登入</a> | <a href="#">註冊</a></div>
</script>
複製程式碼
同時,需要使用 Vue.component 來定義元件:
Vue.component('account', {
template: '#tmpl'
});
複製程式碼
注意: 元件中的DOM結構,有且只能有唯一的根元素(Root Element)來進行包裹!
元件中展示資料和響應事件
- 在元件中,
data
需要被定義為一個方法,例如:
Vue.component('account', {
template: '#tmpl',
data() {
return {
msg: '大家好!'
}
},
methods:{
login(){
alert('點選了登入按鈕');
}
}
});
複製程式碼
- 在子元件中,如果將模板字串,定義到了script標籤中,那麼,要訪問子元件身上的
data
屬性中的值,需要使用this
來訪問;
【重點】為什麼元件中的data屬性必須定義為一個方法並返回一個物件
- 通過計數器案例演示
使用components
屬性定義區域性子元件
- 元件例項定義方式:
<script>
// 建立 Vue 例項,得到 ViewModel
var vm = new Vue({
el: '#app',
data: {},
methods: {},
components: { // 定義子元件
account: { // account 元件
template: '<div><h1>這是Account元件{{name}}</h1><login></login></div>', // 在這裡使用定義的子元件
components: { // 定義子元件的子元件
login: { // login 元件
template: "<h3>這是登入元件</h3>"
}
}
}
}
});
</script>
複製程式碼
- 引用元件:
<div id="app">
<account></account>
</div>
複製程式碼
使用flag
識別符號結合v-if
和v-else
切換元件
- 頁面結構:
<div id="app">
<input type="button" value="toggle" @click="flag=!flag">
<my-com1 v-if="flag"></my-com1>
<my-com2 v-else="flag"></my-com2>
</div>
複製程式碼
- Vue例項定義:
<script>
Vue.component('myCom1', {
template: '<h3>奔波霸</h3>'
})
Vue.component('myCom2', {
template: '<h3>霸波奔</h3>'
})
// 建立 Vue 例項,得到 ViewModel
var vm = new Vue({
el: '#app',
data: {
flag: true
},
methods: {}
});
</script>
複製程式碼
使用:is
屬性來切換不同的子元件,並新增切換動畫
- 元件例項定義方式:
// 登入元件
const login = Vue.extend({
template: `<div>
<h3>登入元件</h3>
</div>`
});
Vue.component('login', login);
// 註冊元件
const register = Vue.extend({
template: `<div>
<h3>註冊元件</h3>
</div>`
});
Vue.component('register', register);
// 建立 Vue 例項,得到 ViewModel
var vm = new Vue({
el: '#app',
data: { comName: 'login' },
methods: {}
});
複製程式碼
- 使用
component
標籤,來引用元件,並通過:is
屬性來指定要載入的元件:
<div id="app">
<a href="#" @click.prevent="comName='login'">登入</a>
<a href="#" @click.prevent="comName='register'">註冊</a>
<hr>
<transition mode="out-in">
<component :is="comName"></component>
</transition>
</div>
複製程式碼
- 新增切換樣式:
<style>
.v-enter,
.v-leave-to {
opacity: 0;
transform: translateX(30px);
}
.v-enter-active,
.v-leave-active {
position: absolute;
transition: all 0.3s ease;
}
h3{
margin: 0;
}
</style>
複製程式碼
父元件向子元件傳值
- 元件例項定義方式,注意:一定要使用
props
屬性來定義父元件傳遞過來的資料
<script>
// 建立 Vue 例項,得到 ViewModel
var vm = new Vue({
el: '#app',
data: {
msg: '這是父元件中的訊息'
},
components: {
son: {
template: '<h1>這是子元件 --- {{finfo}}</h1>',
props: ['finfo']
}
}
});
</script>
複製程式碼
- 使用
v-bind
或簡化指令,將資料傳遞到子元件中:
<div id="app">
<son :finfo="msg"></son>
</div>
複製程式碼
子元件向父元件傳值
- 原理:父元件將方法的引用,傳遞到子元件內部,子元件在內部呼叫父元件傳遞過來的方法,同時把要傳送給父元件的資料,在呼叫方法的時候當作引數傳遞進去;
- 父元件將方法的引用傳遞給子元件,其中,
getMsg
是父元件中methods
中定義的方法名稱,func
是子元件呼叫傳遞過來方法時候的方法名稱
<son @func="getMsg"></son>
複製程式碼
- 子元件內部通過
this.$emit('方法名', 要傳遞的資料)
方式,來呼叫父元件中的方法,同時把資料傳遞給父元件使用
<div id="app">
<!-- 引用父元件 -->
<son @func="getMsg"></son>
<!-- 元件模板定義 -->
<script type="x-template" id="son">
<div>
<input type="button" value="向父元件傳值" @click="sendMsg" />
</div>
</script>
</div>
<script>
// 子元件的定義方式
Vue.component('son', {
template: '#son', // 元件模板Id
methods: {
sendMsg() { // 按鈕的點選事件
this.$emit('func', 'OK'); // 呼叫父元件傳遞過來的方法,同時把資料傳遞出去
}
}
});
// 建立 Vue 例項,得到 ViewModel
var vm = new Vue({
el: '#app',
data: {},
methods: {
getMsg(val){ // 子元件中,通過 this.$emit() 實際呼叫的方法,在此進行定義
alert(val);
}
}
});
</script>
複製程式碼
評論列表案例
目標:主要練習父子元件之間傳值
使用 this.$refs
來獲取元素和元件
<div id="app">
<div>
<input type="button" value="獲取元素內容" @click="getElement" />
<!-- 使用 ref 獲取元素 -->
<h1 ref="myh1">這是一個大大的H1</h1>
<hr>
<!-- 使用 ref 獲取子元件 -->
<my-com ref="mycom"></my-com>
</div>
</div>
<script>
Vue.component('my-com', {
template: '<h5>這是一個子元件</h5>',
data() {
return {
name: '子元件'
}
}
});
// 建立 Vue 例項,得到 ViewModel
var vm = new Vue({
el: '#app',
data: {},
methods: {
getElement() {
// 通過 this.$refs 來獲取元素
console.log(this.$refs.myh1.innerText);
// 通過 this.$refs 來獲取元件
console.log(this.$refs.mycom.name);
}
}
});
</script>
複製程式碼
什麼是路由
-
對於普通的網站,所有的超連結都是URL地址,所有的URL地址都對應伺服器上對應的資源;
-
對於單頁面應用程式來說,主要通過URL中的hash(#號)來實現不同頁面之間的切換,同時,hash有一個特點:HTTP請求中不會包含hash相關的內容;所以,單頁面程式中的頁面跳轉主要用hash實現;
-
在單頁面應用程式中,這種通過hash改變來切換頁面的方式,稱作前端路由(區別於後端路由);
在 vue 中使用 vue-router
- 匯入 vue-router 元件類庫:
<!-- 1. 匯入 vue-router 元件類庫 -->
<script src="./lib/vue-router-2.7.0.js"></script>
複製程式碼
- 使用 router-link 元件來導航
<!-- 2. 使用 router-link 元件來導航 -->
<router-link to="/login">登入</router-link>
<router-link to="/register">註冊</router-link>
複製程式碼
- 使用 router-view 元件來顯示匹配到的元件
<!-- 3. 使用 router-view 元件來顯示匹配到的元件 -->
<router-view></router-view>
複製程式碼
- 建立使用
Vue.extend
建立元件
// 4.1 使用 Vue.extend 來建立登入元件
var login = Vue.extend({
template: '<h1>登入元件</h1>'
});
// 4.2 使用 Vue.extend 來建立註冊元件
var register = Vue.extend({
template: '<h1>註冊元件</h1>'
});
複製程式碼
- 建立一個路由 router 例項,通過 routers 屬性來定義路由匹配規則
// 5. 建立一個路由 router 例項,通過 routers 屬性來定義路由匹配規則
var router = new VueRouter({
routes: [
{ path: '/login', component: login },
{ path: '/register', component: register }
]
});
複製程式碼
- 使用 router 屬性來使用路由規則
// 6. 建立 Vue 例項,得到 ViewModel
var vm = new Vue({
el: '#app',
router: router // 使用 router 屬性來使用路由規則
});
複製程式碼
設定路由高亮
設定路由切換動效
在路由規則中定義引數
- 在規則中定義引數:
{ path: '/register/:id', component: register }
複製程式碼
- 通過
this.$route.params
來獲取路由中的引數:
var register = Vue.extend({
template: '<h1>註冊元件 --- {{this.$route.params.id}}</h1>'
});
複製程式碼
使用 children
屬性實現路由巢狀
<div id="app">
<router-link to="/account">Account</router-link>
<router-view></router-view>
</div>
<script>
// 父路由中的元件
const account = Vue.extend({
template: `<div>
這是account元件
<router-link to="/account/login">login</router-link> |
<router-link to="/account/register">register</router-link>
<router-view></router-view>
</div>`
});
// 子路由中的 login 元件
const login = Vue.extend({
template: '<div>登入元件</div>'
});
// 子路由中的 register 元件
const register = Vue.extend({
template: '<div>註冊元件</div>'
});
// 路由例項
var router = new VueRouter({
routes: [
{ path: '/', redirect: '/account/login' }, // 使用 redirect 實現路由重定向
{
path: '/account',
component: account,
children: [ // 通過 children 陣列屬性,來實現路由的巢狀
{ path: 'login', component: login }, // 注意,子路由的開頭位置,不要加 / 路徑符
{ path: 'register', component: register }
]
}
]
});
// 建立 Vue 例項,得到 ViewModel
var vm = new Vue({
el: '#app',
data: {},
methods: {},
components: {
account
},
router: router
});
</script>
複製程式碼
命名檢視實現經典佈局
- 標籤程式碼結構:
<div id="app">
<router-view></router-view>
<div class="content">
<router-view name="a"></router-view>
<router-view name="b"></router-view>
</div>
</div>
複製程式碼
- JS程式碼:
<script>
var header = Vue.component('header', {
template: '<div class="header">header</div>'
});
var sidebar = Vue.component('sidebar', {
template: '<div class="sidebar">sidebar</div>'
});
var mainbox = Vue.component('mainbox', {
template: '<div class="mainbox">mainbox</div>'
});
// 建立路由物件
var router = new VueRouter({
routes: [
{
path: '/', components: {
default: header,
a: sidebar,
b: mainbox
}
}
]
});
// 建立 Vue 例項,得到 ViewModel
var vm = new Vue({
el: '#app',
data: {},
methods: {},
router
});
</script>
複製程式碼
- CSS 樣式:
<style>
.header {
border: 1px solid red;
}
.content{
display: flex;
}
.sidebar {
flex: 2;
border: 1px solid green;
height: 500px;
}
.mainbox{
flex: 8;
border: 1px solid blue;
height: 500px;
}
</style>
複製程式碼