尚硅谷Vue学习第三章下篇(Todo-list案例)

目录

1.分析Vue脚手架

School.vue

student.vue

App.vue

main.js 

2.ref属性

School.vue

App.vue

main.js 

3.props配置

Student.vue

App.vue

main.js

4.mixin混入

School.vue

Student.vue

App.vue

main.js

mixin.js

5.插件

School.vue

Student.vue

App.vue

main.js

plugins.js

6.scoped样式

7.TodoList案例

MyFooter.vue

MyHeader.vue

MyItem.vue

MyList.vue

App.vue

main.js

8.浏览器本地存储 

LocalStorage

SessionStorage

笔记

脚手架文件结构

关于不同版本的Vue:

vue.config.js配置文件

ref属性

配置项props

mixin(混入)

插件

scoped样式

Todo-List案例

webstorage


1.分析Vue脚手架

School.vue

<template>
	<!-- 组件的结构 -->
	<div class="demo">
		<h2>学校名称:{{schoolName}}</h2>
		<h2>学校地址:{{address}}</h2>
		<button @click="showName">点我提示学校名</button>
	</div>
</template>

<script>
	//组件交互相关的代码(数据,方法等等)
	
	export default{
		name:'School',//一般跟文件名保持一致
		 
		data(){
			return {
				schoolName:'尚硅谷',
				address:'北京昌平'
			}
		},
		methods:{
			showName(){
				alert(this.schoolName)
			}
		},
	}
</script>

<style>
	/* 组建的样式 */
	.demo{
		background-color: orange;
	}
</style>

student.vue

<template>
	<div class="demo">
		<h2>学生姓名:{{name}}</h2>
		<h2>学生年龄:{{age}}</h2>
	</div>
</template>

<script>
	export default{
		name:'Student',//一般跟文件名保持一致
		
		data(){
			return {
				name:'张三',
				age:18
			}
		},
	}
</script>

<style>
</style>

App.vue

<template>
	<div>
		<img src="./assets/logo.png" alt="logo">
		<School></School>
		<Student></Student>
	</div>
</template>

<script>
	//引入组件
	import School from './components/School.vue'
	import Student from './components/Student.vue'
	export default{
		name:'App',
		components:{
			School,
			Student
		}
	}
</script>

<style>
</style>

main.js 

/*
	该文件是整个项目的入口文件
*/

//引入Vue
// 第一种改法,引入完整版本的vue import Vue from 'vue/dist/vue'
import Vue from 'vue'
//引入App组件,它是所有组件的父组件
import App from './App.vue'
//关闭vue的生产提示
Vue.config.productionTip = false

/*
	关于不同版本的Vue:
	
		1.vue.js与vue.runtime.xxx.js的区别:
			(1) vue.js是完整版的vue,包含:核心功能+模板解析器。
			(2) vue.runtime.xxx.js是运行版的Vue,只包含:核心功能:没有模板解析器。
			
		2.因为vue.runtime.xxx.js没有模板解析器,所以不能使用template配置项,
		  需要使用render函数接收到的createElement函数去指定具体内容。
*/

let person = {name:'Tom',age:18,
}

//创建Vue的实例对象 -- vm
new Vue({
	el:'#app',
	//下面这行代码一会解释,完成了这个功能:将App组件放入容器中
   render: h => h(App),
})


2.ref属性

School.vue

<template>
	<div class="school">
		<h2>学校名称:{{name}}</h2>
		<h2>学校地址:{{address}}</h2>
	</div>
</template>

<script>
	export default {
		name:'School',
		data(){
			return{
				name:'尚硅谷',
				address:'北京-昌平'
			}
		}
	}
</script>

<style>
	.school{
		background-color: gray;
	}
</style>

App.vue

<template>
	<div>
		<!-- <h1 v-text="msg" id="title"></h1> -->
		<h1 v-text="msg" ref="title"></h1>
		<button @click="showDOM" ref="btn">点我输出上方的DOM元素</button>
		<School ref="sch"></School>
	</div>
</template>

<script>
	//引入school组件
	import School from './components/School'
	
	export default {
		name:'App',
		data(){
			return {
				msg:'欢迎学习Vue'
			}
		},
		components:{School},
		methods: {
			showDOM(){
				//直接使用原生DOM不太好
				//console.log(document.getElementById('title'))
				console.log(this.$refs.title)
				console.log(this.$refs.sch)
				console.log(this.$refs.btn)
			}
		},
	}
</script>

<style>
	
</style>

main.js 

//引入Vue
import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false

new Vue({
	el:'#app',
	render: h => h(App)
})

3.props配置

Student.vue

<template>
	<div>
		<h1>{{msg}}</h1>
		<h2>学生姓名:{{name}}</h2>
		<h2>学生性别:{{sex}}</h2>
		<h2>学生性年龄:{{age}}</h2>
		<button @click="updateAge">尝试修改收到的年龄</button>
	</div>
</template>

<script>
	export default {
		name:'School',
		data(){
			return{
				msg:'我是你爸爸',
			}
		},
		methods:{
			updateAge(){
				this.age = 22
			}
		},
		//简单声明接收   
		 props:['name','age','sex']
		
		//接收同时对数据进行类型限制
		/*props:{
			name:String,
			age:Number,
			sex:String
		}*/
		
		//接收的同时对数据进行:类型限制+默认值指定+必要性的限制
		/*props:{
			name:{
				type:String,  //name的类型是字符串
				required:true //name必须要传
			},
			age:{
				type:Number,
				default:99  //默认值
			},
			sex:{
				type:String,
				required:true 
			}
		}*/
	}
</script>


App.vue

<template>
	<div>
		<Student name="李四" sex="女" :age="18+1"/>
		<hr>
		<Student name="王五" sex="男" :age="44"/>
	</div>
</template>

<script>
	//引入school组件
	import Student from './components/Student'
	
	export default {
		name:'App',
		components:{Student},
	}
</script>

<style>
	
</style>

main.js

//引入Vue
import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false

new Vue({
	el:'#app',
	render: h => h(App)
})

4.mixin混入

School.vue

<template>
	<div>	
		<h2 @click="showName">学校名称:{{name}}</h2>
		<h2>学校地址:{{address}}</h2>
	</div>
</template>

<script>
	//引入一个混合
	// import {mixin,hunhe} from '../mixin.js'
	export default {
		name:'School',
		data(){
			return{
				name:'尚硅谷',
				address:'北京昌平'
			}
		},
		// mixins:[mixin,hunhe]
		mounted() {
			console.log('你好啊!!!!!')
		}
	}
</script>


Student.vue

<template>
	<div>
		<h2 @click="showName">学生姓名:{{name}}</h2>
		<h2>学生性别:{{sex}}</h2>
	</div>
</template>

<script>
	// import {mixin,hunhe} from '../mixin.js'
	export default {
		name:'Student',
		data(){
			return{
				name:'张三',
				sex:'男'
			}
		},
		// mixins:[mixin,hunhe],
	}
</script>


App.vue

<template>
	<div>
		<Student/>
		<hr>
		<School/>
	</div>
</template>

<script>
	//引入school组件
	import Student from './components/Student'
	import School from './components/School'
	
	export default {
		name:'App',
		components:{Student,School},
	}
</script>

<style>
	
</style>

main.js

//引入Vue
import Vue from 'vue'
import App from './App.vue'
import {mixin,hunhe} from './mixin.js'
Vue.config.productionTip = false
Vue.mixin(hunhe)
Vue.mixin(mixin)
new Vue({
	el:'#app',
	render: h => h(App)
})

mixin.js

export const mixin = {
	methods:{
		showName(){
			alert(this.name)
		}
	},
	mounted(){
		console.log('你好啊')
	},
}
export const hunhe = {
	data() {
		return {
			x:100,
			y:200
		}
	}
}

5.插件

School.vue

<template>
	<div>	
		<h2>学校名称:{{name | mySlice}}</h2>
		<h2>学校地址:{{address}}</h2>
		<button @click="test">点我测试一下hello方法</button>
	</div>
</template>

<script>
	export default {
		name:'School',
		data(){
			return{
				name:'尚硅谷1234',
				address:'北京昌平'
			}
		},
		methods:{
			test(){
				this.hello()
			}
		}
	}
</script>


Student.vue

<template>
	<div>
		<h2>学生姓名:{{name}}</h2>
		<h2>学生性别:{{sex}}</h2>
		<input type="text" v-fbind:value="name" />
	</div>
</template>

<script>
	
	export default {
		name:'Student',
		data(){
			return{
				name:'张三',
				sex:'男'
			}
		},
	}
</script>


App.vue

<template>
	<div>
		<Student/>
		<hr>
		<School/>
	</div>
</template>

<script>
	//引入school组件
	import Student from './components/Student'
	import School from './components/School'
	
	export default {
		name:'App',
		components:{Student,School},
	}
</script>

<style>
	
</style>

main.js

//引入Vue
import Vue from 'vue'
import App from './App.vue'
import plugins from './plugins.js'
Vue.config.productionTip = false

Vue.use(plugins,1,2,3)
new Vue({
	el:'#app',
	render: h => h(App)
})

plugins.js

export default {
	install(Vue,x,y,z){
		console.log('@@@install',Vue)
		console.log(x,y,z)
		//全局过滤器
		Vue.filter('mySlice',function(value){
			return  value.slice(0,5)
		})
		
		//定义全局指令
		Vue.directive('fbind',{
			//指令与元素成功绑定时(一上来)
						bind(element,binding){
							element.value = binding.value
						},
						//指令所在元素被插入页面时
						inserted(element,binding){
							element.focus()
						},
						//指令所在的模板被重新解析时
						update(element,binding){
							element.value = binding.value
							element.focus()
						}
					})
					
		//定义混入
		
		Vue.mixin({
			data(){
				return {
					x:100,
					y:200
				}
			},
		})
	
		//给Vue原型上添加一个方法(vm和vc都能使用了)
		Vue.prototype.hello = ()=>{alert('你好啊')}
	}
}

6.scoped样式

作用功能:

实现组件的私有化,不对全局造成样式污染,表示当前style属性只属于当前模
块虽然方便但是我们需要慎用,因为当我们使用公共组件时会造成很多困难,
增加难度,想知道造成那些难度,需要先从scoped实现原理了解


实现原理:

通过观察DOM结构可以发现:vue通过在DOM结构以及css样式上加上唯一的标记,保证唯一,达到样式私有化,不污染全局的作用,如图,样式属性上也会多一个该字符,以保证唯一


可以看出加上scoped后的组件里的标签都会多一个data-v-469af010的属性,并且在css样式部分可以看出

 

 


由此可知,添加scoped属性的组件,为了达到不污染全局,做了如下处理:

  • 给HTML的DOM节点加一个不重复属性data-v-469af010标志唯一性
  • 在添加scoped属性的组件的每个样式选择器后添加一个等同与“不重复属性”相同的字段,实现类似于“作用域”的作用,不影响全局
  • 如果组件内部还有组件,只会给最外层的组件里的标签加上唯一属性字段,不影响组件内部引用的组件( 注意 )


慎用原因:

其实从原理已经能够了解到慎用原因,这里权当总结

  1. 从原理可见,之所以scoped可达到类似组件私有化、样式设置“作用域”的效果,其实只是在设置scoped属性的组件上的所有标签添加一的data开头的属性,且在标签选择器的结尾加上和属性同样的字段,起到唯一性的作用,但是这样如果组件中也引用其他组建就会出现类似下面的问题:
    1. 父组件无scoped属性,子组件带有scoped,父组件是无法操作子组件的样式的(原因在原理中可知),虽然我们可以在全局中通过该类标签的标签选择器设置样式,但会影响到其他组件
    2. 父组件有scoped属性,子组件无,父组件也无法设置子组件样式,因为父组件的所有标签都会带有data-v-469af010唯一标志,但子组件不会带有这个唯一标志属性,与1同理,虽然我们可以在全局中通过该类标签的标签选择器设置样式,但会影响到其他组件
    3. 父子组建都有,同理也无法设置样式,更改起来增加代码量

所以scoped虽然看似方便但是使用还需谨慎

7.TodoList案例

MyFooter.vue

<template>
	<div class="todo-footer" v-show="total">
	  <label>
	    <!-- <input type="checkbox" :checked="isAll" @change="checkAll"/> -->
		<input type="checkbox" v-model="isAll"/>
	  </label>
	  <span>
	    <span>已完成{{doneTotal}}</span> / 全部{{total}}
	  </span>
	  <button class="btn btn-danger" @click="clearAll">清除已完成任务</button>
	</div>
</template>

<script>
	export default{
		name:'MyFooter',
		props:['todos','checkAllTodo','clearAllTodo'],
		computed:{
			isAll:{
				get(){
					return this.doneTotal === this.total && this.total > 0
				},
				set(value){
					this.checkAllTodo(value)
				}
			},
			total(){
				return this.todos.length
			},
			doneTotal(){
				//简单方法
				// let i = 0
				// this.todos.forEach((todo)=>{
				// 	if(todo.done) i++
				// })
				// return i
				
				/* const x = this.todos.reduce((pre,todo)=>{
					return pre + (todo.done ? 1 : 0)
				},0) */
				return this.todos.reduce((pre,todo)=> pre + (todo.done ? 1 : 0),0)
			}
		},
		methods:{
			// checkAll(e){
			// 	this.checkAllTodo(e.target.checked)
			// }
			clearAll(){
				this.clearAllTodo()
			}
		},
	}
</script>

<style scoped>
	/*footer*/
	.todo-footer {
	  height: 40px;
	  line-height: 40px;
	  padding-left: 6px;
	  margin-top: 5px;
	}
	
	.todo-footer label {
	  display: inline-block;
	  margin-right: 20px;
	  cursor: pointer;
	}
	
	.todo-footer label input {
	  position: relative;
	  top: -1px;
	  vertical-align: middle;
	  margin-right: 5px;
	}
	
	.todo-footer button {
	  float: right;
	  margin-top: 5px;
	}
	
</style>

MyHeader.vue

<template>
	<div class="todo-header">
	  <input type="text" placeholder="请输入你的任务名称,按回车键确认" v-model="title" @keyup.enter="add"/>
	</div>
</template>

<script>
	import {nanoid} from 'nanoid'
	export default{
		name:'MyHeader',
		props:['addTodo'],
		data(){
			return{
				title:''
			}
		},
		methods:{
			add(event){
				//校验数据
				if(!this.title.trim()) return alert('输入不能为空')
				//将用户的输入包装成为一个todo对象
				const todoObj = {
					id:nanoid(),title:this.title,done:false
				}
				//通知APP组件添加一个todo对象
				this.addTodo(todoObj)
				//清空输入
				 this.title = ''
				// console.log(event.target.value)
				// console.log(this.title)
				// console.log(todoObj)
			}
		}
	}
</script>

<style scoped>
	/*header*/
	.todo-header input {
	  width: 560px;
	  height: 28px;
	  font-size: 14px;
	  border: 1px solid #ccc;
	  border-radius: 4px;
	  padding: 4px 7px;
	}
	
	.todo-header input:focus {
	  outline: none;
	  border-color: rgba(82, 168, 236, 0.8);
	  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
	}
</style>

MyItem.vue

<template>
	<li>
	  <label>
	    <input type="checkbox" :checked="todo.done" @change="handleCheck(todo.id)"/>
		<!-- 如下代码也能实现功能,但是不太推荐,因为有点违反原则,因为修改了props -->
	   <!-- <input type="checkbox" v-model="todo.done"> -->
	    <span>{{todo.title}}</span>
	  </label>
	  <button class="btn btn-danger" @click="handleDelete(todo.id)">删除</button>
	</li>
</template>

<script>
	export default{
		name:'MyItem',
		//声明接收todo对象
		props:['todo','checkTodo','deleteTodo'],
		methods:{
			//勾选or取消勾选
			handleCheck(id){
				//通知App组件将对应的todo对象的done值取反
				this.checkTodo(id)
			},
			//删除
			handleDelete(id){
				if(confirm('确定删除么?')){
					//通知App组件将对应的todo选项删除
					this.deleteTodo(id)
				}
			}
		}
	}
</script>

<style scoped>
	/*item*/
	li {
	  list-style: none;
	  height: 36px;
	  line-height: 36px;
	  padding: 0 5px;
	  border-bottom: 1px solid #ddd;
	}
	
	li label {
	  float: left;
	  cursor: pointer;
	}
	
	li label li input {
	  vertical-align: middle;
	  margin-right: 6px;
	  position: relative;
	  top: -1px;
	}
	
	li button {
	  float: right;
	  display: none;
	  margin-top: 3px;
	}
	
	li:before {
	  content: initial;
	}
	
	li:last-child {
	  border-bottom: none;
	}
	
	li:hover{
		background-color: #808080;
	}
	
	li:hover button{
		display: block;
	}
</style>

MyList.vue

<template>
	<ul class="todo-main">
	<MyItem
	 v-for="todoObj in todos" 
	:key="todoObj.id" 
	:todo="todoObj" 
	:checkTodo="checkTodo"
	:deleteTodo="deleteTodo"
	/>
	</ul>
</template>

<script>
	import MyItem from './MyItem'
	export default{
		name:'MyList',
		components:{MyItem},
		props:['todos','checkTodo','deleteTodo']
	}
</script>

<style scoped>
	/*main*/
	.todo-main {
	  margin-left: 0px;
	  border: 1px solid #ddd;
	  border-radius: 2px;
	  padding: 0px;
	}
	
	.todo-empty {
	  height: 40px;
	  line-height: 40px;
	  border: 1px solid #ddd;
	  border-radius: 2px;
	  padding-left: 5px;
	  margin-top: 10px;
	}
</style>

App.vue

<template>
	<div id="root">
	  <div class="todo-container">
	    <div class="todo-wrap">
	     <MyHeader :addTodo="addTodo"/>
	      <MyList :todos="todos" :checkTodo="checkTodo" :deleteTodo="deleteTodo"/>
	      <MyFooter :todos="todos" :checkAllTodo="checkAllTodo" :clearAllTodo="clearAllTodo"/>
	    </div>
	  </div>
	</div>

</template>

<script>
	import MyHeader from './components/MyHeader'
	import MyList from './components/MyList'
	import MyFooter from './components/MyFooter'
	
	
	export default {
		name:'App',
		components:{MyHeader,MyFooter,MyList},
		data(){
			return {
				todos:[
					{id:'001',title:'抽烟',done:false},
					{id:'003',title:'开车',done:false},
					{id:'002',title:'喝酒',done:false},
					
				]
			}
		},
		methods:{
			//添加一个TODO
			addTodo(todoObj){
				this.todos.unshift(todoObj)
			},
			//勾选or取消勾选一个TODO
			checkTodo(id){
				this.todos.forEach((todo)=>{
					if(todo.id == id) todo.done = !todo.done
				})
			},
			//删除一个todo
			deleteTodo(id){
				this.todos = this.todos.filter((todo)=>{
					return todo.id !== id
				})
			},
			//全选or取消全选
			checkAllTodo(done){
				this.todos.forEach((todo)=>{
					todo.done = done
				})
			},
			//清楚所有已经完成的todo
			clearAllTodo(){
				this.todos = this.todos.filter((todo)=>{
					return !todo.done
				})
			}
		}
	}
</script>

<style>
	/*base*/
	body {
	  background: #fff;
	}
	
	.btn {
	  display: inline-block;
	  padding: 4px 12px;
	  margin-bottom: 0;
	  font-size: 14px;
	  line-height: 20px;
	  text-align: center;
	  vertical-align: middle;
	  cursor: pointer;
	  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
	  border-radius: 4px;
	}
	
	.btn-danger {
	  color: #fff;
	  background-color: #da4f49;
	  border: 1px solid #bd362f;
	}
	
	.btn-danger:hover {
	  color: #fff;
	  background-color: #bd362f;
	}
	
	.btn:focus {
	  outline: none;
	}
	
	.todo-container {
	  width: 600px;
	  margin: 0 auto;
	}
	
	.todo-container .todo-wrap {
	  padding: 10px;
	  border: 1px solid #ddd;
	  border-radius: 5px;
	}
	
</style>

main.js

//引入Vue
import Vue from 'vue'
import App from './App.vue'
Vue.config.productionTip = false

new Vue({
	el:'#app',
	render: h => h(App)
})

8.浏览器本地存储 

LocalStorage

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>localStorage</title>
	</head>
	<body>
		<!-- storage n. 存储,仓库 -->
		
		<h2>localStorage</h2>
		<button onclick="saveData()">点我保存一个数据</button>
		<button onclick="readData()">点我读取一个数据</button>
		<button onclick="deleteData()">点我删除一个数据</button>
		<button onclick="deleteAllData()">点我清空一个数据</button>
		
		<script type="text/javascript">
			let p = {name:'张三',age:18};
		
			function saveData(){
				localStorage.setItem('msg','hello!');
				localStorage.setItem('msg2',666);
				localStorage.setItem('person',JSON.stringify(p));
			}
			function readData(){
				console.log(localStorage.getItem('msg'));
				console.log(localStorage.getItem('msg2'));
				const result = localStorage.getItem('person');  //如果result是null,控制台输出也是null。
				console.log(JSON.parse(result));
				
				console.log(localStorage.getItem('msg4')) // null
			}
			function deleteData(){
				localStorage.removeItem('msg2');
			}
			function deleteAllData(){
				localStorage.clear();
			}
		</script>
	</body>
</html>

SessionStorage

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>sessionStorage</title>
	</head>
	<body>
		<h2>sessionStorage</h2>
		<button onclick="saveData()">点我保存一个数据</button>
		<button onclick="readData()">点我读取一个数据</button>
		<button onclick="deleteData()">点我删除一个数据</button>
		<button onclick="deleteAllData()">点我清空一个数据</button>
		
		<script type="text/javascript">
			let p = {name:'张三',age:18};
		
			function saveData(){
				sessionStorage.setItem('msg','hello!');
				sessionStorage.setItem('msg2',666);
				sessionStorage.setItem('person',JSON.stringify(p));
			}
			function readData(){
				console.log(sessionStorage.getItem('msg'));
				console.log(sessionStorage.getItem('msg2'));
				const result = sessionStorage.getItem('person');  //如果result是null,控制台输出也是null。
				console.log(JSON.parse(result));
				
				console.log(sessionStorage.getItem('msg4')) // null
			}
			function deleteData(){
				sessionStorage.removeItem('msg2');
			}
			function deleteAllData(){
				sessionStorage.clear();
			}
		</script>
	</body>
</html>

笔记

脚手架文件结构

├── node_moudles
├── public
|    ├── ├── favicon.ico: 页签图标
|    └── index.html: 主页面
├── src
|    ├── assets: 存放经他自愿
|    |   └── logo.png
|    ├── conponent: 存放组件
|    |   └── HelloWorld.vue
|    ├── App.vue: 汇总所有组件
|    ├── main.js: 入口文件
├── .gitignore: git版本管制忽略的配置
├── .babel.config.js: babel的配置文件
├── .package.json: 应用包配置文件
├── .README.md: 应用描述文件
├── .pacage-lock.json: 包版本控制文件

关于不同版本的Vue:

1.vue.js与vue.runtime.xxx.js的区别:
    (1) vue.js是完整版的vue,包含:核心功能+模板解析器。
    (2) vue.runtime.xxx.js是运行版的Vue,只包含:核心功能:没有模板解析器。
        
2.因为vue.runtime.xxx.js没有模板解析器,所以不能使用template配置项,
      需要使用render函数接收到的createElement函数去指定具体内容。

vue.config.js配置文件

使用vue inspect > output.js 可以查看Vue脚手架的默认配置。
使用vue.config.js可以对脚手架进行个性化定制,详情见: https://cli.vuejs.org/zh

ref属性

1.被用来给元素或子组件注册引用信息(id的替代者)
2.应用在html标签上获取的是真实DOM元素,应用在组件标签上时组件实例对象(vc)
3.使用方式:
    打标识:<h1 ref="xxx">.....</h1>  或 <School ref="xxx"></School>
    获取:this.$refs.xxx

配置项props

    功能:让组件接收外部传过来的数据
        (1).传递数据:
            <Demo name="xxx">
        (2).接收数据:
            第一种方式(只接收):
                props:['name']
            第二种方式(限制类型):
                props:{
                    name:Number
                }
            第三种方式(限制类型、限制必要性、指定默认值):
                props:{
                    name:{
                        type:String,    //类型
                        required:true,  //必要性
                        default:'老王'  //默认值
                    }
                }
    备注:props是只读的,Vue底层会监测你对props的修改,如果进行了修改,就会发出警告,若业务需求确实需要修改,
    那么请复制props的内容到data中一份,然后去修改data中的数据。

mixin(混入)

功能:可以把多个组件共用的配置提取成一个混入对象
使用方式:
    第一部以定义混合,例如:
        {
            data(){...},
            methods{....}
            ....
        }
    第二步使用混合,例如:
        (1) 全局混入: Vue.mixin(xxx)
        (2) 局部混入: mixins:['xxx']
备注:如果使用data中的数据,methods中的方法冲突了,按照组件中的来,不破坏代码
    对于生命周期的钩子函数来说,混合的钩子函数在前,组件的在后。

插件

功能:用于增强Vue
本质:包含install方法的一个对象,install的第一个参数是Vue,第二个以后的参数是插件使用者传递的数据。
定义插件:对象.install = function(Vue options){
    // 1. 添加全局过滤器
    Vue.filter(....)
    
    // 2. 添加全局指令
    Vue.directive(....)
    
    // 3. 配置全局混入
    Vue.mixin(....)
    
    // 4. 添加实例方法
    Vue.prototype.$myMethod = function (){...}
    Vue.prototype.$myProperty = xxxx
}
使用插件: Vue.use()

scoped样式

作用:让样式在局部生效,防止冲突
写法:<style scoped>
  • assets文件夹一般放的是前端的静态资源(视频,图片,音频)

Todo-List案例

  • 组件化编码流程(通用) (1).拆分静态组件:组件要按照功能点拆分,命名不要与html元素冲突。 (2).实现动态组件:考虑好数据的存放位置,数据是一个组件再用,还是一些组件再用。 1).一个组件在用:放在组件自身即可。

    2).一些组件在用:放在他们共同的父组件上(状态提升) (3).实现交互:从绑定事件开始

  • props适用于 (1).父组件 => 子组件 通信 (2).子组件 => 父组件 通信(要求父先给子一个函数)

  • 使用v-model时要切记:v-model绑定的值不能是props传过来的值,因为props是不可以修改的!

  • props传过来若是对象类型的值,修改对象中的属性时Vue不会报错,但不推荐这样做。

webstorage

  1. 存储内容大小一般支持5MB左右(不同浏览器可能还不一样)

  2. 浏览器通过Windows.sessionStorage和Windows.localStorage属性来实现本地存储机制。

  3. 相关API

    1. xxxxxStorage.setItem('key','value'); 该方法接受一个键和值作为参数,会把键值对添加到存储中,如果键名存在,则更新其对应的值。

    2. xxxxxStorage.getItem('key','value'); 该方法接受一个键名作为参数,返回键名对应的值。

    3. xxxxxStorage.removeItem('key','value'); 该方法接受一个键名作为参数,并把该键名对应的键值从存储中删除。

    4. xxxxxStorage.clear(); 该方法会清空存储中的所有数据。

  4. 备注:

    1. SessionStorage存储的内容会随着浏览器窗口关闭而消失。

    2. LocalStorage存储的内容,需要手动清除才会消失。

    3. xxxxxStorage.setItem(xxx)如果xxx地赢得value获取不到,namegetItem的返回值是null。

    4. JSON.parse(null)的结果依然是null。

    5. Storage n. 存储,仓库

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值