此时调用change,定时器回调修改opacity,数据修改,模板重新解析,再次调用change。
解绑(自定义)事件监听器
注意注意注意!
但如果大家的模型层数据是从后台动态响应返回的,那么你肯定会遇到这么一个问题,为什么我mounted函数中的方法获取模型层数据是空的了??
经过我查看了:Vue.js 生命周期官方介绍,我才了解到:created和mounted执行时,异步初始化还没执行(还没执行完),也就是created里的数据还没获取到,mounted就开始了渲染视图的工作,那么这时模型层数据肯定就是为空的啦,而mounted只会调用一次,这就陷入了一个死局,mounted永远等不到created获取完数据后在渲染,那么解决的方法就是为mounted中的方法设置一个定时器,因为created获取数据的速度是很快的,我们只用让mounted停那么一丢丢时间就ok了!
解决方法:设定等待一个时间,确保你的初始值都已经被初始化在渲染视图
hello,{{name}}
templat可以写在文件上部,也可以写在配置对象里面。
Vue中不使用template时:
整个root容器当作模板
Vue使用template时:
会直接替换掉root,把template当作模板进行解析。
组件不要写el属性。
1.new Vue({}),创建一个vm实例,vm.$mount('#app')挂载到app div上。
1.Vue.extend({}),创建一个组件,组件的本质是一个VueComponent构造函数。
2.cosnt s = Vue.extend({options})可以简写为const s = {options}。简写也调用了Vue.extend。
3.写组件标签时
new VueComponent({options})。
4.每次调用Vue.extend,返回的都是一个新的VueComponent。
内部sub变量接收VueComponent函数,返回sub。
vc是可复用的vm。el是vm特有的。
VueComponent.prototype.__proto__ === Vue.prototype
所以vc能够访问的Vue原型上的方法。
1.Vue.component其实内部是调用Vue.extend创建的子类构造方法,并且创建后放入Vue.options.components里面,以实现全局注册。而Vue.extend仅仅是创建子类构造方法,不放入Vue.options.components。其他细节和应用可看官方文档和网上文章。
// Vue.extend扩展子类
var subExtendClass = Vue.extend({
name: 'SubExtendClass',
data: function() {
return {
name: 'php'
};
},
template: "hi {{name}}, I'm dclnet
"
});
window.subExtendClass = subExtendClass;
console.log('Vue.extend class: subExtendClass ', subExtendClass);
// -----------------------------------------------
// Vue.component注册组件
var subComponent = Vue.component('SubComponent', {
data: function() {
return {
name: 'java'
};
},
template: "hello {{name}}, I'm dclnet
"
});
window.subComponent = subComponent;
console.log('Vue.component class: subComponent ', subComponent);
// ===============================================
// html中使用组件
window.app = new Vue({
el: '#dclnet',
// 注意:这里直接放components里面,局部注册 <<<<<
components: {'sub-extend-class': subExtendClass}
});
data需要用函数式写法
{{msg}}
Document
每次调用extend,都返回了一个VueComponent
Document
复习原型对象:
让组件vc,可以访问到Vue原型对象(一个object对象)上的属性、方法。
*查找属性和方法,会沿着隐式原型链查找。
Student.vue:
stuname:{{ stuname }}
stuage{{ stuage }}
School.vue:
schoolname:{{ schoolname }}
schoolage{{ schoolage }}
App.vue:
main.js:
import App from './App.vue';
new Vue({
el:'#root',
template:' ',
components:{
App,
}
})
index.html:
Document
在桌面创建一个demo文件夹
helloworld界面
目前需要把组件名称改为双驼峰(SchoolMsg)这种,不然会报错!!!!!!!
不要用School!!!!
asssts :静态资源
components:子组件
public :页面
流程:执行nmp run serve,进入src找到main.js,发现需要引入App.vue,然后进入App.vue,引入App里面的子组件,main完成引入App,创建Vue实例,把组件放入容器中。
不需要在页面中引入main.js,脚手架已经配置好了。
main.js:
/*
该文件为入口文件
*/
//引入vue
import Vue from 'vue'
//引入App组件 所有组件的父组件
import App from './App.vue'
//关闭vue生产提示
Vue.config.productionTip = false
//创建vue实例对象
new Vue({
//将App组件放入容器中
render: h => h(App),
}).$mount('#app')
App.vue:
index.html:
<%= htmlWebpackPlugin.options.title %>
目录结构:
编译项目:
使用template+components:
会报错,提示引入的Vue有问题:
当前引入语法(ES6模块化语法)
要么交给render函数,要么引入带有模板解析器的Vue。
当前引入的Vue版本(残缺了模板解析器):
此时接收一个函数作为参数,会在页面创建一个h1元素,效果等同于template:`
此时为什么要用render?
因为考虑到了引入的是残缺版的Vue,不能解析模板的版本。
没有用到this,进行简写。并将组件App传入。
为什么要用不完整版本的Vue,节省打包后的文件体积,模板解析器也不应该出现在打包文件里。
解析标签类型的template
在vue.config.js里面修改。
配置参考:配置参考 | Vue CLI (vuejs.org)https://cli.vuejs.org/zh/config/
标签添加ref属性,vc的一个属性会有这个dom。
对于传统的HTML标签,id 和 ref 都能实现获取dom的功能,
对于组件标签,给它加id标签时,相当于给该组件最外层容器加id,获得外层div。
添加ref时,获得的是组件实例对象。
此时vc的_data中只有msg属性
使用v-bind: 使标签引号里面的内容变为js表达式,age的值是运行引号里面表达式的结果。
props上的属性优先级大于data里面的。
{{msg}}
stuname:{{ Mystuname }}
stuage:{{ Mystuage+1 }}
stusex:{{ Mystusex }}
mixin.js
// eslint-disable-next-line no-unused-vars
export const mixin = {
methods: {
show() {
alert(this.name);
},
},
mounted() {
console.log('(mixin)挂载完毕')
},
}
// eslint-disable-next-line no-unused-vars
export const mixin2 = {
data(){
return{
x:200
}
}
}
StudentInfo.vue
{{ msg }}
stuname:{{ name }}
stuage:{{ stuage }}
SchoolInfo.vue
schoolname:{{ name }}
schoolage{{ schoolage }}
全局引入混入:
/*
该文件为入口文件
*/
//引入vue
import Vue from 'vue'
//引入App组件 所有组件的父组件
import App from './App.vue'
//全局引入混合 vm vc 都能用
// eslint-disable-next-line no-unused-vars
//import {mixin,mixin2} from './components/mixin';
//关闭vue生产提示
Vue.config.productionTip = false
//Vue.mixin(mixin)
//Vue.mixin(mixin2)
//创建vue实例对象
new Vue({
//将App组件放入容器中
render: h => h(App),
}).$mount('#app')
在 main.js引入并应用插件:
定义一个插件,其中定义了全局过滤器、全局自定义指令、全局混入、Vue原型对象方法。vm和vc都能用。
plugins.js:
// eslint-disable-next-line no-unused-vars
export default {
install(Vue,x){
console.log(x)//1
//全局过滤器
Vue.filter('mySlice',function(value){
return value.slice(0,4);
});
//定义全局自定义指令
//指令语法就是操作dom元素的属性,内容,绑定事件。
Vue.directive('fbind', {
//指令与元素成功绑定时调用(一上来就调用)
bind(el, binding) {
el.value = binding.value;
},
//指令所在元素插入页面时调用
inserted(el) {
//默认获取焦点
el.focus();
},
//指令所在模板重新解析时调用
update(el, binding) {
el.value = binding.value;
},
});
//全局混入
Vue.mixin({
data(){
return{
x:100,
y:200,
}
},
methods: {
show(){
alert(this.y);
}
},
});
//给Vue原型添加方法
//vm和vc都能用
Vue.prototype.hello = ()=>{
alert("hello");
}
}
}
SchoolInfo.vue:
schoolname:{{ name|mySlice }}
schoolage{{ schoolage }}
StudentInfo.vue
{{ msg }}
stuname:{{ name }}
stuage:{{ stuage }}
使两个子组件的class可以重名,并且效果不同。
查看并安装less-loader