<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事件javascript
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并没🈶定义a时,但在html中咱们有写入了a,原来a是不会被渲染出来的,可是这两条语句都能使得a渲染出来;起到了相似强制刷新的做用app.$nextTick(function() {})
:经常使用来获取dom更新后的数据,由于dom更新数据时异步的,有时候并不能及时获取到,则可用这么方法;也可当作promise
使用html
Vue.nextTick() .then(function () { // DOM 更新了 })
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 }) }
vm.$destroy()
螚手动触发beforeDestroy
与destroyed
;卸载不是消除页面上的dom,而是解除任何绑定java
data中存放着组件或者vue实例的数据;可是在new Vue()
时,data则能够直接
写成一个对象,而在组件中时data必须为一个方法,而且return
一个对象,这是为何呢?
就是必须返回一个独立的对象,防止组件之间相互影响npm
当组件中的data为一个对象时:由于组件时可复用的,父组件A中使用了子组件b,而且对b组件中data的值进行了改变,那么当父组件c再次使用子组件b时也会使用被A改变了的data,这是不合理的,因此在组件中data必须为一个`function`而且返回一个对象
<div v-html="html"></div> data: { html: '<span>888</span>' //会解析html结构并append进去 }
绑定dom的一些attribute
promise
<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
本身想要数据,不要出现无限循环
)一般形式以下app
computed: { xx () { return 'xxx' } }
watch
一般用于监听data中的数据,有两个参数(new, old)
来改变相应的数据,看起来是一对多,与computed
的多对一有区别;并且默认第一次渲染不刷新;能够手动handle
而且不要改自身监听的属性的值
dom
watch: { xxx (new, old) { .... } } //默认第一次渲染不刷新
watch: { xxx: { handle (new, old) { ... } }, immediate: true, deep: true //深度监听,例如监听obj时其中的元素发生变化,并不会监听到,可是deep为true时则会生效,这样性能开销会大 } //经过handle第一次渲染刷新
因此咱们可使用字符串形式
,来指定监听obj中的a异步
watch: { 'xxx.a': { //监听xxx对象中的a属性 handle (new, old) { ... } }, immediate: true, } //经过handle第一次渲染刷新
methods
computed
不一样,全部数据变化都会执行methods
内的方法v-text
等价于textContent
,v-html
等价于`innerHTMLv-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>
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') //后执行 } })
父组件决定放什么内容,子组件决定放哪函数
<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>