vue基礎知識
Vue基礎知識整理
vue例項方法:
<div id="root"> {{num}} <my-components></my-components> </div> <template id="tem"> <div> <p>這是元件</p> </div> </template> </body> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script type="text/javascript"> const app = new Vue({ el: "#root", data: { num: 123, obj: {c: 666} }, components: { "my-components": { template: "#tem" } } }) </script>
-
app.$el
與app.$refs
都是獲取dom的節點,app.$el
是元件掛載的節點,而app.$refs.xxx
則是ref=xxx
的節點 -
app.$data
用於獲取data中的所有資料,如果要直接獲取資料可以通過app.$num
某個屬性即可 -
app.$children
獲取子元件 -
app.$root === app
相等獲取vue例項 -
app.$options
返回一個物件,裡面包含建立vue例項時傳入的引數以及預設的引數,所以可以通過app.$options.data().num
來獲取資料;app.$options.render = (h) => h("div", {}, "頁面上資料重新update時觸發"),例如加個定時器,那麼h函式就會執行並渲染頁面
-
const unWatch = app.$watch('xx', (n, o) => {})
,可用來監聽data中的資料變化,但是用app監聽是,watch
不會自動關閉,需要手動關閉,unWatch()
-
app.$on
與app.$emit
,用來定義事件以及觸發事件,在父元件emit子元件的on事件vm.$on('test', (a ,b) => {//vm.$once事件是代表只執行一次 console.log('test is emit') }) vm.$emit('test', 1, 2)//可以傳遞給a, b
-
app.$forceUpdate
與app.$set(app.obj, 'xx', 1)
可以用來渲染當data中的obj並沒:u6709:定義a時,但在html中我們有寫入了a,原來a是不會被渲染出來的,但是這兩條語句都能使得a渲染出來;起到了類似強制重新整理的作用 -
app.$nextTick(function() {})
:常用來獲取dom更新後的資料,因為dom更新資料時非同步的,有時候並不能及時獲取到,則可用這麼方法;也可當做promise
使用Vue.nextTick() .then(function () { // DOM 更新了 })
vue的生命週期
- vue建立到掛載
beforeCreate () { this.$on('test', (a, b) => { console.log(a, b, '執行事件') }) this.$emit('test', 1, 2) //事件已完成,但dom與資料不能進行操作 }, created () { console.log(this.msg) this.msg = 888 console.log(this.msg) //能操作data中的資料但不能操作dom }, beforeMount () { console.log(this.$refs.span, '還是不能操作獲取dom') //b不能獲取dom }, //這中間會執行render函式,進行虛擬dom的渲染 //接下來菜市mounted階段 mounted () { console.log(this.$refs.span, 'mounted能進行dom的獲取與操作') }
如果new Vue()時沒有進行el的指定則不會進行beforeMount與mounted
,我們可以手動vm.$mount("#app")
如果new Vue()時有template: '<div>888</div>',或者render (h) { h('div', {}, '888')}
都會對el:#app的dom進行整體覆蓋
-
vue資料更新
beforeUpdate
與updated
當資料發生變化時會執行這兩個鉤子函式,但是一般可以通過watch與
Computed`進行監聽資料變化,執行相應操作,官方提到:
注意 updated 不會承諾所有的子元件也都一起被重繪。如果你希望等到整個檢視都重繪完畢,可以用 vm.$nextTick 替換掉 updated:
updated: function () { this.$nextTick(function () { // Code that will run only after the // entire view has been re-rendered }) }
- vue解除安裝
vm.$destroy()
螚手動觸發beforeDestroy
與destroyed
;解除安裝不是消除頁面上的dom,而是解除任何繫結
vue-data
-
data中存放著元件或者vue例項的資料;但是在
new Vue()
時,data則可以直接寫成一個物件,而在元件中時data必須為一個方法,並且
return
一個物件,這是為什麼呢?就是必須返回一個獨立的物件,防止元件之間相互影響
當元件中的data為一個物件時:因為元件時可複用的,父元件A中使用了子元件b,並且對b元件中data的值進行了改變,那麼當父元件c再次使用子元件b時也會使用被A改變了的data,這是不合理的,所以在元件中data必須為一個`function`並且返回一個物件
vue-html
<div v-html="html"></div> data: { html: '<span>888</span>'//會解析html結構並append進去 }
vue-bind
繫結dom的一些attribute
<div v-bind:class="{active: isActive}"></div>//v-bind可省略 data: { isActive: true } //或者 <div :class="classname"></div> computed: { classname () { return { active: !this.isActive } } },
computed
,watch
,methods
淺談區別
-
computed
本質就是get
方法,通常用的就是get
方法去獲取資料,該資料不用放在data
中;直接放在computed
中,通過計算通過get
方式獲取資料,預設第一次渲染就能獲取到,而不用等到重新渲染在獲取;(監聽多個data資料來get
自己想要資料,不要出現無限迴圈
)通常形式如下computed: { xx () { return 'xxx' } }
-
watch
通常用於監聽data中的資料,有兩個引數(new, old)
來改變相應的資料,看起來是一對多,與computed
的多對一有區別;而且預設第一次渲染不重新整理;可以手動handle
並且不要改自身監聽的屬性的值
watch: { xxx (new, old) { .... } }//預設第一次渲染不重新整理
watch: { xxx: { handle (new, old) { ... } }, immediate: true, deep: true//深度監聽,例如監聽obj時其中的元素髮生變化,並不會監聽到,但是deep為true時則會生效,這樣效能開銷會大 } //通過handle第一次渲染重新整理
所以我們可以使用
字串形式
,來指定監聽obj中的awatch: { 'xxx.a': {//監聽xxx物件中的a屬性 handle (new, old) { ... } }, immediate: true, } //通過handle第一次渲染重新整理
-
methods
與computed
不同,所有資料變化都會執行methods
內的方法
vue原生指令
-
v-text
等價於textContent
,v-html
等價於`innerHTML -
v-show="bool"
就是是否display:none
;v-if
,v-else-if
,v-else
是動態增刪dom會消耗效能不推薦使用 -
v-for
<div id="app"> <ul> <li v-for="(item, index) in arr" :key="item">{{item}}: {{index}}</li> </ul> <ul> <li v-for="(value, key, index) in obj" :key="key">{{key}}: {{value}} - {{index}}</li> </ul> </div> <script> Vue.config.devtools = true const vm = new Vue({ el: '#app', data: { msg: 123, obj: { 'a': 12, 'b': 34 }, arr: [1, 2, 3, 4] } }) </script>
-
v-on
繫結事件,當繫結物件不是vue例項時,實際上是使用addEventListener
進行事件新增,若是例項物件則vm.$on()
-
v-model
<div id="app"> <!-- <comp-one :value="num" @input="num = arguments[0]"></comp-one> --> <comp-one v-model="num"></comp-one> <div>{{num}}</div> </div> <script> Vue.config.devtools = true const component = { props: ['value'], template: "<input type='text' :value='value' @input='handleInput'/>", methods: { handleInput(e) { this.$emit('input', e.target.value) } } } Vue.component('CompOne', component) const vm = new Vue({ el: '#app', components: { CompOne: component }, data: { num: 1 } }) </script>
vue元件
- 建立
- 方法1:全域性建立一個元件
const component = { template: '<span>{{text}}</span>', data () { return { text: 123456 } } } Vue.component('CompOne', component) const vm = new Vue({ el: '#app', template: '<comp-one></comp-one>', })
- 元件內部建立元件
const component = { template: '<span>{{text}}</span>', data () { return { text: 123456 } } } const vm = new Vue({ el: '#app', components: { CompOne: component }, data: { arr: [1, 2, 3] } })
-
props
屬性通過父元件向子元件傳遞資料,但
props
是單項資料流,不能有子元件進行改變,需要父元件傳遞一個函式,由父元件來決定怎麼改變props
的值
<div id="app"> <comp-one :prop-one="num" :on-change="handleChange"></comp-one> //<comp-one :prop-one="num" @change="handleChange"></comp-one> </div> <script> Vue.config.devtools = true const component = { template: '<span @click="handleClick">{{propOne}}</span>', props:{ propOne: Number, onChange: Function //這便可省略用$emit }, methods: { handleClick() { this.onChange() //this,$emit('change') } } } Vue.component('CompOne', component) const vm = new Vue({ el: '#app', components: { CompOne: component }, data: { num: 1, }, methods: { handleChange() { this.num += 1 } } }) </script>
-
extend
屬性
const component = { template: '<span @click="handleClick">{{propOne}}{{text}}</span>', props:{ propOne: Number, }, data () { return { text: 888 } }, mounted () { console.log('component mounted')//先執行 }, methods: { handleClick() { // this.onChange() this.$emit('change') } } } const compVue = Vue.extend(component) //生成vue子類並擁有元件的屬性 //也可通過新建一個元件並繼承上個元件屬性(extend:component),並new Vue() new compVue({ el:'#app', propsData: { propOne: 12356//用propsData進行賦值 }, data: { text: 666//後覆蓋繼承元件的data中的值 }, mounted () { console.log('compVue mounted')//後執行 } })
vue-插槽
父元件決定放什麼內容,子元件決定放哪
- 具名插槽
<div id="app"> <comp-one> <span slot="body">具名插槽</span> <span slot="foot" slot-sc>{{value}}</span> <span slot-scope="props">{{props.value}}作用域插槽</span> </comp-one> </div> <script> Vue.config.devtools = true; const component = { template: ` <div> <div> <slot name='body'></slot> </div> <div> <slot name='foot'></slot> </div> <div> <slot :value="value"></slot> </div> </div> `, data () { return { value: 888 } } }; const vm = new Vue({ el: "#app", components: { CompOne: component }, data: { value: 666 } }); </script>