el:
data:
methods:
computed:
watch
包含多个属性监视的对象
分为一般监视和深度监视
xxx:function(value){}
xxx:{
deep:true,
handler:fun(value)
}
另一种添加监视方法:vm.$watch(‘xxx’,function(value){})
vue-cli:vue脚手架
vue-resouce(axios):ajax请求
vue-route:路由
vuex:状态管理
vue-lazyload:图片懒加载
vue-scoller:页面滑动相关
mint-ui:基于vue的UI组件库(移动端)
element-ui:基于vue的UI组件库(PC端)
<html lang="en">
<head>
<meta charset="UTF-8">
<title>01_HelloWorldtitle>
head>
<body>
<div id="test">
<input type="text" v-model="msg"><br>
<input type="text" v-model="msg">
<p>Hello {{msg}}p>
div>
<script type="text/javascript" src="../js/vue.js">script>
<script type="text/javascript">
const vm = new Vue({ // 配置对象 options
// 配置选项(option)
el: '#test', // element: 选择器,指定用vue来管理页面中的哪个标签区域
data: {
msg: 'World'
}
})
script>
body>
html>
打开Vue页面,F12进入开发者调试,选择Vue,即可使用该调试工具。
<html lang="en">
<head>
<meta charset="UTF-8">
<title>模板语法title>
head>
<body>
<div id="app">
<h2>1. 双大括号表达式h2>
<p>{{content}}p>
<p>{{content.toUpperCase()}}p>
<h2>2. 指令一: 强制数据绑定h2>
<a href="url">访问指定站点a><br>
<a v-bind:href="url">访问指定站点2a><br>
<a :href="url">访问指定站点2a><br>
<h2>3. 指令二: 绑定事件监听h2>
<button v-on:click="test">点我button>
<button @click="test">点我button>
div>
<script type="text/javascript" src="../js/vue.js">script>
<script type="text/javascript">
new Vue({
el: '#app',
data: {
content: 'NBA I Love This Game',
url: 'http://www.baidu.com'
},
methods: {
test () {
alert('好啊!!!')
}
}
})
script>
body>
html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>计算属性和监视title>
head>
<body>
<div id="demo">
姓: <input type="text" placeholder="First Name" v-model="firstName"><br>
名: <input type="text" placeholder="Last Name" v-model="lastName"><br>
姓名1(单向): <input type="text" placeholder="Full Name1" v-model="fullName1"><br>
姓名2(单向): <input type="text" placeholder="Full Name2" v-model="fullName2"><br>
姓名3(双向): <input type="text" placeholder="Full Name3" v-model="fullName3"><br>
<p>{{fullName1}}p>
<p>{{fullName1}}p>
div>
<script type="text/javascript" src="../js/vue.js">script>
<script type="text/javascript">
const vm = new Vue({
el: '#demo',
data: {
firstName: 'A',
lastName: 'B',
fullName2: 'A-B'
},
// 计算属性配置: 值为对象
computed: {
//什么时候执行:初始化显示/相关的data属性发生变化
fullName1 () { // 属性的get()
console.log('fullName1()', this)
return this.firstName + '-' + this.lastName
},
fullName3: {
// 回调函数的三个属性:1.你定义的 2.你没有调用 3.但是它执行了
// 回调函数:什么时候调用?用来做什么
// 当获取当前属性值时自动调用, 将返回值(根据相关的其它属性数据)作为属性值
get () {
console.log('fullName3 get()')
return this.firstName + '-' + this.lastName
},
// 当属性值发生了改变时自动调用, 监视当前属性值变化, 同步更新相关的其它属性值
set (value) {// fullName3的最新value值 A-B23
console.log('fullName3 set()', value)
// 更新firstName和lastName
const names = value.split('-')
this.firstName = names[0]
this.lastName = names[1]
}
}
},
watch: {
// 配置监视firstName
firstName: function (value) { // firstName发生了变化,相当于属性的set
console.log('watch firstName', value)
// 更新fullName2
this.fullName2 = value + '-' + this.lastName
}
}
})
// 监视lastName
vm.$watch('lastName', function (value) {
console.log('$watch lastName', value)
// 更新fullName2
this.fullName2 = this.firstName + '-' + value
})
script>
body>
html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>class与style绑定title>
<style>
.classA {
color: red;
}
.classB {
background: blue;
}
.classC {
font-size: 20px;
}
style>
head>
<body>
<div id="demo">
<h2>1. class绑定: :class='xxx'h2>
<p :class="myClass">xxx是字符串p>
<p :class="{classA: hasClassA, classB: hasClassB}">xxx是对象p>
<p :class="['classA', 'classB']">xxx是数组p>
<h2>2. style绑定h2>
<p :style="{color:activeColor, fontSize}">:style="{ color: activeColor, fontSize: fontSize + 'px' }"p>
<button @click="update">更新button>
div>
<script type="text/javascript" src="../js/vue.js">script>
<script type="text/javascript">
new Vue({
el: '#demo',
data: {
myClass: 'classA',
hasClassA: true,
hasClassB: false,
activeColor: 'red',
fontSize: '20px'
},
methods: {
update () {
this.myClass = 'classB'
this.hasClassA = !this.hasClassA
this.hasClassB = !this.hasClassB
this.activeColor = 'yellow'
this.fontSize = '30px'
}
}
})
script>
body>
html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>条件渲染title>
head>
<body>
<div id="demo">
<p v-if="ok">表白成功p>
<p v-else>表白失败p>
<hr>
<p v-show="ok">求婚成功p>
<p v-show="!ok">求婚失败p>
<button @click="ok=!ok">切换button>
div>
<script type="text/javascript" src="../js/vue.js">script>
<script type="text/javascript">
new Vue({
el: '#demo',
data: {
ok: true,
}
})
script>
body>
html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>列表渲染title>
head>
<body>
<div id="demo">
<h2>测试: v-for 遍历数组h2>
<ul>
<li v-for="(p, index) in persons" :key="index">
{{index}}--{{p.name}}--{{p.age}}
--<button @click="deleteP(index)">删除button>
--<button @click="updateP(index, {name:'Cat', age: 16})">更新button>
li>
ul>
<button @click="addP({name: 'xfzhang', age: 18})">添加button>
<h2>测试: v-for 遍历对象h2>
<ul>
<li v-for="(item, key) in persons[1]" :key="key">{{key}}={{item}}li>
ul>
div>
<script type="text/javascript" src="../js/vue.js">script>
<script type="text/javascript">
new Vue({
el: '#demo',
data: {
persons: [
{name: 'Tom', age:18},
{name: 'Jack', age:17},
{name: 'Bob', age:19},
{name: 'Mary', age:16}
]
},
methods: {
deleteP (index) {
this.persons.splice(index, 1) // 调用了不是原生数组的splice(), 而是一个变异(重写)方法
// 1. 调用原生的数组的对应方法
// 2. 更新界面
},
updateP (index, newP) {
console.log('updateP', index, newP)
// this.persons[index] = newP // vue根本就不知道
this.persons.splice(index, 1, newP)
// this.persons = []
},
addP (newP) {
this.persons.push(newP)
}
}
})
script>
body>
html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>过滤与排序title>
head>
<body>
<div id="demo">
<input type="text" v-model="searchName">
<ul>
<li v-for="(p, index) in filterPersons" :key="index">
{{index}}--{{p.name}}--{{p.age}}
li>
ul>
<div>
<button @click="setOrderType(2)">年龄升序button>
<button @click="setOrderType(1)">年龄降序button>
<button @click="setOrderType(0)">原本顺序button>
div>
div>
<script type="text/javascript" src="../js/vue.js">script>
<script type="text/javascript">
new Vue({
el: '#demo',
data: {
searchName: '',
orderType: 0, // 0代表不排序, 1代表降序, 2代表升序
persons: [
{name: 'Tom', age:18},
{name: 'Jack', age:17},
{name: 'Bob', age:19},
{name: 'Mary', age:16}
]
},
computed: {
filterPersons () {
// debugger
// 取出相关数据
const {searchName, persons, orderType} = this
let arr = [...persons]
// 过滤数组
if(searchName.trim()) {
arr = persons.filter(p => p.name.indexOf(searchName)!==-1)
}
// 排序
if(orderType) {
arr.sort(function (p1, p2) {
if(orderType===1) { // 降序
return p2.age-p1.age
} else { // 升序
return p1.age-p2.age
}
})
}
return arr
}
},
methods: {
setOrderType (orderType) {
this.orderType = orderType
}
}
})
script>
body>
html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>07_事件处理title>
head>
<body>
<div id="example">
<h2>1. 绑定监听h2>
<button @click="test1">test1button>
<button @click="test2('abc')">test2button>
<button @click="test3('abcd', $event)">test3button>
<h2>2. 事件修饰符h2>
<a href="http://www.baidu.com" @click.prevent="test4">百度一下a>
<div style="width: 200px;height: 200px;background: red" @click="test5">
<div style="width: 100px;height: 100px;background: blue" @click.stop="test6">div>
div>
<h2>3. 按键修饰符h2>
<input type="text" @keyup.13="test7">
<input type="text" @keyup.enter="test7">
div>
<script type="text/javascript" src="../js/vue.js">script>
<script type="text/javascript">
new Vue({
el: '#example',
data: {
},
methods: {
test1(event) {
alert(event.target.innerHTML)
},
test2 (msg) {
alert(msg)
},
test3 (msg, event) {
alert(msg+'---'+event.target.textContent)
},
test4 () {
alert('点击了链接')
},
test5 () {
alert('out')
},
test6 () {
alert('inner')
},
test7 (event) {
console.log(event.keyCode)
alert(event.target.value)
}
}
})
script>
body>
html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>表单输入绑定title>
head>
<body>
<div id="demo">
<form action="/xxx" @submit.prevent="handleSubmit">
<span>用户名: span>
<input type="text" v-model="username"><br>
<span>密码: span>
<input type="password" v-model="pwd"><br>
<span>性别: span>
<input type="radio" id="female" value="女" v-model="sex">
<label for="female">女label>
<input type="radio" id="male" value="男" v-model="sex">
<label for="male">男label><br>
<span>爱好: span>
<input type="checkbox" id="basket" value="basket" v-model="likes">
<label for="basket">篮球label>
<input type="checkbox" id="foot" value="foot" v-model="likes">
<label for="foot">足球label>
<input type="checkbox" id="pingpang" value="pingpang" v-model="likes">
<label for="pingpang">乒乓label><br>
<span>城市: span>
<select v-model="cityId">
<option value="">未选择option>
<option :value="city.id" v-for="(city, index) in allCitys" :key="city.id">{{city.name}}option>
select><br>
<span>介绍: span>
<textarea rows="10" v-model="info">textarea><br><br>
<input type="submit" value="注册">
form>
div>
<script type="text/javascript" src="../js/vue.js">script>
<script type="text/javascript">
new Vue({
el: '#demo',
data: {
username: '',
pwd: '',
sex: '男',
likes: ['foot'],
allCitys: [{id: 1, name: 'BJ'}, {id: 2, name: 'SS'}, {id: 3, name: 'SZ'}],
cityId: '2',
info: ''
},
methods: {
handleSubmit () {
console.log(this.username, this.pwd, this.sex, this.likes, this.cityId, this.info)
alert('提交注册的ajax请求')
}
}
})
script>
body>
html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>生命周期title>
head>
<body>
<div id="test">
<button @click="destroyVue">destory vuebutton>
<p v-if="isShow">尚硅谷IT教育p>
div>
<script type="text/javascript" src="../js/vue.js">script>
<script type="text/javascript">
new Vue({
el: '#test',
data: {
isShow: true
},
beforeCreate() {
console.log('beforeCreate()')
},
created() {
console.log('created()')
},
beforeMount() {
console.log('beforeMount()')
},
mounted () {
console.log('mounted()')
// 执行异步任务
this.intervalId = setInterval(() => {
console.log('-----')
this.isShow = !this.isShow
}, 1000)
},
beforeUpdate() {
console.log('beforeUpdate()')
},
updated () {
console.log('updated()')
},
beforeDestroy() {
console.log('beforeDestroy()')
// 执行收尾的工作
clearInterval(this.intervalId)
},
destroyed() {
console.log('destroyed()')
},
methods: {
destroyVue () {
this.$destroy()
}
}
})
script>
body>
html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>过渡&动画title>
<style>
/*指定过渡样式*/
.xxx-enter-active, .xxx-leave-active {
transition: opacity 1s
}
/*指定隐藏时的样式*/
.xxx-enter, .xxx-leave-to {
opacity: 0;
}
.move-enter-active {
transition: all 1s
}
.move-leave-active {
transition: all 3s
}
.move-enter, .move-leave-to {
opacity: 0;
transform: translateX(20px)
}
style>
head>
<body>
<div id="demo">
<button @click="show = !show">Togglebutton>
<transition name="xxx">
<p v-show="show">hellop>
transition>
div>
<hr>
<div id="demo2">
<button @click="show = !show">Toggle2button>
<transition name="move">
<p v-show="show">hellop>
transition>
div>
<script type="text/javascript" src="../js/vue.js">script>
<script type="text/javascript">
new Vue({
el: '#demo',
data: {
show: true
}
})
new Vue({
el: '#demo2',
data: {
show: true
}
})
script>
body>
html>
Vue.filter(filterName,function(value[,arg1,arg2,....])){
// 进行一定的数据处理
return new Value
}
<div>{{myData|filterName}}</div>
<div>{{myData|filterName(arg)}}</div>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>过滤器title>
head>
<body>
<div id="test">
<h2>显示格式化的日期时间h2>
<p>{{time}}p>
<p>最完整的: {{time | dateString}}p>
<p>年月日: {{time | dateString('YYYY-MM-DD')}}p>
div>
<script type="text/javascript" src="../js/vue.js">script>
<script type="text/javascript" src="https://cdn.bootcss.com/moment.js/2.22.1/moment.js">script>
<script>
// 定义过滤器
Vue.filter('dateString', function (value, format='YYYY-MM-DD HH:mm:ss') {
return moment(value).format(format);
})
new Vue({
el: '#test',
data: {
time: new Date()
},
mounted () {
setInterval(() => {
this.time = new Date()
}, 1000)
}
})
script>
body>
html>
Vue.directive('my-directive',function(el,binding){
el.innerHTML = binding.value.toupperCase()
})
directives:{
'my-directive':{
bind(el,binding){
el.innerHTML = binding.value.toupperCase()
}
}
}
v-my-directive='xxx'
<html lang="en">
<head>
<meta charset="UTF-8">
<title>内置指令title>
<style>
[v-cloak] { display: none }
style>
head>
<body>
<div id="example">
<p v-cloak>{{content}}p>
<p v-text="content">p>
<p v-html="content">p>
<p ref="msg">abcdp>
<button @click="hint">提示button>
div>
<script type="text/javascript" src="../js/vue.js">script>
<script type="text/javascript">
new Vue({
el: '#example',
data: {
content: '百度一下'
},
methods: {
hint () {
alert(this.$refs.msg.innerHTML)
}
}
})
script>
body>
html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>自定义指令title>
head>
<body>
<div id="test">
<p v-upper-text="msg">p>
<p v-lower-text="msg">p>
div>
<div id="test2">
<p v-upper-text="msg">p>
<p v-lower-text="msg">p>
div>
<script type="text/javascript" src="../js/vue.js">script>
<script type="text/javascript">
// 注册一个全局指令
// el: 指令所在的标签对象
// binding: 包含指令相关数据的容器对象
Vue.directive('upper-text', function (el, binding) {
console.log(el, binding)
el.textContent = binding.value.toUpperCase()
})
new Vue({
el: '#test',
data: {
msg: "I Like You"
},
// 注册局部指令
directives: {
'lower-text'(el, binding) {
console.log(el, binding)
el.textContent = binding.value.toLowerCase()
}
}
})
new Vue({
el: '#test2',
data: {
msg: "I Like You Too"
}
})
script>
body>
html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>插件title>
head>
<body>
<div id="test">
<p v-my-directive="msg">p>
div>
<script type="text/javascript" src="../js/vue.js">script>
<script type="text/javascript" src="vue-myPlugin.js">script>
<script type="text/javascript">
// 声明使用插件(安装插件: 调用插件的install())
Vue.use(MyPlugin) // 内部会调用插件对象的install()
const vm = new Vue({
el: '#test',
data: {
msg: 'HaHa'
}
})
Vue.myGlobalMethod()
vm.$myMethod()
new Object()
script>
body>
html>
output:{
publicPath:'/xxx/' //打包文件夹的名称
}
'rules':{
'no-new':1
}
/* eslint-disable no-new*/
new Vue({
el:'#body',
components:{App}
})
*.js
*.vue
<template>
页面模板
</template>
<script>
export default{
data(){//模板里面只能写方法
return:{
}
},
methods:{},
computed:{}.
components:{}
}
</script>
<style>
样式定义
</style>
<template>
<div>
<img src="./assets/logo.png" alt="logo" />
<!-- 3.使用组件标签 -->
<HelloWorld />
</div>
</template>
<script>
//1.引入组件
import HelloWorld from './components/HelloWorld.vue'
export default {
// 2.映射组件标签
components:{
HelloWorld
}
}
</script>
<style scoped>
</style>
<my-component name='tom' :age='3' :set-name='setName'></my-component>
props:['name','age','setName']
props:{
name:String,
age:Number,
setName:Function
}
props:{
name:{type:String,required:true,default:xxx}
}
//方式一:通过v-on绑定
@delete_to="deleteTodo"
//方式二:通过$on()
this.$refs.xxx.$on('delete_todo',function(todo)){
this.deleteTodo(todo)
}
//触发事件
this.$emit(eventName,data)
PubSub.subscribt('msg',function(msg,data){})
PubSub.publish('msg',data)
优点:此方式可实现任意关系组件间的通信(数据)
此方式用于父组件向子组件传递“标签数据”
<template>
<div>
<slot name="xxx">不确定的标签结构1slot>
<div>
组件不确定的标签结构
div>
<slot name="yyy">不确定的标签结构2slot>
div>
template>
<child>
<div slot="xxx">
xxx对应的标签结构
div>
<div slot="yyy">
yyy对应的标签结构
div>
child>
vue插件,非官方库,vue1.x使用广泛
通用的Ajax请求库,官方推荐,vue2.x使用广泛
https://github.com/pagekit/vue-resource/blob/develop/docs/http.md
npm install vue-resource --save
// 引入模块
import VueResource from 'vue-resource'
// 使用插件
Vue.use(VueResource)
// 通过vue组件对象发送ajax请求
this.$http.get('/someURL').then(response)=>{
//请求成功的数据
console.log(response.data)//返回结果数据
},(response)=>{
//错误信息
console.log(response.statusText)//错误信息
}
npm install axios --save
// 引入模块
import axios from 'axios'
//发送Ajax请求
axios.get(url).then(response=>{
console.log(response.data)//得到返回结果数据
}).catch(error=>{
console.log(error.message)//错误信息
})
npm install --save mint-ui
// 下载
npm install --save-dev babel-plugin-component
// 修改babel配置
"plugins":["transform-runtime",["component",{
"libraryName":"mint-ui",
"style":true
}]]
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,minimm-scale=1,user-scalable=no" />
<script src="https://as.alipayobjects.com/g/component/fastclick/1.0.6/fastclick.js">script>
<script>
if('addEventListener' in document){
document.addEventListener('DOMContentLoaded',function(){
FastClick.attach(document.body);
},false);
}
if(!window.Promise){
document.writelv('<script src="https://as.alipayobjects.com/g/component/fastclick/1.0.6/fastclick.js">script>')
}
script>
import {Button} from 'mint-ui'
Vue.component(Button.name,Button)
<template>
<mt-button @click="handleClick" type="primary" style="width:100%">Testmt-button>
template>
<script>
import {Toast} from 'mint-ui'
export default{
methods:{
handleClick(){
Toast('点击了测试');
}
}
}
script>
new VueRouter({
//多个配置项
})
routes:[
{//一般路由
path:'/about',
component:About
},
{//自动跳转路由
path:'/',
redirect:'/about'
}
]
import router from './router'
new Vue({
router
})
1.<router-link>:用来生成路由链接
<router-link to='/xxx'>Go To XXXrouter-link>
2.<router-view>:用来显示当前路由组件界面
<router-view>router-view>
文件夹命名:pages/views
示例路由组件:Home.vue/About.vue
<div>
<router-linke to="/about">Aboutrouter-linke>
div>
export default new VueRouter({
routes:[
{
path:'/',
redirect:'/about'
},
{
path:'/about',
component:About
},
{
path:'/home',
component:Home
}
]
})
import Vue from 'vue'
import router from './router'
// 创建vue配置路由器
new Vue({
el:'#app',
router,
render:h=>h(app)
})
linkActiveClass:‘active’;//指定选中的路由链接的class
News.vue
Message.vue
path:'/home',
component:hoem,
children:[
{
path:'/home/news',
component:News
},
{
path:'message',//简化写法
component:Message
}
]
<router-link to="/home/news">Newsrouter-link>
<router-link to="/home/message">Messagerouter-link>
<router-view>router-view>
<keep-alive>
<router-view>router-view>
keep-alive>
children:[
{
path:'mdetail/:id',
component:MessageDetail
}
]
<router-link :to="'/home/message/mdetail/'+m.id">{{m.title}}router-link>
this.$route.params.id
pushShow (id) {
this.$router.push(`/home/message/detail/${id}`)
}
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="test">MVVMddiv>
<ul id="fragment_test">
<li>test1li>
<li>test2li>
<li>test3li>
ul>
<script type="text/javascript">
//1. [].slice.call(lis): 根据伪数组生成对应的真数组
const lis = document.getElementsByTagName('li') // lis是伪数组(是一个特别的对象, length和数值下标属性)
console.log(lis instanceof Object, lis instanceof Array)
// 数组的slice()截取数组中指定部分的元素, 生成一个新的数组 [1, 3, 5, 7, 9], slice(0, 3)
// slice2()
Array.prototype.slice2 = function (start, end) {
start = start || 0
end = start || this.length
const arr = []
for (var i = start; i < end; i++) {
arr.push(this[i])
}
return arr
}
const lis2 = Array.prototype.slice.call(lis) // lis.slice()
console.log(lis2 instanceof Object, lis2 instanceof Array)
// lis2.forEach()
//2. node.nodeType: 得到节点类型
const elementNode = document.getElementById('test')
const attrNode = elementNode.getAttributeNode('id')
const textNode = elementNode.firstChild
console.log(elementNode.nodeType, attrNode.nodeType, textNode.nodeType)
//3. Object.defineProperty(obj, propertyName, {}): 给对象添加属性(指定描述符)
const obj = {
firstName: 'A',
lastName: 'B'
}
//obj.fullName = 'A-B'
Object.defineProperty(obj, 'fullName', {
// 属性描述符:
// 数据描述符
//访问描述符
// 当读取对象此属性值时自动调用, 将函数返回的值作为属性值, this为obj
get () {
return this.firstName + "-" + this.lastName
},
// 当修改了对象的当前属性值时自动调用, 监视当前属性值的变化, 修改相关的属性, this为obj
set (value) {
const names = value.split('-')
this.firstName = names[0]
this.lastName = names[1]
}
})
console.log(obj.fullName) // A-B
obj.fullName = 'C-D'
console.log(obj.firstName, obj.lastName) // C D
Object.defineProperty(obj, 'fullName2', {
configurable: false, //是否可以重新define
enumerable: true, // 是否可以枚举(for..in / keys())
value: 'A-B', // 指定初始值
writable: false // value是否可以修改
})
console.log(obj.fullName2) // A-B
obj.fullName2 = 'E-F'
console.log(obj.fullName2) // A-B
/*Object.defineProperty(obj, 'fullName2', {
configurable: true,
enumerable: true,
value: 'G-H',
writable: true
})*/
//4. Object.keys(obj): 得到对象自身可枚举属性组成的数组
const names = Object.keys(obj)
console.log(names)
//5. obj.hasOwnProperty(prop): 判断prop是否是obj自身的属性
console.log(obj.hasOwnProperty('fullName'), obj.hasOwnProperty('toString')) // true false
//6. DocumentFragment: 文档碎片(高效批量更新多个节点)
// document: 对应显示的页面, 包含n个elment 一旦更新document内部的某个元素界面更新
// documentFragment: 内存中保存n个element的容器对象(不与界面关联), 如果更新framgnet中的某个element, 界面不变
/*
- test1
- test2
- test3
*/
const ul = document.getElementById('fragment_test')
// 1. 创建fragment
const fragment = document.createDocumentFragment()
// 2. 取出ul中所有子节点取出保存到fragment
let child
while(child=ul.firstChild) { // 一个节点只能有一个父亲
fragment.appendChild(child) // 先将child从ul中移除, 添加为fragment子节点
}
// 3. 更新fragment中所有li的文本
Array.prototype.slice.call(fragment.childNodes).forEach(node => {
if (node.nodeType===1) { // 元素节点
node.textContent = 'atguigu'
}
})
// 4. 将fragment插入ul
ul.appendChild(fragment)
script>
body>
html>
代码实现:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>数据代理title>
head>
<body>
<div id="test">div>
<script type="text/javascript" src="js/mvvm/compile.js">script>
<script type="text/javascript" src="js/mvvm/mvvm.js">script>
<script type="text/javascript" src="js/mvvm/observer.js">script>
<script type="text/javascript" src="js/mvvm/watcher.js">script>
<script type="text/javascript">
const vm = new MVVM({
el: "#test",
data: {
name: '张三2'
}
})
console.log(vm.name) // 读取的是data中的name, vm代理对data的读操作
vm.name = '李四2' // 数据保存到data中的name上, vm代理对data的写操作
console.log(vm.name, vm._data.name)
script>
body>
html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>模板解析_表达式_vuetitle>
head>
<body>
<div id="test">
<p>{{name}}p>
div>
<script type="text/javascript" src="js/mvvm/compile.js">script>
<script type="text/javascript" src="js/mvvm/mvvm.js">script>
<script type="text/javascript" src="js/mvvm/observer.js">script>
<script type="text/javascript" src="js/mvvm/watcher.js">script>
<script type="text/javascript">
new MVVM({
el: '#test',
data: {
name: 'SADAMU'
}
})
script>
body>
html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>模板解析_事件指令title>
head>
<body>
<div id="test">
<button v-on:click="test">测试button>
div>
<script type="text/javascript" src="js/mvvm/compile.js">script>
<script type="text/javascript" src="js/mvvm/mvvm.js">script>
<script type="text/javascript" src="js/mvvm/observer.js">script>
<script type="text/javascript" src="js/mvvm/watcher.js">script>
<script type="text/javascript">
new MVVM({
el: '#test',
data: {
msg: 'hello atguigu'
},
methods: {
test () {
alert(this.msg)
}
}
})
script>
body>
html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>模板解析_一般指令title>
<style>
.aclass {
color: red;
}
.bClass {
font-size: 30px;
}
style>
head>
<body>
<div id="test">
<p v-text="msg">p>
<p v-html="msg">p>
<p class="bClass" v-class="myClass">xxxxxxp>
div>
<script type="text/javascript" src="js/mvvm/compile.js">script>
<script type="text/javascript" src="js/mvvm/mvvm.js">script>
<script type="text/javascript" src="js/mvvm/observer.js">script>
<script type="text/javascript" src="js/mvvm/watcher.js">script>
<script type="text/javascript">
new MVVM({
el: '#test',
data: {
msg: '尚硅谷',
myClass: 'aclass'
},
methods: {
test () {
alert(this.msg)
}
}
})
script>
body>
html>
一旦更新了data中的某个属性数据,所有界面上直接使用或间接使用此属性的节点更新
Observer
Dep(Depend)
data中的每个属性(所有层次)都对应一个dep对象
创建的时机
对象的结构
{
id,//每个dep都有一个唯一的id
subs//包含n个对应watcher的数组(subscribes的简写)
}
subs属性说明
Compiler
Watcher
模板中每个非事件指令或表达式都对应一个watcher对象
监视当前表达式数据的变化
创建的时机:在初始化编译模板时
对象的组成
{
vm,//vm对象
exp,//对应指令的表达式
cb,//当表达式所对应的数据发生改变的回调函数
value,//表达式当前的值
depIds//表达式中各级属性所对应的dep对象的集合对象
//属性名为dep的id,属性值为dep
}
总结:dep与watcher的关系:多对多
代码实现
<html>
<head>
<meta charset="UTF-8">
<title>数据劫持-数据绑定title>
head>
<body>
<div id="test">
<p>{{name}}p>
<p v-text="name">p>
<p v-text="wife.name">p>
<button v-on:click="update">更新button>
div>
<script type="text/javascript" src="js/mvvm/compile.js">script>
<script type="text/javascript" src="js/mvvm/mvvm.js">script>
<script type="text/javascript" src="js/mvvm/observer.js">script>
<script type="text/javascript" src="js/mvvm/watcher.js">script>
<script type="text/javascript">
new MVVM({
el: '#test',
data: {
name: 'sadamu', // dep0
wife: { // dep1
name: 'binbin', // dep2
age: 18 // dep3
}
},
methods: {
update () {
this.name = 'avatar'
}
}
})
script>
body>
html>
代码实现
<html>
<head>
<meta charset="UTF-8">
<title>数据双向绑定title>
head>
<body>
<div id="test">
<input type="text" v-model="msg">
<p>{{msg}}p>
div>
<script type="text/javascript" src="js/mvvm/compile.js">script>
<script type="text/javascript" src="js/mvvm/mvvm.js">script>
<script type="text/javascript" src="js/mvvm/observer.js">script>
<script type="text/javascript" src="js/mvvm/watcher.js">script>
<script type="text/javascript">
new MVVM({
el: '#test',
data: {
msg: 'haha'
}
})
script>
body>
html>
vuex管理的状态对象
它应该是唯一的
const state={
xxx:initValue
}
包含多个直接更新state的方法(回调函数)的对象
谁来触发:action中的commit(‘mutation名称’)
只能包含同步的代码,不能写异步代码
const mutations={
yyy(state,{data1}){
//更新state的某个属性
}
}
包含多个事件回调函数的对象
通过执行:commit()来触发mutation的调用,间接更新state
谁来触发:组件中:$store.dispatch(‘action名称’,data1) //‘zzz’
可以包含异步代码(定时器,ajax)
const actions={
zzz({commit,state},data1){
commit('yyy',{data1})
}
}
包含多个计算属性(get)的对象
谁来读取:组件中:$store.getters.xxx
const getters={
mmm(state){
return ...
}
}
export default new Vuex.Store({
state,
mutations,
actions,
getters
})
import {mapState,mapGetters,mapActions} from 'vuex'
export default{
computed:{
...mapState(['xxx']),
...mapGetters(['mmm']),
},
methods:mapActions(['zzz'])
}
{{xxx}}{{mmm}}@click="zzz(data)"
import store from './store'
new Vue({
store
})
代码实现
<html>
<head>
<meta charset="UTF-8">
<title>数据双向绑定title>
head>
<body>
<div id="test">
<input type="text" v-model="msg">
<p>{{msg}}p>
div>
<script type="text/javascript" src="js/mvvm/compile.js">script>
<script type="text/javascript" src="js/mvvm/mvvm.js">script>
<script type="text/javascript" src="js/mvvm/observer.js">script>
<script type="text/javascript" src="js/mvvm/watcher.js">script>
<script type="text/javascript">
new MVVM({
el: '#test',
data: {
msg: 'haha'
}
})
script>
body>
html>
[外链图片转存中…(img-44Q93wcS-1590936591436)]
vuex管理的状态对象
它应该是唯一的
const state={
xxx:initValue
}
包含多个直接更新state的方法(回调函数)的对象
谁来触发:action中的commit(‘mutation名称’)
只能包含同步的代码,不能写异步代码
const mutations={
yyy(state,{data1}){
//更新state的某个属性
}
}
包含多个事件回调函数的对象
通过执行:commit()来触发mutation的调用,间接更新state
谁来触发:组件中:$store.dispatch(‘action名称’,data1) //‘zzz’
可以包含异步代码(定时器,ajax)
const actions={
zzz({commit,state},data1){
commit('yyy',{data1})
}
}
包含多个计算属性(get)的对象
谁来读取:组件中:$store.getters.xxx
const getters={
mmm(state){
return ...
}
}
export default new Vuex.Store({
state,
mutations,
actions,
getters
})
import {mapState,mapGetters,mapActions} from 'vuex'
export default{
computed:{
...mapState(['xxx']),
...mapGetters(['mmm']),
},
methods:mapActions(['zzz'])
}
{{xxx}}{{mmm}}@click="zzz(data)"
import store from './store'
new Vue({
store
})
这篇权当是学习Vue的一个基础,更多内容,我打算做一个网站,遇到了再更新吧。