vue技術分享
目錄
- vue組件之間的通信
- vue中數(shù)據監(jiān)聽watch的使用
- vuex狀態(tài)管理
- vue-awesome-swiper插件的使用 https://github.com/surmon-china/vue-awesome-swiper
一、vue組件之間的通信
1. 父組件傳值給子組件 </br>
<!--父組件代碼-->
<template>
<div>
<div class="box">
<h1>父組件</h1>
<input type="text" v-model="msg"> <br>
<div>
<p>測試參數(shù):{{msg}}</p>
</div>
</div>
<div class="box">
<Demo1Child :info="msg"></Demo1Child>
</div>
</div>
</template>
<script>
import Demo1Child from '@/components/DemoChild'
export default {
name: 'HelloWorld',
components:{
Demo1Child
},
data () {
return {
msg: ''
}
}
}
</script>
<!--子組件代碼-->
<template>
<div>
<h1>子組件</h1>
<input type="text" v-model="info"> <br>
<p>{{info}}</p>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
props: {
info: {
type: String,
default: function () {
return ''
}
}
}
}
</script>
父組件使用屬性綁定的方式給子組件綁定需要給子組件傳遞的數(shù)據,子組件使用props接收。(子組件直接使用 input, v-model綁定props此處有坑) ==demochild1==
2. 子組件給父組件傳遞參數(shù)
<!--父組件代碼-->
<template>
<div>
<div class="box">
<h1>父組件</h1>
<div>
<p>子組件傳遞上來的參數(shù):{{childrenData}}</p>
</div>
</div>
<div class="box">
<DemoChild2 :info="msg" v-on:listenChildEvent="showChildData"></DemoChild2>
</div>
</div>
</template>
<script>
import DemoChild2 from '@/components/DemoChild2';
export default {
name: 'HelloWorld',
components:{
DemoChild1,
DemoChild2
},
data () {
return {
msg: '',
childrenData:''
}
},
methods:{
showChildData(data){
this.childrenData = data;
}
}
}
</script>
<!--子組件代碼-->
<template>
<div>
<h1>子組件</h1>
<input type="text" v-model="childData" @change="emitFather()"> <br>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
data(){
return{
childData:''
}
},
methods:{
emitFather(){
this.$emit('listenChildEvent',this.childData);
}
}
}
</script>
子組件中需要以某種方式例如點擊事件的方法來觸發(fā)一個自定義事件; </br>
將需要傳的值作為$emit的第二個參數(shù),該值將作為實參傳給響應自定義事件的方法;</br>
在父組件中注冊子組件并在子組件標簽上使用 v-on 對自定義事件的監(jiān)聽 ==DemoChild2==
3. 父子組件數(shù)據的雙向通信
==prop 是單向綁定的==:當父組件的屬性變化時,將傳導給子組件,但是不會反過來。這是為了防止子組件無意修改了父組件的狀態(tài)——這會讓應用的數(shù)據流難以理解。
另外,每次父組件更新時,子組件的所有 prop 都會更新為最新值。這意味著你不應該在子組件內部改變 prop。如果你這么做了,Vue 會在控制臺給出警告 ==DemoChild3==
<!--父組件代碼-->
<template>
<div>
<div class="box">
<h1>父組件3</h1>
<div>
<input type="text" v-model="msg">
<p>{{msg}}</p>
</div>
</div>
<div class="box">
<DemoChild3 :msg.sync="msg"></DemoChild3>
</div>
</div>
</template>
<script>
import DemoChild3 from '@/components/DemoChild3';
export default {
name: 'HelloWorld',
components:{
DemoChild1,
DemoChild2,
DemoChild3
},
data () {
return {
msg: '',
childrenData:''
}
},
methods:{
showChildData(data){
this.childrenData = data;
}
}
}
<!--子組件代碼-->
<template>
<div>
<h1>子組件3</h1>
<input type="text" v-model="childData"> <br>
<p>{{msg}}</p>
<input type="button" value="點我加一下" @click="emitFather()">
</div>
</template>
<script>
export default {
name: 'HelloWorld',
data(){
return{
childData:''
}
},
props: {
msg: {
type: String,
default: function () {
return ''
}
}
},
methods:{
emitFather(){
this.$emit('update:msg',this.childData);
}
}
}
</script>
4. 非父子組件之間的通信
實現(xiàn)非父子組件間的通信,可以通過創(chuàng)建一個vue實例Bus作為媒介,要相互通信的兄弟組件之中,都引入Bus,之后通過分別調用Bus事件觸發(fā)和監(jiān)聽來實現(xiàn)組件之間的通信和參數(shù)傳遞。
<!--bus.js-->
import Vue from 'vue';
export default new Vue;
<!--組件一-->
<template>
<div>
<h1>組件一</h1>
<input type="text" v-model="message">
<input type="button" value="確認傳遞參數(shù)" @click="bus()">
</div>
</template>
<script>
import Bus from './bus'
export default {
data () {
return {
message:'111',
};
},
methods:{
bus () {
Bus.$emit('msg',this.message);
}
}
}
<!--組件二-->
<template>
<div>
<h1>組件二</h1>
<p>{{message}}</p>
</div>
</template>
<script>
import Bus from './bus'
export default {
data () {
return {
message:''
};
},
mounted() {
let self = this;
Bus.$on('msg', (e) => {
self.message = e
console.log(`傳來的數(shù)據是:${e}`);
})
}
}
二、vuex狀態(tài)管理
- 多個視圖依賴于同一狀態(tài)。
- 來自不同視圖的行為需要變更同一狀態(tài)。
對于問題一,傳參的方法對于多層嵌套的組件將會非常繁瑣,并且對于兄弟組件間的狀態(tài)傳遞無能為力。
對于問題二,我們經常會采用父子組件直接引用或者通過事件來變更和同步狀態(tài)的多份拷貝。以上的這些模式非常脆弱,通常會導致無法維護的代碼。
vuex是一個專門為vue.js設計的集中式狀態(tài)管理架構。狀態(tài)?我把它理解為在data中的屬性需要共享給其他vue組件使用的部分,就叫做狀態(tài)。簡單的說就是data中需要共用的屬性。比如:我們有幾個頁面要顯示用戶名稱和用戶等級,或者顯示用戶的地理位置。如果我們不把這些屬性設置為狀態(tài),那每個頁面遇到后,都會到服務器進行查找計算,返回后再顯示。
- 首先安裝vuex插件 npm install vuex --save
- State
- Mutation
- Getter
- Action
- Module
State:這個就是我們說的訪問狀態(tài)對象,它就單頁應用中的共享值。怎么將狀態(tài)對象賦值給內部對象,也就是把stroe.js中的值,賦值給模板里data中的值。一般有三種方式。
1.通過computed的計算屬性直接賦值
computed屬性可以在輸出前,對data中的值進行改變,我們就利用這種特性把store.js中的state值賦值給我們模板中的data值。
computed:{
test(){
return this.$store.state.count; //store.state.count
}
},
store
2.mapState 輔助函數(shù)——通過對象賦值
需要在組件中引入==import {mapState} from 'vuex';==
computed:mapState({
test:function(state){
return state.count;
}
}),
3.mapState 輔助函數(shù)——通過數(shù)組賦值
computed:mapState(["count"])
Mutation:更改 Vuex 的 store 中的狀態(tài)的唯一方法是提交 mutation。要想更改store中state的值,只能通過mutation。
1.Vuex提供了==commit==方法來修改狀態(tài)
組件中這樣使用commit
<button @click="$store.commit('add')">+</button>
<button @click="$store.commit('reduce')">-</button>
store.js中這樣定義mutation
const mutations={
add(state){
state.count++;
},
reduce(state){
state.count--;
}
}
2.提交載荷(Payload)——傳值
組件中這樣定義傳值
<button @click="$store.commit('add','this')">+</button>
store.js中這樣定義mutation中的add方法
const mutations={
add(state,test){
state.count = test;
},
reduce(state){
state.count--;
}
}
3.模板獲取mutation中的方法
需要在組件中引入 ==import {mapMutations} from 'vuex';==
組件中js代碼可以這樣寫
methods:{
...mapMutations(['add','reduce']),
},
組件中的html代碼可以這樣寫
<button @click="add('this')">+</button>
Getters:getters從表面是獲得的意思,可以把他看作在獲取數(shù)據之前進行的一種再編輯,相當于對數(shù)據的一個過濾和加工
在store.js中這樣寫
const getters = {
count:function(state){
return state.count +=100;
}
}
在組件中這樣寫
computed:{
// count(){
// return this.$store.getters.count;
// },
...mapGetters(["count"])
}
Actions:actions和的Mutations功能基本一樣,不同點是,actions是異步的改變state狀態(tài),而Mutations是同步改變狀態(tài)
在store.js中這樣寫
const actions ={
addAction(doAnything){
// doAnything.commit('add',5)
setTimeout(function(){
doAnything.commit('add',5);
},3000)
console.log('我比add提前執(zhí)行');
},
reduceAction({commit}){
commit('reduce')
}
}
在組件中這樣寫
methods:{
...mapMutations([
'add','reduce'
]),
...mapActions(['addAction','reduceAction'])
}
三、vue中數(shù)據監(jiān)聽watch的使用
watch首先是一個對象,是對象就有鍵名(你要監(jiān)聽的對象數(shù)據),鍵值(可以是函數(shù),函數(shù)名,對象),鍵值如果是對象選項有三個
- 第一個handler:其值是一個回調函數(shù)。即監(jiān)聽到變化時應該執(zhí)行的函數(shù)(不能使用箭頭函數(shù))。
- 第二個是deep:其值是true或false;確認是否深入監(jiān)聽。(一般監(jiān)聽時是不能監(jiān)聽到對象屬性值的變化的,數(shù)組的值變化可以聽到。)
- 第三個是immediate:其值是true或false;確認是否以當前的初始值執(zhí)行handler的函數(shù)。
<template>
<div>
<p>今天掙了{{money}}元</p>
<p>晚餐可以吃個{{food}}</p>
<p>
<button @click="add">加班</button>
<button @click="reduce">偷懶</button>
</p>
<input type="text" v-model="arr[0]"> <br>
<input type="text" v-model="obj.name">
</div>
</template>
<script>
var foods=['菜夾饃','肉夾饃','牛肉面','肯德基全家桶','六菜一湯'];
export default {
data () {
return {
food:'菜夾饃',
money:5,
arr:[1,2,3,4],
obj:{
name:'李四',
age:18,
sex:'女'
}
};
},
methods:{
add:function(){
this.money+=5;
},
reduce:function(){
this.money-=5;
}
},
watch:{
money:function(newVal,oldVal){
if(newVal<5){
this.food = '土'
}else if(newVal==5){
this.food=foods[0];
}else if(newVal==10)
{
this.food=foods[1];
}else if(newVal==15)
{
this.food=foods[2];
}else if(newVal==20)
{
this.food=foods[3];
}else{
this.food=foods[4];
}
},
arr:{
handler(curVal,oldVal){
console.log(curVal,oldVal)
},
// deep:true
},
obj:{
handler(newVal,oldVal){
console.log(newVal,oldVal);
},
deep:true
}
}
}
</script>
注意項:在使用數(shù)據監(jiān)聽的同時要使用原聲js獲取DOM節(jié)點,一定要加上非空判斷,不然代碼容易報錯
watch: {
'name': function (newVal, oldVal) {
this.variable_arr = []
this.temp = []
if (newVal.content && newVal.content !== '') {
let str = newVal.content.replace('%storeName%', `(${this.currentStore.store_name})`)
let temp = []
this.temp = str.split('%')
this.temp.forEach((v, index) => {
if ((index + 1) % 2 !== 0) {
temp.push(v)
}
})
this.views = temp.join('')
this.count = Math.ceil((this.views.length + this.identification.length) / 70) * this.phone_list.length
}
if (document.getElementsByClassName('smsref') && document.getElementsByClassName('smsref')[0]) {
document.getElementById('refForm').reset()
}
},
},
四、vue里ref ($refs)用法
ref 有三種用法 https://www.cnblogs.com/goloving/p/9404099.html
- ref 加在普通的元素上,用this.ref.name 獲取到的是dom元素
- ref 加在子組件上,用this.ref.name 獲取到的是組件實例,==可以使用組件的所有方法。==
- 如何利用 v-for 和 ref 獲取一組數(shù)組或者dom 節(jié)點