05 [Binding Style Conditional Rendering List Rendering]

1. Binding styles

1.1 class style

The writing method :class=xxxxxx can be a string, an object, or an array.
So it is divided into three ways of writing: string writing, object writing, and array writing.

1.1.1 String writing

String notation applies to:The class name is not sure, it needs to be obtained dynamically

<style>
	.normal{
      
      
        background-color: skyblue;
    }
</style>

<!-- 准备好一个容器-->
<div id="root">
    <!-- 绑定class样式--字符串写法,适用于:样式的类名不确定,需要动态指定 -->
    <div class="basic" :class="mood" @click="changeMood">{
   
   {name}}</div>
</div>

<script>
	const vm = new Vue({
      
      
        el:'#root',
        data:{
      
      
            mood:'normal'
        }
    })
</script>

1.1.2 Array writing

Array writing applies to:To bind multiple styles, the number is uncertain, and the name is also uncertain

<style>
    .lktest1{
      
      
        background-color: yellowgreen;
    }
    .lktest2{
      
      
        font-size: 30px;
        text-shadow:2px 2px 10px red;
    }
    .lktest3{
      
      
        border-radius: 20px;
    }
</style>

<!-- 准备好一个容器-->
<div id="root">
    <!-- 绑定class样式--数组写法,适用于:要绑定的样式个数不确定、名字也不确定 -->
	<div class="basic" :class="classArr">{
   
   {name}}</div>
</div>

<script>
	const vm = new Vue({
      
      
        el:'#root',
        data:{
      
      
            classArr: ['lktest1','lktest2','lktest3']
       }
    })
</script>

1.1.3 Object writing

Object notation applies to:To bind multiple styles, the number is determined and the name is determined, but it is not sure whether to use it or not

<style>
    .lktest1{
      
      
        background-color: yellowgreen;
    }
    .lktest2{
      
      
        font-size: 30px;
        text-shadow:2px 2px 10px red;
    }
</style>

<!-- 准备好一个容器-->
<div id="root">
    <!-- 绑定class样式--对象写法,适用于:要绑定的样式个数确定、名字也确定,但要动态决定用不用 -->
	<div class="basic" :class="classObj">{
   
   {name}}</div>
</div>

<script>
	const vm = new Vue({
      
      
        el:'#root',
        data:{
      
      
            classObj:{
      
      
                lktest1:false,
                lktest2:false,
			}
        }
    })
</script>

1.2 style style

There are two ways of writing, object writing, array writing

1.2.1 Object writing

<!-- 准备好一个容器-->
<div id="root">
    <!-- 绑定style样式--对象写法 -->
	<div class="basic" :style="styleObj">{
   
   {name}}</div>
</div>

<script>
	const vm = new Vue({
      
      
        el:'#root',
        data:{
      
      
            styleObj:{
      
      
                fontSize: '40px',
                color:'red',
			}
        }
    })
</script>

1.2.2 Array writing

<!-- 准备好一个容器-->
<div id="root">
    <!-- 绑定style样式--数组写法 -->
	<div class="basic" :style="styleArr">{
   
   {name}}</div>
</div>

<script>
	const vm = new Vue({
      
      
        el:'#root',
        data:{
      
      
            styleArr:[
                {
      
      
                    fontSize: '40px',
                    color:'blue',
                },
                {
      
      
                    backgroundColor:'gray'
                }
            ]
        }
    })
</script>

2. Conditional rendering

2.1 v-if

  • Writing:
    • v-if= "expression"
    • v-else-if= "expression"
    • v-else
  • Applicable to: scenes with low switching frequency , because the DOM elements that are not displayed are directly removed
  • Features: Because the DOM elements that are not displayed are directly removed
  • Note: v-ifcan be used together with, but requires that the structure cannot be v-else-if" interrupted "v-else
  • templateThe label does not affect the structure, there will be no such label in the page html, but it can only be used with v-if , not v-show
!-- 准备好一个容器-->
<div id="root">
    <!-- 使用v-if做条件渲染 -->
    <h2 v-if="false">欢迎来到{
   
   {name}}</h2>
    <h2 v-if="1 === 1">欢迎来到{
   
   {name}}</h2>
    
    
    <!-- v-else和v-else-if -->
    <div v-if="n === 1">Angular</div>
    <div v-else-if="n === 2">React</div>
    <div v-else-if="n === 3">Vue</div>
    <div v-else>哈哈</div>
    
    
    <!-- v-if与template的配合使用 -->
    <!-- 就不需要写好多个判断,写一个就行 -->
    <!-- 这里的思想就像事件代理的使用 -->
    <template v-if="n === 1">
        <h2>你好</h2>
        <h2>上海</h2>
        <h2>北京</h2>
    </template>
</div>

<script>
	const vm = new Vue({
      
      
        el:'#root',
        data:{
      
      
            styleArr:[
                {
      
      
                    fontSize: '40px',
                    color:'blue',
                },
                {
      
      
                    backgroundColor:'gray'
                }
            ]
        }
    })
</script>

2.2 v-show

  • Writing: v-show="expression"
  • Applicable to: Scenes with high switching frequency
  • Features: The DOM elements that are not displayed are not removed, they are just hidden using styles ( display:none)
  • Remarks: v-ifWhen using it, the element may not be available, but v-showit must be available when using it. v-if is to change the element actually dom, and v-show is to hide or display domthe element
<!-- 准备好一个容器-->
<div id="root">
    <!-- 使用v-show做条件渲染 -->
    <h2 v-show="false">欢迎来到{
   
   {name}}</h2>
    <h2 v-show="1 === 1">欢迎来到{
   
   {name}}</h2>
</div>

3. List rendering

3.1 v-for directive

  • Display list data with one
  • Grammar: v-for= (item, index)in xxx:key`= "yyy" , where the key can be index, better is the unique identifier of the traversal object, if the key is written as index, it can be used without writing index in front
  • Traversable: array, object, string (rarely used), specified number of times (rarely used)
<title>基本列表</title>
<script type="text/javascript" src="../js/vue.js"></script>

<div id="root">
  <!-- 遍历数组 -->
  <h3>人员列表(遍历数组)</h3>
  <ul>
    <li v-for="(p,index) of persons" :key="index">{
   
   { p.name }}-{
   
   { p.age }}</li>
  </ul>

  <!-- 遍历对象 -->
  <h3>汽车信息(遍历对象)</h3>
  <ul>
    <li v-for="(value,k) of car" :key="k">{
   
   { value }}--{
   
   { k }}</li>
  </ul>

  <!-- 遍历字符串 -->
  <h3>测试遍历字符串(用得少)</h3>
  <ul>
    <li v-for="(char,index) of str" :key="index">{
   
   { char }}-{
   
   { index }}</li>
  </ul>

  <!-- 遍历指定次数 -->
  <h3>测试遍历指定次数(用得少)</h3>
  <ul>
    <li v-for="(number,index) of 5" :key="index">{
   
   { number }}--{
   
   { index }}</li>
  </ul>
</div>

<script type="text/javascript">
  Vue.config.productionTip = false
  new Vue({
      
      
    el: '#root',
    data: {
      
      
      persons: [
        {
      
       id: '001', name: '张三', age: 18 },
        {
      
       id: '002', name: '李四', age: 19 },
        {
      
       id: '003', name: '王五', age: 20 }
      ],
      car: {
      
      
        name: '奥迪A8',
        price: '70万',
        color: '黑色'
      },
      str: 'hello'
    }
  })
</script>

3.2 The function and principle of key

  1. What is the function of the key in vue? (The internal principle of key)
    is the virtual dom in vue. Vue will generate virtual dom according to the data in data. If it is the first time to generate a page, it will convert virtual dom into real dom and display it on the page.
  2. What is the use of virtual dom?
    Every time the data in vm._data changes, it will trigger the generation of a new virtual dom, and the new virtual dom will be compared with the old virtual dom. If there is the same, when it becomes a real dom, this part of the same part does not need to be recreated. To generate, you only need to convert the different dom between the two into real dom, and then splicing with the original real dom. My understanding is that virtual dom plays a role of dom reuse, and avoids repeated redundant operations, which are explained in detail below.
  3. And what is the use of the key?
    key is the identity of the virtual dom.
    Let’s start with some preliminary knowledge: what is real DOM? What is the difference between real DOM and virtual DOM? How to use code to display real DOM and virtual DOM

Real DOM and its parsing process

Here is a reference to the superhero boss: https://juejin.cn/post/6844903895467032589

webkitRendering engine workflow flow chart
insert image description here
All browser rendering engine workflows are roughly divided into 5 steps: create DOMtree —> create Style Rules—> build Rendertree —> layout Layout—> draw Painting.

  • The first step is to build a DOM tree: when the browser receives the HTML document responded from the server, it will traverse the document nodes to generate a DOM tree. It should be noted that during the process of DOM tree generation, it may be blocked by the loading and execution of CSS and JS. Rendering blocking will be mentioned below.

  • The second step is to generate a style sheet: use a CSS analyzer to analyze the inline style on CSS files and elements, and generate a style sheet for the page;

  • Render blocking: When the browser encounters a script tag, DOM construction will pause until the script is loaded and executed, and then continue to build the DOM tree. Every time a Javascript script is executed, it will seriously block the construction of the DOM tree. If the JavaScript script also operates the CSSOM, but the CSSOM is not downloaded and constructed, the browser will even delay script execution and DOM construction until the CSSOM is downloaded and constructed. Therefore, the introduction of script tags is very important, and the following two principles can be followed in actual use:

    • css priority: in the order of introduction, css resources precede js resources

    • js back: js code is placed at the bottom, and js should affect DOM construction as little as possible

      There is also a little knowledge: when parsing html, new elements will be inserted into the dom tree, and css will be searched at the same time, and then the corresponding style rules will be applied to the elements. The search style sheet is matched in order from right to left For example: div p {...}, it will first search for all p tags and determine whether its parent tag is a div before deciding whether to use this style of rendering. So usually write css as much as possible with class or id, don't over-cascade

  • The third step is to build the rendering tree: we can build the rendering tree through the DOM tree and CSS rules. The browser will traverse each visible node (note that it is a visible node) from the root node of the DOM tree to each visible node, find its adapted CSS rule and apply it. After the rendering tree is built, each node is a visible node and contains its content and corresponding rule styles. This is also the biggest difference between the rendering tree and the DOM tree. Rendering is for display, and those invisible elements will not appear in this tree. In addition, elements with display none will not be displayed in this tree. Elements with visibility hidden will appear in this tree.

  • The fourth step is to render the layout : the layout stage will traverse from the root node of the rendering tree, and then determine the exact size and position of each node object on the page. The output of the layout stage is a box model, which will accurately capture each The exact position and size of the element within the screen.

  • Step 5: Rendering tree drawing : In the drawing phase, the rendering tree is traversed, and the renderer's paint() method is called to display its content on the screen. The drawing of the rendering tree is done by the browser's UI backend components.

important point:

1. DOMDoes the construction of the tree start when the document is loaded? Building DOMthe tree is a gradual process. In order to achieve a better user experience, the rendering engine will display the content on the screen as soon as possible. It does not have to wait until the entire HTMLdocument is parsed before starting to build renderthe tree and layout.

2. RenderThe tree DOMis CSSbuilt after the tree and the style sheet are built? These three processes are not completely independent when they are actually carried out, but there will be crossover, and they will be loaded, parsed, and rendered at the same time.

3. CSSWhat are the points for attention in the analysis? CSSThe parsing is reversed from right to left, the more nested tags, the slower the parsing.

4. What is the realJS price of the operation ? DOM**The traditional DOM structure operation method has a great impact on performance. The reason is that frequent operations on the DOM structure will cause page reflow and repaint, and the browser has to frequently calculate the layout, rearrange and draw Page elements, causing the browser to generate huge performance overhead. The real performance of direct manipulation DOMis particularly poor, we can demonstrate it again.

<div id="app"></div>
<script>
    // 获取 DIV 元素
    let box = document.querySelector('#app');
    console.log(box);

    // 真实 DOM 操作
    console.time('a');
    for (let i = 0; i <= 10000; i++) {
      
      
        box.innerHTML = i;
    }
    console.timeEnd('a');

    // 虚拟 DOM 操作
    let num = 0;
    console.time('b');
    for (let i = 0; i <= 10000; i++) {
      
      
        num = i;
    }
    box.innerHTML = num;
    console.timeEnd('b');

</script>

3.3.1 Benefits of Virtual DOM

Virtual DOMis designed to solve browser performance problems. As before, if there are 10 DOMupdate , the virtual DOMwill not operate immediately DOM, but save diffthe content to a local JSobject, and finally put this JSobject attchon DOMthe tree at one time, and then perform subsequent operations , to avoid a large amount of unnecessary calculations. Therefore, the advantage of using JSobject simulation DOMnode is that the update of the page can be reflected on JSthe object DOM, and the speed of operating JSthe object is obviously faster. After the update is completed, the final JSobject is mapped to the real object DOM, to be drawn by the browser.

​ While this is one advantage that a virtual DOM brings, it's not the whole story. The biggest advantage of virtual DOM is that it abstracts the original rendering process and realizes cross-platform capabilities. It is not limited to the browser's DOM. It can be the native component of Android and IOS, it can be a very popular small program recently, or it can be Is a variety of GUI.

​ Back to the original question, what exactly is virtual DOM? To put it simply, it is an ordinary JavaScript object, which contains three attributes tag: , props, and .children

3.3.2 The role of key in virtual DOM

The key is the identifier of the virtual DOM object. When the data changes, Vue will generate a [new virtual DOM] according to the [new data], and then Vue will compare the difference between the [new virtual DOM] and the [old virtual DOM]. The comparison rules are as follows :

  • The same key as the new virtual DOM is found in the old virtual DOM:
    • ①. If the content in the virtual DOM has not changed, use the previous real DOM directly!
    • ②. If the content in the virtual DOM changes, a new real DOM is generated, and then the previous real DOM in the page is replaced.
  • The same key as the new virtual DOM was not found in the old virtual DOM
    • Create new real DOM, then render to the page.

3.3.3 Possible problems caused by using index as key

If you perform operations on the data: adding in reverse order, deleting in reverse order, etc.:
there will be unnecessary real DOM updates ==> the interface effect is fine, but the efficiency is low.

case

<!-- 准备好一个容器-->
<div id="root">
    <!-- 遍历数组 -->
    <h2>人员列表(遍历数组)</h2>
    <button @click.once="add">添加一个老刘</button>
    <ul>
        <li v-for="(p,index) of persons" :key="index">
            {
   
   {p.name}}-{
   
   {p.age}}
            <input type="text">
        </li>
    </ul>
</div>

<script type="text/javascript">
	Vue.config.productionTip = false

	new Vue({
      
      
		el: '#root',
		data: {
      
      
			persons: [
				{
      
       id: '001', name: '张三', age: 18 },
				{
      
       id: '002', name: '李四', age: 19 },
				{
      
       id: '003', name: '王五', age: 20 }
			]
		},
		methods: {
      
      
			add() {
      
      
				const p = {
      
       id: '004', name: '老刘', age: 40 }
				this.persons.unshift(p)
			}
		},
	});
</script>

explain

Initial data

persons: [
{ id: '001', name: 'Zhang San', age: 18 },
{ id: '002', name: 'Li Si', age: 19 },
{ id: '003', name: 'Wang Wu', age: 20 }
]

Vue generates virtual DOM
initial virtual DOM based on data

<li key='0'>张三-18<input type="text"></li>
<li key='1'>李四-19<input type="text"></li>
<li key='2'>王五-20<input type="text"></li>

Convert virtual DOM to real DOM and add { id: '004', name: 'Old Liu', age: 40 } new data
insert image description here
this.persons.unshift({ id: '004', name: '老刘', age: 40 })
at the front of the persons array :

persons: [
		{
    
     id: '004', name: '老刘', age: 40 },
		{
    
     id: '001', name: '张三', age: 18 },
		{
    
     id: '002', name: '李四', age: 19 },
		{
    
     id: '003', name: '王五', age: 20 }
]

Vue generates virtual DOM
new virtual DOM based on data

<li key='0'>老刘-30<input type="text"></li>
<li key='1'>张三-18<input type="text"></li>
<li key='3'>李四-19<input type="text"></li>
<li key='4'>王五-20<input type="text"></li>

Convert the virtual DOM to the real DOM
insert image description here
because Lao Liu was inserted into the first one, and the value of the key was reset. The vue Diff algorithm judges that all the virtual DOM has changed according to the value of the key, and then regenerates a new real DOM. In fact, Zhang San, Li Si, and Wang Wu have not changed, and they can directly reuse the previous real DOM, but because of the disorder of the key, they all have to be regenerated, resulting in a waste of performance .
If the structure also contains the DOM of the input class:
it will generate an error DOM update ==> There is a problem with the interface.

This time the result is not a waste of performance, it will directly lead to page errors

image-20220628124642025

3.3.4 Summary

  • It is best to use the unique identifier of each piece of data as the key, such as unique values ​​such as id, mobile phone number, ID number, student number, etc.
  • If there are no reverse sequence operations such as adding and deleting data in reverse order, it is only used to render the list for display, and there is no problem with using index as the key

insert image description here
insert image description here

3.3 List filtering

3.3.1 watch realization

<div id="root">
  <h2>人员列表</h2>
  <input type="text" placeholder="请输入名字" v-model="keyWord">
  <ul>
    <li v-for="(p,index) of filPersons" :key="p.id">
      {
   
   { p.name }}-{
   
   { p.age }}-{
   
   { p.sex }}
    </li>
  </ul>
</div>

<script type="text/javascript">
  Vue.config.productionTip = false
  // 用 watch 实现 
   new Vue({
      
      
			el: '#root',
			data: {
      
      
				keyWord: '',
				persons: [
					{
      
       id: '001', name: '马冬梅', age: 19, sex: '女' },
					{
      
       id: '002', name: '周冬雨', age: 20, sex: '女' },
					{
      
       id: '003', name: '周杰伦', age: 21, sex: '男' },
					{
      
       id: '004', name: '温兆伦', age: 22, sex: '男' }
				],
				filPersons: []
			},
			watch: {
      
      
				keyWord: {
      
      
					immediate: true,
					handler(val) {
      
      
						this.filPersons = this.persons.filter((p) => {
      
      
							return p.name.indexOf(val) !== -1
						})
					}
				}
			}
		}) 
</script>

Note: indexOfThe result for an empty string is 0, so the initial filtering of the above code is all data

3.3.2 Computed implementation

<div id="root">
  <h2>人员列表</h2>
  <input type="text" placeholder="请输入名字" v-model="keyWord">
  <ul>
    <li v-for="(p,index) of filPersons" :key="p.id">
      {
   
   { p.name }}-{
   
   { p.age }}-{
   
   { p.sex }}
    </li>
  </ul>
</div>

<script type="text/javascript">
  Vue.config.productionTip = false
  // 用 computed 实现
  new Vue({
      
      
    el: '#root',
    data: {
      
      
      keyWord: '',
      persons: [
        {
      
       id: '001', name: '马冬梅', age: 19, sex: '女' },
        {
      
       id: '002', name: '周冬雨', age: 20, sex: '女' },
        {
      
       id: '003', name: '周杰伦', age: 21, sex: '男' },
        {
      
       id: '004', name: '温兆伦', age: 22, sex: '男' }
      ]
    },
    computed: {
      
      
      filPersons() {
      
      
        return this.persons.filter((p) => {
      
      
          return p.name.indexOf(this.keyWord) !== -1
        })
      }
    }
  }) 
</script>

3.4 List sorting

Sometimes in order to reduce the pressure on the server, what can be done on the front end is done as much as possible on the front end.

<div id="root">
  <h2>人员列表</h2>
  <input type="text" placeholder="请输入名字" v-model="keyWord">
  <button @click="sortType = 2">年龄升序</button>
  <button @click="sortType = 1">年龄降序</button>
  <button @click="sortType = 0">原顺序</button>
  <ul>
    <li v-for="(p,index) of filPersons" :key="p.id">
      {
   
   {p.name}}-{
   
   {p.age}}-{
   
   {p.sex}}
      <input type="text">
    </li>
  </ul>
</div>

<script type="text/javascript">
  Vue.config.productionTip = false
  new Vue({
      
      
    el: '#root',
    data: {
      
      
      keyWord: '',
      sortType: 0, // 0原顺序 1降序 2升序
      persons: [
        {
      
       id: '001', name: '马冬梅', age: 30, sex: '女' },
        {
      
       id: '002', name: '周冬雨', age: 31, sex: '女' },
        {
      
       id: '003', name: '周杰伦', age: 18, sex: '男' },
        {
      
       id: '004', name: '温兆伦', age: 19, sex: '男' }
      ]
    },
    computed: {
      
      
      filPersons() {
      
      
        const arr = this.persons.filter((p) => {
      
      
          return p.name.indexOf(this.keyWord) !== -1
        })
        //判断一下是否需要排序
        if (this.sortType) {
      
      
          arr.sort((p1, p2) => {
      
      
            return this.sortType === 1 ? p2.age - p1.age : p1.age - p2.age
          })
        }
        return arr
      }
    }
  })
</script>

Guess you like

Origin blog.csdn.net/Instanceztt/article/details/130999949