<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                ![](https://img.kancloud.cn/7f/e1/7fe1f616788b0cffdc053f2827908f84_554x386.png) ![](https://img.kancloud.cn/e3/57/e35775b5e5a6404cd64b1a8b5ff5dbfd_554x148.png) ![](https://img.kancloud.cn/54/fa/54fafaeb9eac268fe181cb0eed03deec_554x491.png) ![](https://img.kancloud.cn/3a/83/3a8387a1447400a9da55734bd1ad5304_554x194.png) ### vue中MVVM的理解 M:模型(Model):數據模型;負責數據存儲。泛指后端進行的各種業務邏輯處理和數據操控,主要圍繞數據庫系統展開。 V就是:View 視圖: 負責頁面展示,也就是用戶界面。主要由 HTML 和 CSS 來構建 VM就是:視圖模型(View-Model): 負責業務邏輯處理(比如Ajax請求等),對數據進行加工后交給視圖展示 通過vue類創建的對象叫Vue實例化對象,這個對象就是MVVM模式中的VM層,模型通過它可以將數據綁定到頁面上,視圖可以通過它將數據映射到模型上 優點 ``` 1.低耦合。視圖(View)可以獨立于Model變化和修改, 2.可重用性。你可以把一些視圖邏輯放在一個ViewModel里面,讓很多view重用這段視圖邏輯 3.前后端分離,開發人員可以專注于業務邏輯(ViewModel)和數據的開發,設計人員可以專注于頁面設計 ``` ### 為什么說VUE是一個漸進式的javascript框架, 漸進式是什么意思? VUE允許你將一個網頁分割成可復用的組件,每個組件都包含屬于自己的HTML、CSS、JAVASCRIPT以用來渲染網頁中相應的地方。對于VUE的使用可大可小,它都會有相應的方式來整合到你的項目中。所以說它是一個漸進式的框架。VUE是響應式的(reactive)這是VUE最獨特的特性,也就是說當我們的數據變更時,VUE會幫你更新所有網頁中用到它的地方。 ### vue生命周期 ``` beforeCreate(創建前) :組件實例被創建之初,組件的屬性生效之前 //beforeCreate生命周期執行的時候,data和methods中的數據都還沒有初始化。不能在這個階段使用data中的數據和methods中的方法 created(創建后) :組件實例已經完全創建,屬性也綁定,但真實 dom 還沒有生成,$el 還不可用 // data 和 methods都已經被初始化好了,如果要調用 methods 中的方法,或者操作 data 中的數據,最早可以在這個階段中操作 beforeMount(掛載前) :在掛載開始之前被調用:相關的 render 函數首次被調用 //執行到這個鉤子的時候,在內存中已經編譯好了模板了,但是還沒有掛載到頁面中,此時,頁面還是舊的 mounted(掛載后) :在el 被新創建的 vm.$el 替換,并掛載到實例上去之后調用該鉤子 //到mounted周期的時候,Vue實例已經初始化完成了。此時組件脫離了創建階段,進入到了運行階段。 如果我們想要通過插件操作頁面上的DOM節點,最早可以在和這個階段中進行 beforeUpdate(更新前) :組件數據更新之前調用,真實DOM還沒被渲染 // 當執行這個鉤子時,頁面中的顯示的數據還是舊的,data中的數據是更新后的,頁面還沒有和最新的數據保持同步 update(更新后) :組件數據更新之后 //頁面顯示的數據和data中的數據已經保持同步了,都是最新的 activated(激活前) :keep-alive專屬,組件被激活時調用 //當組件被切回來時,再去緩存里找這個組件、觸發 activated鉤子函數。 deactivated(激活后) :keep-alive專屬,組件被銷毀時調用 //當組件被換掉時,會被緩存到內存中、觸發 deactivated 生命周期 beforeDestory(銷毀前) :組件銷毀前調用 //Vue實例從運行階段進入到了銷毀階段,這個時候上所有的 data 和 methods , 指令, 過濾器 ……都是處于可用狀態。還沒有真正被銷毀 destoryed(銷毀后) :組件銷毀前調用 //這個時候上所有的 data 和 methods , 指令, 過濾器 ……都是處于不可用狀態。組件已經被銷毀了。 ``` Vue 實例從創建到銷毀的過程,就是生命周期。從開始創建、初始化數據、編譯模板、掛載Dom→渲染、更新→渲染、銷毀等一系列過程,稱之為 Vue 的生命周期。 **Vue子組件和父組件執行順序** 加載渲染過程:beforeCreate(父) —> created(父)—>beforeMount(父)—>beforeCreate(子)—>created(子)—>beforeMount(子)—>mounted(子)—>mounted(父) 更新過程:beforeUpdate(父) —> beforeUpdate(子) —> update(子) —> update(父) 父組件更新:beforeUpdate(父) —> updated(父) 銷毀過程:beforeDestory(父) —> beforeDestory(子) —> destoryed(子) —> destoryed(父) ### v-el 作用是什么 ``` 提供一個在頁面上已存在的 DOM 元素作為 Vue 實例的掛載目標。可以是 CSS 選擇器,也可以是一個 HTMLElement 實例。 ``` ### Vue的el屬性和$mount優先級? ``` new Vue({ router, store, el: '#app', render: h => h(App) }).$mount('#div') /*當出現上面的情況就需要對el和$mount優先級進行判斷,從下面的官方圖片我們可以看出來, el的優先級是高于$mount的,因此以el掛載節點為準*/ ``` ![](https://img-blog.csdnimg.cn/9e200153c89d4302be6402db7957f4af.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA6ICB5Y-k5oeC,size_20,color_FFFFFF,t_70,g_se,x_16) ### Vue實現數據雙向綁定的原理:Object.defineProperty() vue實現數據雙向綁定主要是:采用數據劫持結合發布者-訂閱者模式的方式,通過Object.defineProperty()來劫持各個屬性的setter,getter,在數據變動時發布消息給訂閱者,觸發相應監聽回調。 vue的數據雙向綁定 將MVVM作為數據綁定的入口,整合Observer,Compile和Watcher三者,通過Observer來監聽自己的model的數據變化,通過Compile來解析編譯模板指令(vue中是用來解析 {{}}),最終利用watcher搭起observer和Compile之間的通信橋梁,達到數據變化 —>視圖更新;視圖交互變化(input)—>數據model變更雙向綁定效果。 #### 數據雙向綁定示例: ``` <body> <div id="app"> <input type="text" id="txt"> <p id="show"></p> </div> </body> <script type="text/javascript"> var obj = {} Object.defineProperty(obj, 'txt', { get: function () { return obj }, set: function (newValue) { document.getElementById('txt').value = newValue document.getElementById('show').innerHTML = newValue } }) document.addEventListener('keyup', function (e) { obj.txt = e.target.value }) </script> ``` #### 假如data里面的數據不想做響應式,該怎么做 ``` 1、數據放在vue實例外(vue template中訪問不到數據) 2、created, mounted鉤子函數中定義(注意data中不要聲明該變量名) 3、自定義Options 4、Object.freeze() ``` #### 如何將獲取data中某一個數據的初始狀態? ``` data() { return { num: 10 }, mounted() { this.num = 1000 }, methods: { countNum() { // 可以通過this.$options.data().keyname來獲取初始值 // 計算出num增加了多少 console.log(1000 - this.$options.data().num) } } ``` ### 動態給vue的data添加一個新的屬性時為什么不刷新?怎樣解決? **原因:**一開始data里面的obj的屬性會被設成了響應式數據,而后面新增的屬性,并沒有通過Object.defineProperty設置成響應式數據,所以當我們動態添加的時候并不會刷新 ##### 解決: ``` 1、Vue.set() /*參數 {Object | Array} target {string | number} propertyName/index {any} value*/ Vue.set(this.list, 0, {name: 'zhangsan', age: 18}) this.$set(this.list, 0, {name: 'zhangsan', age: 18}) //如果是在組件中使用,就不能直接使用Vue實例來調用,但是可以使用this 2、Object.assign() //直接使用Object.assign()添加到對象的新屬性不會觸發更新應創建一個新的對象,合并原對象和混入對象的屬性 this.someObject = Object.assign({},this.someObject,{newProperty1:1,newProperty2:2 ...}) 3、$ forcecUpdated() //$forceUpdate迫使Vue 實例重新渲染,且僅僅影響實例本身和插入插槽內容的子組件,而不是所有子組件。 ``` ##### 小結: * 如果為對象添加少量的新屬性,可以直接采用Vue.set() * 如果需要為新對象添加大量的新屬性,則通過Object.assign()創建新對象 * 如果你實在不知道怎么操作時,可采取$forceUpdate()進行強制刷新 (不建議) * PS:vue3是用過proxy實現數據響應式的,直接動態添加新屬性仍可以實現數據響應式 #### Vue.observable Vue.observable,讓一個對象變成響應式數據。Vue 內部會用它來處理 data 函數返回的對象返回的對象可以直接用于渲染函數和計算屬性內,并且會在發生變更時觸發相應的更新。也可以作為最小化的跨組件狀態存儲器 ##### 使用場景: ``` /*在非父子組件通信時,可以使用通常的bus或者使用vuex,但是一些小項目上功能不是太復雜, 而使用上面兩個又有點繁瑣。這時,observable就是一個很好的選擇*/ // 先新建一個js文件,引入vue import Vue from 'vue // 創建state對象,使用observable讓state對象可響應 export let state = Vue.observable({ name: '張三', age: 18 }) // 創建對應的方法 export let mutations = { changeName(name) { state.name = name }, setAge(age) { state.age = age } } ``` ``` //在需要使用的文件中獲取 <template> <div> <p>姓名:{{ name }}</p> <p>年齡:{{ age }}</p> <button @click="changeName('李四')">改變姓名</button> <button @click="setAge(20)">改變年齡</button> </div> </template> import { state, mutations } from '@/store export default { // 在計算屬性中拿到值 computed: { name() { return state.name }, age() { return state.age } }, // 調用mutations里面的方法,更新數據 methods: { changeName: mutations.changeName, setAge: mutations.setAge } } ``` #### 簡單實現數據響應(數據劫持) ``` var demo={ name:'張三' } //Object.defineProperty(obj,prop,descriptor) //obj:目標對象,prop:需要新增,或者修改的屬性名,descriptor:定義的特性 Object.defineProperty(demo,'name',{ set(value){ console.log('重新設為:'+value) name=value }, get(){ return name } }) demo.name='李四' console.log(demo.name)//李四 ``` #### 動態指令設置及動態傳參 ``` <template> ... <child @[someEvent]="handleSomeEvent()" :[someProps]="1000" />... </template> <script> ... data(){ return{ ... someEvent: type ? "click" : "dbclick", someProps: type ? "num" : "price" } }, methods: { handleSomeEvent(){ // do some } } </script> //應用場景:用于頁面中根據不同的返回值進行事件的觸發和值的傳參 ``` ### Vue組件間的參數傳遞 1. 父組件傳給子組件:子組件通過props方法接受數據; 2. 子組件傳給父組件:$emit方法傳遞參數 3. 非父子組件間的數據傳遞,兄弟組件傳值借用eventBus,就是創建一個事件中心,相當于中轉站,可以用它來傳遞事件和接收事件。發送數據使用 $emi t方法,使用 $on 接收 更多詳細內容可以查看我的另一篇文章Vue父子組件間傳值方法集 ### provide和inject使用(響應式) provide和inject是用來實現父組件向深層的子組件傳值和接收的語法,具體如下: ``` // 祖先組件 provide(){ return { // keyName: { name: this.name }, // value 是對象才能實現響應式,也就是引用類型 keyName: this.changeValue // 通過函數的方式也可以[注意,這里是把函數作為value,而不是this.changeValue()] // keyName: 'test' value 如果是基本類型,就無法實現響應式 } }, data(){ return { msg:'初始mesg' } }, methods: { changeValue(){ this.msg= '改變后的msg' } } // 后代組件 inject:['keyName'] create(){ console.log(this.keyName) // 改變后的msg } ``` ### Vue的路由實現:hash模式 和 history模式 hash模式: 在瀏覽器中符號“#”,#以及#后面的字符稱之為hash,用window.location.hash讀取; 特點:hash雖然在URL中,但不被包括在HTTP請求中;用來指導瀏覽器動作,對服務端安全無用,hash不會重加載頁面。 history模式: history 模式下,前端的 URL 必須和實際向后端發起請求的 URL 一致,history采用HTML5的新特性;且提供了兩個新方法:pushState(),replaceState()可以對瀏覽器歷史記錄棧進行修改,以及popState事件的監聽到狀態變更。 ### $nextTick原理及運用 1.nextTick是啥? ``` Vue.nextTick( [callback, context] ):在下次 DOM 更新循環結束之后執行延遲回調。在修改數據之后立即使用這個方法,獲取更新后的 DOM。 ``` 2.為什么需要它呢? ``` Vue是異步執行dom更新的,一旦觀察到數據變化,Vue就會開啟一個隊列,然后把在同一個事件循環 (event loop) 當中觀察到數據變化的 watcher 推送進這個隊列。如果這個watcher被觸發多次,只會被推送到隊列一次。 這種緩沖行為可以有效的去掉重復數據造成的不必要的計算和DOm操作。而在下一個事件循環時,Vue會清空隊列,并進行必要的DOM更新。 假使你設置 vm.someData = 'new value',DOM 并不會馬上更新,而是在異步隊列被清除,也就是下一個事件循環 開始時執行更新時才會進行必要的DOM更新。如果此時你想要根據更新的 DOM 狀態去做某些事情,就會出現問題。 為了在數據變化之后等待 Vue 完成更新 DOM ,可以在數據變化之后立即使用 Vue.nextTick(callback) 。 這樣回調函數在 DOM 更新完成后就會調用。 ``` 3.我在什么地方用它呢? ``` 1、在Vue生命周期的created()鉤子函數進行的DOM操作一定要放在Vue.nextTick()的回調函數中。 原因是在created()鉤子函數執行的時候DOM 其實并未進行任何渲染,而此時進行DOM操作無異于徒勞, 所以此處一定要將DOM操作的js代碼放進Vue.nextTick()的回調函數中。與之對應的就是mounted鉤子函數, 因為該鉤子函數執行時所有的DOM掛載和渲染都已完成,此時在該鉤子函數中進行任何DOM操作都不會有問題 。 2、在數據變化后要執行的某個操作,而這個操作需要使用隨數據改變而改變的DOM結構的時候 (譬如v-if/v-show根據字段變化顯隱),這個操作都應該放進Vue.nextTick()的回調函數中。 ``` ### Compute和watch區別和應用場景 ##### computed ``` //計算屬性中的屬性不需要在data中定義,而且必須有return data(){ return{ firstname:"張", lastname:"三" } } computehd(){ fullname(){ return this.firstname+this.lastname } } /*計算屬性具有緩存,計算屬性是基于它們的依賴進行緩存的,只有在它的相關依賴發生改變時才會重新求值。 只要計算屬性的依賴沒有改變,那么調用它就會直接返回之前的緩存。 同時computed對于其中變量的依賴時多個 的時候,只要其中一個發生了變化都會觸發這個函數*/ //應用場景:當一個變量的值受多個變量的值影響 ``` ##### watch ``` //監聽器watch中的值需要在data中定義,且函數有參數,newval和oldval data: { firstName: '張', lastName: '三', fullName: '張三r' }, watch: { firstName: function (oval,nval) { this.fullName = nval + ' ' + this.lastName }, lastName: function (oval,nval) { this.fullName = this.firstName + ' ' + nval }, immediate: true,// 代表在wacth里聲明了firstName之后立即先去執行其函數方法 deep: true //深度監聽 } //watch的依賴是單個的,它每次只可以對一個變量進行監控,并且區別于computed屬性,監聽器watch可以是異步的而computed則不行 //應用場景:當一個變量的值影響著多個變量的值 ``` ### filters ``` //過濾器分為全局過濾和局部過濾,當命名沖突時以局部過濾器權重高 //插值中 {{msg|filterMsg}} //bind中 <div v-bind:"id|filterId"></div> //運用場景: //一般來說我們用過濾器來格式化一些數據或者渲染的文本對于格式展現的要求 ``` ##### 全局: ``` Vue.filter('過濾器名',function(value){ //do some }) ``` ##### 局部: ``` filters:{ 過濾器名稱:function(value){ //do some } } ``` #### vuex ##### vuex是什么?怎么使用?哪種功能場景使用它? ``` //是什么 vue框架中狀態管理。在main.js引入store注入。新建一個目錄store 。場景有:單頁應用中,組件之間的狀態, 音樂播放、登錄狀態、加入購物車等。 //屬性: State、 Getter、Mutation 、Action、 Module //State state是數據源存放地,對應于一般Vue對象里面的data。state里面存放的數據是響應式的, Vue組件從store中讀取數據,若是store中的數據發生改變,依賴這個數據的組件也會發生更新 需要通過mapState把全局 state 和 getters 映射到當前組件的 computed 計算屬性中。 //Getter getters 可以對State進行計算操作,在多個組件間復用 //Mutation 、Action Action 類似于 mutation,不同在于Action 提交的是 mutation,而不是直接變更狀態;Action 可以包含任意異步操作。 //Module Vuex允許我們將store分隔成模塊(module),每個模塊擁有自己的state,mutation,action,getter,甚至是嵌套子模塊 //使用場景 一句話,不要為了使用vuex而去使用vuex,推薦組件間數據復用,記錄登錄及其它狀態值數據,一些需要緩存的數據使用vuex都能達到很好的管理 ``` ### v-show 與 v-if 的區別,兩者的優先級 ``` v-show指令是通過修改元素的display的CSS屬性讓其顯示或者隱藏; v-if指令是直接銷毀和重建DOM達到讓元素顯示和隱藏的效果; 使用v-show會更加節省性能上的開銷;當只需要一次顯示或隱藏時,使用v-if更加合理。 //優先級 v-for優先級比v-if高(vue2.x中) //注意事項 不要把 v-if 和 v-for 同時用在同一個元素上,帶來性能方面的浪費(每次渲染都會先循環再進行條件判斷) 正確的做法應該是再v-for的外面新增一個模板標簽template,在template上使用v-if也能結合filters或者是computed屬性對數據進行加工,避免v-if判斷,更好的渲染 ``` **注意:在vue2.x中,v-for的優先級會比v-if的優先高,但在vue3.x中這一判斷優先級被換了過來,在3.x的環境下v-if優先級更高,除此之外v-for和v-if在同一標簽中使用也會報錯,解決辦法可以在外面套一個template標簽,或者使用computed來對數組進行過濾然后渲染** ### vue中key的原理及其必要性 vue中key作用:key是給每一個vnode的唯一id,也是diff的一種優化策略,可以根據key,更準確, 更快的找到對應的vnode節點 key是每一個節點的唯一標識 必要性:當我們對數據進行更新的時候,譬如在數組中插入、移除數據時,設置的key值能讓vue底層高效的對新舊vnode進行diff,然后將比對出的結果用來更新真實的DOM ### vue路由傳參 ``` //通過 params 傳參 this.$router.push({ name: '目標組件名', params: { id: id } }) //接收: this.$route.params //通過 query 傳參 this.$router.push({ path: '目標組件路徑', query: { id: id } }) //接收 this.$route.query //區別:query使用path來引入,params使用name來引入,接收方式是this.$route.query.name和this.$route.params.name,值得注意的是query傳遞的參數會顯示在url后面以?id=?形式展示。 //動態路由傳參 //直接調用$router.push 實現攜帶參數的跳轉 this.$router.push({ path: `/particulars/${id}`, }) //通過this.$route.params.id接收,可以看到,和上面傳參不一樣的是我們直接把動態參數加在路徑后面實現動態路由 ``` ### vue路由的鉤子函數 ##### 導航鉤子種類 全局導航鉤子、組件內鉤子、單獨路由獨享組件 ``` //路由的鉤子函數總結有6個 全局的路由鉤子函數:beforeEach、afterEach 單個的路由鉤子函數:beforeEnter 組件內的路由鉤子函數:beforeRouteEnter、beforeRouteLeave、beforeRouteUpdate ``` ##### 全局導航鉤子 全局前置守衛:beforeEach ``` const router = new VueRouter({ ... }) router.beforeEach((to, from, next) => { // ... }) to: Route: 即將要進入的目標 路由對象 from: Route: 當前導航正要離開的路由 next: Function: 一定要調用該方法不然會阻塞路由。執行效果依賴 next 方法的調用參數。 next()方法接收的參數: ``` 全局后置鉤子:afterEach ``` router.afterEach((to, from) => { // do someting }); //后置鉤子并沒有 next 函數 ``` ##### 路由獨享的鉤子 路由獨享的導航鉤子,它是在路由配置上直接進行定義的,參數的使用,和全局前置守衛是一樣的 使用的鉤子函數與全局路由守衛一致,為beforeEnter,不同的是,路由獨享守衛是定義在路由記錄中,全局路由守衛是定義在入口文件中,路由獨享守衛只在路由進入時有效,全局路由守衛是所有路由跳轉都會被攔截。 ##### 組件內的導航鉤子 ``` beforeRouteEnter:在渲染該組件的對應路由前調用 beforeRouteUpdate:在當前路由改變,但是該組件被復用時調用 beforeRouteLeave:導航離開該組件的對應路由時調用 //注意:beforeRouteEnter 不能獲取組件實例 this,因為當守衛執行前,組件實例被沒有被創建出來,剩下兩個鉤子則可以正常獲取組件實例 this ``` ### 共享組件將不會重新渲染問題 我們有時候開發中會把多個路由解析為同一個Vue組件。問題是,Vue默認情況下共享組件將不會重新渲染,如果你嘗試在使用相同組件的路由之間進行切換,則不會發生任何變化,此時我們需要傳遞key來區分,達到刷新的目的 ``` const routes = [ { path: "/a", component: MyComponent }, { path: "/b", component: MyComponent }, ]; ``` ``` <template> <router-view :key="$route.path"></router-view> </template> ``` ### v-slot插槽 插槽就是子組件中用slot標簽定義的預留位置,有name屬性叫具名插槽,不設置name屬性的叫不具名插槽,使用插槽主要是為了在父組件中使用子組件標簽的時候可以往子組件內寫入html代碼。 ##### 插槽使用: ``` //父組件: <template> <div> <div>這是父組件</div> <son>slot內容</son> </div> </template> //子組件 <template> <div> <div>這是子組件</div> <input type="text" placeholder="請輸入"> </div> </template> //一般情款下想在子組件內插入內容像上面直接在標簽里書寫時不顯示的需要以slot為媒介 //改寫后: //子組件: <template> <div> <div>這是子組件</div> <input type="text" placeholder="請輸入"> <slot></slot> </div> </template> //此時我們沒有給插槽設置name,所以這是一個不具名插槽 //具名插槽: //父組件: <template> <div> <div>這是父組件</div> <son> <template slot="myslot"> <div> 實踐具名slot </div> </template> </son> </div> </template> //子組件 <template> <div> <div>這是子組件</div> <input type="text" placeholder="請輸入"> <slot name="myslot"></slot> </div> </template> //此時設置name屬性的插槽為具名插槽,與之相對應的用了slot的設置為相同屬性名的內容則會被渲染在插槽中,此時如果有未設置slot插槽名的內容則會被渲染在不具名插槽中 ``` ##### 插槽作用域: ``` //父組件: <template> <div> <div>父組件</div> <son> <template slot="myslot" slot-scope="props"> <ul> <li v-for="item in props.data"> {{item}} </li> </ul> </template> </son> </div> </template> //子組件: <template> <div> <div>子組件</div> <input type="text" placeholder="請輸入"> <slot name="myslot" :data='list'></slot> </div> </template> <script> export default { name:'Son', data(){ return{ list:[ {name:"張三",age:3}, {name:"李四",age:4}, {name:"王五",age:5} ] } } } </script> ``` ### mixins **mixins是一種分發Vue組件中可復用功能的一種靈活方式。混入對象可以包含任意組件選項。當組件使用混入對象時,所有混入對象的選項將被混入該組件本身的選項。** mixins是一個JavaScript對象,可以包含組件中的任意選項,比如Vue實例中生命周期的各個鉤子函數,也可以是data、components、methods或directives等 **運用:** ``` //mixin文件 export const myMixin={ data(){ return{ msg:1 } }, created(){ console.log('myMixin') }, methods:{ Fn(){ console.log('myMixin') } } } //引入 <template> <div>運用mixin的組件</div> </template> <script> import {myMixin} from'目標文件路徑' export default{ mixins:[myMixin] } </script> ``` **特點:** ``` 1、在組件A對混入的數據做出更改后組件B獲取到的仍是混入初始設置的數據,組件間操作互不污染。 2、值為對象的如methods,components等,選項會被合并,組件會覆蓋混入對象的方法。 比如混入對象里有個方法A,組件里也有方法A,這時候在組件里調用的話,執行的是組件里的A方法。 3、created,mounted等,就會被合并調用,混合對象里的鉤子函數在組件里的鉤子函數之前調用, 同一個鉤子函數里,會先執行混入對象的東西,再執行本組件的。 4、在mixins里面包含異步請求函數的時候,通過直接調用異步函數獲取返回數據 ``` **運用場景區別:** vuex:用來做狀態管理,可以看做全局變量,里面定義的變量在每個組件中均可以使用和修改, 在任一組件中修改此變量的值之后,其他組件中此變量的值也會隨之修改。 mixins:可以定義共用的變量,在每個組件中使用,引入組件中之后,各個變量是相互獨立的, 值的修改在組件中不會相互影響。 父子組件:父子組件相對來說比較獨立,只是父組件將一部分使用子組件,而mixins更像是對于組件的拓展,并且 組件可以對于混入的數據和方法進行多樣化操作。 ### vue自定義組件添加事件 使用修飾符.native 監聽組件根元素的原生事件 ``` <my-button @click.native="alert()" names="點擊觸發"></my-button> ``` ### axios ``` //axios特點: 在瀏覽器中創建XMLHttpRequest請求 在node.js中發送http請求 支持Promise API 攔截請求和響應 轉換請求和響應數據 取消要求 自動轉換JSON數據 客戶端支持防止CSRF/XSRF(跨域請求偽造) //axios的請求方式: axios(config) axios.request(config) axios.get(url [,config]) axios.post(url [,data [,config]]) axios.put(url [,data [,config]]) axios.delete(url [,config]) axios.patch(url [,data [,config]]) axios.head(url [,config]) ``` ##### axios一般用法配置與請求 ``` //引入axios import axios from 'axios' //定義axios請求接口的baseURL axios.default.baseURL = 'http://localhost:8080/api/products' //執行GET請求 axios.get('/user?ID=12345') //返回的是一個Promise .then(res=>console.log(res)) .catch(err=>console.log(err)); //可配置參數的方式 axios.get('/user',{ params:{ ID:12345 } }).then(res=>console.log(res)) .catch(err=>console.log(err)); //發送post請求 axios.post('/user',{ firstName: 'simon', lastName:'li' }).then(res=>console.log(res)) .catch(err=>console.log(err)); //發送post請求 axios({ method: 'post', //請求方式,默認是get請求 url:'/user/12345', //地址 data:{ //參數 firstName: 'simon', lastName: 'li' } }); ``` ##### 發送并發請求: ``` //發送多個請求(并發請求),類似于promise.all,若一個請求出錯,那就會停止請求 const get1 = axios.get('/user/12345'); const get2 = axios.get('/user/12345/permission'); axios.all([get1,get2]) .then(axios.spread((res1,res2)=>{ console.log(res1,res2); })) .catch(err=>console.log(err)) //函數返回的是一個數組axios.spread(callback)可用于將結果數組展開 ``` ##### 請求配置: ``` { //服務器的地址,是必須的選項 url: '/user', //請求的方式,若沒有則默認是get method:'get', //如果url不是絕對地址,則會加上baseURL baseURL: 'http://localhost:3000/', //transformRequest允許請求的數據在發送至服務器之前進行處理,這個屬性只適用于put、post、patch方式 //數組的最后一個函數必須返回一個字符串或者一個'ArrayBuffer'或'Stream'或'Buffer' 實例或'ArrayBuffer','Formdata', //若函數中用到了headers,則需要設置headers屬性 transformRequest: [function(data,headers){ //根據需求對數據進行處理 return data; }], //transformResponse允許對返回的數據傳入then/catch之前進行處理 transformResponse:[function(data){ //依需要對數據進行處理 return data; }], //headers是自定義的要被發送的信息頭 headers: {'X-Requested-with':'XMLHttpRequest'}, //params是請求連接中的請求參數,必須是一個純對象 params:{ ID:12345 }, //paramsSerializer用于序列化參數 paramsSerializer: function(params){ return Qs.stringify(params,{arrayFormat:'brackets'}); }, //data是請求時作為請求體的數據——request.body //只適用于put、post、patch請求方法 //瀏覽器:FormData,File,Blob;Node:stream data:{ firstName: 'simon', }, //timeout定義請求的時間,單位是毫秒,如果請求時間超過設定時間,請求將停止 timeout:1000, //withCredentials表明跨跨域請求書否需要證明。 withCredentials:false, //默認值 //adapter適配器,允許自定義處理請求 //返回一個promise adapter:function(config){ /*...*/ }, //auth表明HTTP基礎的認證應該被使用,并提供證書 auth:{ username:'simon', password:'123456', }, //responseType表明服務器返回的數據類型,這些類型包括:json/blob/document/ arraybuffer/text/stream responseType: 'json', //proxy定義服務器的主機名和端口號 //auth屬性表明HTTP基本認證應該跟proxy相連接,并提供證書 //這將設置一個'Proxy-Authorization'頭(header),覆蓋原來自定義的 proxy:{ host:127.0.0.1, port:8080, auth:{ username:'simon', password:'123456' } }, //取消請求 cancelToken: new CancelToken(cancel=>{}) } ``` ### keep-alive **活動組件實例在切換離開時將被卸載。這將導致它持有的任何更改狀態丟失** 我們在開發過程中經常會有tab切換的這種需求,此時如果說有接口請求或者組件的刷新將會導致我們原來的數據重置,如果不想組件重置數據,我們可以用< keep-alive >標簽包裹 ![](https://img-blog.csdnimg.cn/f795912099244c2abf97549501d0e4a3.png) 上面是官網的一個例子,當從A切換到B組件再切回A時候,count計數將會重置,但是當用< keep-alive >包裹時候,再切換,我們會發現count能夠得以保留了 ``` //Inactive components will be cached! <keep-alive> <component :is="activeComponent" /> </keep-alive> ``` **includes和exclude:** ``` <keep-alive include="a,b"> <component :is="view"></component> </keep-alive> <!-- 正則表達式 (使用 `v-bind`) --> <keep-alive :include="/a|b/"> <component :is="view"></component> </keep-alive> <!-- 數組 (使用 `v-bind`) --> <keep-alive :include="['a', 'b']"> <component :is="view"></component> </keep-alive> /*匹配首先檢查組件自身的 name 選項,如果 name 選項不可用,則匹配它的局部注冊名稱 (父組件 components 選項的鍵值),匿名組件不能被匹配*/ ``` 設置了 keep-alive 緩存的組件,會多出兩個生命周期鉤子(activated與deactivated): * 首次進入組件時:beforeRouteEnter > beforeCreate > created> mounted > activated > … … > beforeRouteLeave > deactivated * 再次進入組件時:beforeRouteEnter >activated > … … > beforeRouteLeave > deactivated ### Vue常用的修飾符及其使用 修飾符是用于限定類型以及類型成員的聲明的一種符號 常見修飾符種類: * 表單修飾符 * 事件修飾符 * 鼠標按鍵修飾符 * 鍵值修飾符 * v-bind修飾符 ##### 1、表單修飾符 ``` //lazy、trim、number //光標離開標簽的時候,才會將值賦予給value <input type="text" v-model.lazy="value"> //過濾用戶輸入的首尾空格字符,注意,如果是中間的空格則不會過濾 <input type="text" v-model.trim="value"> //自動將用戶的輸入值轉為數值類型,但如果這個值無法被parseFloat解析,則會返回原來的值 <input v-model.number="age" type="number"> ``` ##### 2、事件修飾符 ``` //stop、prevent、self、once、capture、passive、native //阻止了事件冒泡 <button @click.stop="btn()">ok</button> //阻止了事件的默認行為 <form v-on:submit.prevent="onSubmit"></form> //只當在 event.target 是當前元素自身時觸發處理函數 <div v-on:click.self="doSome">...</div> //事件只能觸發一次 <button @click.once="btn()">ok</button> //事件觸發從包含這個元素的頂層開始往下觸發 //輸出結構: 1 2 <div @click.capture="btn(1)"> 1 <div @click.capture="btn(2)"> 2 </div> </div> /* 在移動端,當我們在監聽元素滾動事件的時候,會一直觸發onscroll事件會讓我們的網頁變卡, 因此我們使用這個修飾符的時候,相當于給onscroll事件整了一個.lazy修飾符*/ <div v-on:scroll.passive="onScroll">...</div> /*讓組件變成像html內置標簽那樣監聽根元素的原生事件,否則組件上使用 v-on 只會監聽自定義事件 注意:使用.native修飾符來操作普通HTML標簽是會令事件失效的*/ <my-component v-on:click.native="doSomething"></my-component> ``` ##### 3、鼠標按鈕修飾符 ``` //left 左鍵點擊、right 右鍵點擊、middle 中鍵點擊 <button @click.left="btn('left')">ok</button> <button @click.right="btn('right')">ok</button> <button @click.middle="btn('middle')">ok</button> ``` ##### 4、鍵盤修飾符 ``` //onkeyup,onkeydown,后面需要跟keycode編碼名或者按鍵編碼 <input type="text" @keyup.keyCode="btn()"> ``` ##### 5、v-bind修飾符 ``` //async、prop、camel //能對props進行一個雙向綁定 //父組件 <comp :myMessage.sync="bar"></comp> //子組件 this.$emit('update:myMessage',params); //上面代碼與以下代碼是等同的,實際上就是實現了獲取子組件信息處理并回傳 //父親組件 <comp :myMessage="bar" @update:myMessage="func"></comp> func(e){ this.bar = e; } //子組件js func2(){ this.$emit('update:myMessage',params); } 注意: 1、使用sync的時候,子組件傳遞的事件名格式必須為update:value,其中value必須與子組件中props中 聲明的名稱完全一致 2、注意帶有 .sync 修飾符的 v-bind 不能和表達式一起使用 3、將 v-bind.sync 用在一個字面量的對象上,例如 v-bind.sync=”{ title: doc.title }”,是無法正常工作的 //設置自定義標簽屬性,避免暴露數據,防止污染HTML結構 <input id="uid" title="title1" value="1" :index.prop="index"> //將命名變為駝峰命名法,如將view-Box屬性名轉換為 viewBox <svg :view-Box.camel="viewBox"></svg> ``` ### SSR 什么是ssr:Server-Side Rendering 我們稱其為SSR,意為服務端渲染,展開說就是通過服務側完成頁面的 HTML 結構拼接的頁面處理技術,發送到瀏覽器,然后為其綁定狀態與事件,成為完全可交互頁面的過程 ssr作用: * seo:搜索引擎優先爬取頁面HTML結構,使用ssr時,服務端已經生成了和業務想關聯的HTML,有利于seo * 首屏呈現渲染:用戶無需等待頁面所有js加載完成就可以看到頁面視圖(壓力來到了服務器,所以需要權衡哪些用服務端渲染,哪些交給客戶端) 缺點: 1. 項目復雜度高 2. 需要庫的支持性,代碼兼容 3. 服務器負載變大,相對于前后端分離務器只需要提供靜態資源來說,服務器負載更大
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看