這個組件徹底依賴於vue-class-component,它具有如下幾個屬性
// @Prop 裝飾器是用以接收來自父組件的數據
// 子組件
<template>
<h1>收到:{{msg}}</h1>
</template>
<script lang="ts">
import { Component, Vue,Prop,Model } from 'vue-property-decorator';
@Component({})
export default class LangSelect extends Vue {
@Prop() private msg!: string;
}
</script>
// 父組件
<template>
<div class="login-container">
<lang-select msg='父組件的消息'></lang-select>
</div>
</template>
<script lang="ts">
import { Component, Vue, Watch } from 'vue-property-decorator';
import LangSelect from '@/components/LangSelect/index.vue';
@Component({
components: {
LangSelect
}
})
export default class extends Vue {}
</script>複製代碼
// @Model 裝飾器是用以組件上實現雙向綁定
// 子組件
<template>
<input type="checkbox" v-on:change="$emit('handleChange',$event.target.checked)" v-bind:checked='checked'>
</template>
<script lang="ts">
import { Component, Vue,Prop,Model } from 'vue-property-decorator';
import { AppModule } from '@/store/modules/app';@Component({})
export default class LangSelect extends Vue {
@Model('handleChange', { type: Boolean }) private checked!: boolean;
}
</script>// 父組件
<template>
<div class="login-container">
<el-button type="primary" @click="onAlterFoo">父組件改變foo</el-button>
<lang-select v-model="foo" class="set-language" size="16px"></lang-select>
</div>
</template>
<script lang="ts">
import { Component, Vue, Watch } from 'vue-property-decorator';
import LangSelect from '@/components/LangSelect/index.vue';
@Component({ name: 'Login', components: { LangSelect }})
export default class extends Vue {
private foo:boolean = true;
private onAlterFoo() {
this.foo = !this.foo;
}}
</script>
複製代碼
// @Watch 裝飾器是用以監控數據是否改變
<template>
<div class="login-container">
<el-button type="primary" @click="onAlterFoo">父組件改變foo</el-button>
val:{{val}}——oldVal:{{oldVal}}
</div>
</template>
<script lang="ts">
import { Component, Vue, Watch } from 'vue-property-decorator';
import LangSelect from '@/components/LangSelect/index.vue';
@Component({
name: 'Login',
components: {
LangSelect
}})
export default class extends Vue {
private foo:boolean = true;
private val:boolean = true;
private oldVal:boolean = true;
private onAlterFoo() {
this.foo = !this.foo;
}
@Watch('foo')
private handleChanged(val:boolean,oldVal:boolean):void{
this.val = val;
this.oldVal = oldVal;
}}
</script>
複製代碼
//@Provide 裝飾器是用以注入數據,@Inject 裝飾器是用以獲取注入的數據。
// 子組件 @Inject
<template>
<h1>收到:{{bar}}</h1>
</template>
<script lang="ts">
import { Component, Vue, Inject } from 'vue-property-decorator';
@Component({})
export default class LangSelect extends Vue {
@Inject() private readonly bar!:string
}
</script>
// 父組件 @Provide
<template>
<div class="login-container">
@provide/@Inject —— 接收來自父組件的數據:{{foo}}
<lang-select></lang-select>
</div>
</template>
<script lang="ts">
import { Component, Vue, Provide } from 'vue-property-decorator'
import LangSelect from '@/components/LangSelect/index.vue';
@Component({
components: {
LangSelect
}
})
export default class extends Vue {
@Provide('bar') private foo = '啥消息';
}
</script>
複製代碼
// @Emit 裝飾器是用以子組件觸發父組件的自定義事件
// 子組件
<template>
<el-dropdown trigger="click" class="international" @command="handleParent">
<div class="el-dropdown-link">
<slot>
<i ref="icon" class="el-icon-setting"></i>
</slot>
</div>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item :disabled="language==='zh'" command="zh">中文</el-dropdown-item>
<el-dropdown-item :disabled="language==='en'" command="en">English</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
<script lang="ts">
import { Component, Vue,Prop, Watch,Emit } from 'vue-property-decorator';import { AppModule } from '@/store/modules/app';
@Component({})
export default class LangSelect extends Vue {
@Prop({default:"14px"}) size!:string
get language() { return AppModule.language;
}
@Emit()
private handleParent(){}
}
</script>
// 父組件
<template>
<div class="login-container">
<lang-select @handle-parent='handleMe' class="set-language" size="16px"></lang-select>
</div>
</template>
<script lang="ts">import { Component, Vue, Watch } from 'vue-property-decorator';
import LangSelect from '@/components/LangSelect/index.vue';
@Component({ name: 'Login', components: { LangSelect }})
export default class extends Vue {
private handleMe(){ console.log('子組件觸發') }
}
</script>
複製代碼
// @Component 裝飾器是用以聲明子組件
// 子組件
<template>
<p>子組件</p>
</template>
<script lang="ts">
import { Component, Vue,Prop, Watch } from 'vue-property-decorator';
@Component
export default class LangSelect extends Vue {}
</script>
// 父組件
<template>
<div class="login-container">
<lang-select class="set-language" @langChanged="changeLanguage" size="16px">{{currentLang}}</lang-select>
</div>
</template>
<script lang="ts">
import { Component, Vue, Watch } from 'vue-property-decorator';
import LangSelect from '@/components/LangSelect/index.vue';
@Component({ name: 'Login', components: { LangSelect }})
export default class extends Vue {}
</script>複製代碼
// 聲明 resize.ts
import { Component, Vue, Watch } from 'vue-property-decorator';
@Component({ name: 'ResizeMixin'})
export default class extends Vue {
get device() {
return '231323'
}
get sidebar() {
return '是的'
}
}
// 使用 vue界面
<template>
<div class="login-container"> {{classObj}} </div>
</template><script lang="ts">
import { mixins } from 'vue-class-component';
import ResizeMixin from '../../layout/mixin/resize';
export default class extends mixins(ResizeMixin) {
get classObj() {
console.log(this.sidebar,this.device)
return this.sidebar;
}
}
</script>
複製代碼
// @ref 獲取 DOM 元素
<template>
<div class="login-container">
<input type="text" v-model="value" ref='aButton' />
</div></template><script lang="ts">
import { Vue, Component, Ref } from 'vue-property-decorator';
@Componentexport default class YourComponent extends Vue {
@Ref('aButton') readonly name!: string;
private value = 'AAA';
private mounted() {
console.log(this.name); // <input type="text">
}
}
</script>複製代碼
參考地址vue
// Vuex 容許咱們將 store 分割成模塊(module)
// 每一個模塊擁有本身的 state、mutation、action、getter、甚至是嵌套子模塊
// index.ts
import Vue from 'vue'import Vuex from 'vuex';
import { IAppState } from './modules/app';
import { IUserState } from './modules/user';
Vue.use(Vuex)
export interface IRootState {
app: IAppState
user: IUserState
}
export default new Vuex.Store<IRootState>({})
// ./modules/app
import { VuexModule, Module, Mutation, Action, getModule } from 'vuex-module-decorators';
import Cookies from 'js-cookie';
import { getSidebarStatus, setSidebarStatus } from '@/utils/cookies';
const initLang = window.appConf.lang;
import store from '@/store';
export enum DeviceType {
Mobile,
Desktop,
language
}
export interface IAppState {
device: DeviceType
language:string
sidebar: {
opened: boolean
withoutAnimation: boolean
}
}
@Module({ dynamic: true, store, name: 'app' })
class App extends VuexModule implements IAppState {
public sidebar = {
opened: getSidebarStatus() !== 'closed',
withoutAnimation: false
}
public device = DeviceType.Desktop
public language = Cookies.get('language') || initLang;
@Mutation
private TOGGLE_SIDEBAR(withoutAnimation: boolean) {
this.sidebar.opened = !this.sidebar.opened
this.sidebar.withoutAnimation = withoutAnimation
if (this.sidebar.opened) {
setSidebarStatus('opened')
} else {
setSidebarStatus('closed')
}
}
@Mutation
private CLOSE_SIDEBAR(withoutAnimation: boolean) {
this.sidebar.opened = false
this.sidebar.withoutAnimation = withoutAnimation
setSidebarStatus('closed')
}
@Mutation
private TOGGLE_DEVICE(device: DeviceType) {
this.device = device
}
@Mutation
SET_LANGUAGE(language: string) {
this.language = language;
Cookies.set('language', language)
}
@Action
public ToggleSideBar(withoutAnimation: boolean) {
this.TOGGLE_SIDEBAR(withoutAnimation)
}
@Action
public CloseSideBar(withoutAnimation: boolean) {
this.CLOSE_SIDEBAR(withoutAnimation)
}
@Action
public ToggleDevice(device: DeviceType) {
this.TOGGLE_DEVICE(device)
} //i18n-setting
@Action({ commit: 'SET_LANGUAGE' })
async SetLanguage(language: string) {
return language;
}
}
export const AppModule = getModule(App)
// ./modules/user
import { VuexModule, Module, Action, Mutation, getModule } from 'vuex-module-decorators';
import { login, logout, getUserInfo } from '@/api/users';
import { getToken, setToken, removeToken } from '@/utils/cookies';
import store from '@/store';
export interface IUserState { token: string name: string avatar: string introduction: string roles: string[]}@Module({ dynamic: true, store, name: 'user' })
class User extends VuexModule implements IUserState {
public token = getToken() || ''
public name = ''
public avatar = ''
public introduction = ''
public roles: string[] = []
@Mutation private SET_TOKEN(token: string) {
this.token = token
}
@Mutation
private SET_NAME(name: string) {
this.name = name
}
@Mutation
private SET_AVATAR(avatar: string) {
this.avatar = avatar
}
@Mutation
private SET_INTRODUCTION(introduction: string) {
this.introduction = introduction
}
@Mutation
private SET_ROLES(roles: string[]) {
this.roles = roles
}
@Action
public async Login(userInfo: { username: string, password: string }) {
let { username, password } = userInfo
username = username.trim()
const { data } = await
login({ username, password })
setToken(data.accessToken)
this.SET_TOKEN(data.accessToken)
}
@Action public ResetToken() {
removeToken()
this.SET_TOKEN('')
this.SET_ROLES([])
}
@Action
public async GetUserInfo() {
if (this.token === '') {
throw Error('GetUserInfo: token is undefined!')
}
const { data } = await getUserInfo({ /* Your params here */ })
if (!data) {
throw Error('Verification failed, please Login again.')
}
const { roles, name, avatar, introduction } = data.user
// roles must be a non-empty array
if (!roles || roles.length <= 0) {
throw Error('GetUserInfo: roles must be a non-null array!')
}
this.SET_ROLES(roles)
this.SET_NAME(name)
this.SET_AVATAR(avatar)
this.SET_INTRODUCTION(introduction)
}
@Action
public async LogOut() {
if (this.token === '') {
throw Error('LogOut: token is undefined!')
}
await logout()
removeToken()
this.SET_TOKEN('')
this.SET_ROLES([])
}
}
export const UserModule = getModule(User)
複製代碼
參考地址:www.npmjs.com/package/vue…vuex
參考地址:www.npmjs.com/package/vue…npm